package org.netbeans.gradle.project.properties;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Assume;
import org.junit.Test;
import org.netbeans.gradle.project.api.config.ConfigPath;
import org.netbeans.gradle.project.api.config.ConfigTree;
import static org.junit.Assert.*;
public class ConfigTreeTest {
private final AtomicReference<Boolean> basicBuilderWorks = new AtomicReference<>(null);
private void assumeBasicBuilderWorks() {
Boolean works = basicBuilderWorks.get();
if (works == null) {
works = false;
try {
testBasicBuilder();
works = true;
} catch (Throwable ex) {
}
basicBuilderWorks.compareAndSet(null, works);
}
Assume.assumeTrue(works);
}
private void verifyTrivial(ConfigTree tree) {
assertSame(tree, tree.getDeepChildTree(ConfigPath.ROOT));
assertSame(tree, tree.getDeepChildTree(new String[0]));
}
private void verifyNoChildren(ConfigTree tree) {
assertTrue("tree.childTrees.isEmpty", tree.getChildTrees().isEmpty());
assertSame(ConfigTree.EMPTY, tree.getChildTree("key2"));
assertSame(ConfigTree.EMPTY, tree.getDeepChildTree("key1"));
assertSame(ConfigTree.EMPTY, tree.getDeepChildTree("key1", "key2"));
}
private void verifyNoValue(ConfigTree tree) {
assertNull(tree.getValue(null));
assertEquals("my-default", tree.getValue("my-default"));
}
private void verifyValue(ConfigTree tree, String value) {
if (value == null) {
verifyNoValue(tree);
}
else {
assertEquals(value, tree.getValue(null));
assertEquals(value, tree.getValue("WRONG-" + value));
}
}
private void verifyEmpty(ConfigTree tree) {
verifyNoValue(tree);
assertFalse("ConfigTree.hasValues", tree.hasValues());
verifyNoChildren(tree);
verifyTrivial(tree);
}
private void verifyValueWithoutChildren(ConfigTree tree, String value) {
assertEquals("tree.hasValues", value != null, tree.hasValues());
verifyValue(tree, value);
verifyNoChildren(tree);
verifyTrivial(tree);
}
@Test
public void testEmptyConstant() {
verifyEmpty(ConfigTree.EMPTY);
}
@Test
public void testSingleValueByBuilder() {
final String value = "my-value";
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.setValue(value);
ConfigTree tree = builder.create();
assertTrue(tree.hasValues());
verifyValue(tree, value);
verifyNoChildren(tree);
}
@Test
public void testSingleValueByFactoryNull() {
assertSame(ConfigTree.EMPTY, ConfigTree.singleValue(null));
}
@Test
public void testSingleValueByFactory() {
final String value = "my-value";
ConfigTree tree = ConfigTree.singleValue(value);
assertTrue(tree.hasValues());
verifyValue(tree, value);
verifyNoChildren(tree);
}
private static <K, E> E getSingle(Map<K, List<E>> map, K key) {
List<E> values = map.get(key);
if (values == null) {
throw new AssertionError("Expected to have key: " + key);
}
if (values.size() != 1) {
fail("Expected to have exactly one value for key " + key + " instead of " + values.size());
}
return values.get(0);
}
@Test
public void testBasicBuilder() {
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.setValue("my-value");
ConfigTree.Builder childBuilder = builder.getChildBuilder("child-key0");
childBuilder.setValue("deep-value");
ConfigTree.Builder childChildBuilder = builder.getDeepChildBuilder("child-key1", "child-key2");
childChildBuilder.setValue("deeper-value");
builder.addChildBuilder("list-key").setValue("list-value0");
builder.addChildBuilder("list-key").setValue("list-value1");
ConfigTree tree = builder.create();
verifyTrivial(tree);
assertTrue(tree.hasValues());
verifyValue(tree, "my-value");
Map<String, List<ConfigTree>> childTrees = tree.getChildTrees();
assertEquals(3, childTrees.size());
List<ConfigTree> childList = childTrees.get("list-key");
assertEquals(2, childList.size());
verifyValueWithoutChildren(childList.get(0), "list-value0");
verifyValueWithoutChildren(childList.get(1), "list-value1");
ConfigTree childTree1 = getSingle(childTrees, "child-key0");
verifyValueWithoutChildren(childTree1, "deep-value");
ConfigTree childTree2 = getSingle(childTrees, "child-key1");
assertTrue(childTree2.hasValues());
verifyTrivial(childTree2);
verifyNoValue(childTree2);
Map<String, List<ConfigTree>> childChildTrees = childTree2.getChildTrees();
assertEquals(1, childChildTrees.size());
ConfigTree childTree3 = getSingle(childChildTrees, "child-key2");
verifyValueWithoutChildren(childTree3, "deeper-value");
}
private ConfigTree getSinglePath(String value, String... path) {
assumeBasicBuilderWorks();
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.getDeepChildBuilder(path).setValue(value);
return builder.create();
}
@Test
public void testDeepBuilderWithPath() {
ConfigTree expected = getSinglePath("my-value", "key1", "key2");
ConfigPath path = ConfigPath.fromKeys("key1", "key2");
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.getDeepChildBuilder(path).setValue("my-value");
assertEquals(expected, builder.create());
}
@Test
public void testDeepBuilderWithKeys() {
ConfigTree expected = getSinglePath("my-value", "key1", "key2");
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.getDeepChildBuilder("key1", "key2").setValue("my-value");
assertEquals(expected, builder.create());
}
@Test
public void testModifyAfterDetach1() {
ConfigTree expected = getSinglePath("my-value", "key1", "key2");
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.detachChildTreeBuilders();
builder.getDeepChildBuilder("key1", "key2").setValue("my-value");
assertEquals(expected, builder.create());
}
@Test
public void testModifyAfterDetach2() {
ConfigTree expected = getSinglePath("my-value", "key1");
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.detachChildTreeBuilders();
builder.getChildBuilder("key1").setValue("my-value");
assertEquals(expected, builder.create());
}
@Test
public void testModifyAfterDetach3() {
ConfigTree expected = getSinglePath("my-value", "key1");
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.detachChildTreeBuilders();
builder.setChildTree("key1", expected.getChildTree("key1"));
assertEquals(expected, builder.create());
}
@Test
public void testModifyValueAfterDetach() {
ConfigTree expected = getSinglePath("my-value");
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.detachChildTreeBuilders();
builder.setValue("my-value");
assertEquals(expected, builder.create());
}
@Test
public void testChildModificationIsIgnoredAfterDetach() {
ConfigTree expected = getSinglePath("my-value", "key1", "key2");
ConfigTree.Builder builder = new ConfigTree.Builder();
ConfigTree.Builder childBuilder = builder.getDeepChildBuilder("key1", "key2");
childBuilder.setValue("my-value");
builder.detachChildTreeBuilders();
childBuilder.setValue("ignored-value1");
childBuilder.getChildBuilder("ignored-key").setValue("ignored-value2");
assertEquals(expected, builder.create());
}
@Test
public void testToString() {
assumeBasicBuilderWorks();
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.setValue("value1");
builder.addChildBuilder("key1").setValue("value2");
builder.addChildBuilder("key1").setValue("value3");
builder.addChildBuilder("key2").setValue("value4");
String strValue = builder.create().toString();
assertNotNull(strValue);
assertTrue(strValue.contains("value1"));
assertTrue(strValue.contains("value2"));
assertTrue(strValue.contains("value3"));
assertTrue(strValue.contains("value4"));
assertTrue(strValue.contains("key1"));
assertTrue(strValue.contains("key2"));
}
@Test
public void testDoesntHaveValueWithDeepTree() {
ConfigTree tree = getSinglePath(null, "key1", "key2");
if (tree.hasValues()) {
fail("Not expected to have value: " + tree);
}
}
private void verifyEquals(ConfigTree tree1, ConfigTree tree2) {
if (!tree1.equals(tree2)) {
fail("tree1.equals(tree2) must be true.\nTree1 = " + tree1 + ",\nTree2 = " + tree2);
}
if (!tree2.equals(tree1)) {
fail("tree2.equals(tree1) must be true.\nTree1 = " + tree1 + ",\nTree2 = " + tree2);
}
if (tree1.hashCode() != tree2.hashCode()) {
fail("The hash code for equivalent trees must match.\nTree1 = " + tree1 + ",\nTree2 = " + tree2);
}
}
private void verifyNotEquals(ConfigTree tree1, ConfigTree tree2) {
if (tree1.equals(tree2)) {
fail("tree1.equals(tree2) must be false.\nTree1 = " + tree1 + ",\nTree2 = " + tree2);
}
if (tree2.equals(tree1)) {
fail("tree2.equals(tree1) must be false.\nTree1 = " + tree1 + ",\nTree2 = " + tree2);
}
}
@Test
public void testEqualsForSame() {
ConfigTree.Builder builder = new ConfigTree.Builder();
builder.setValue("value-testEqualsForSame");
ConfigTree tree = builder.create();
verifyEquals(tree, tree);
}
@Test
public void testEqualsWithValueOnly() {
assumeBasicBuilderWorks();
String value = "value-testEqualsWithOnlyValues";
verifyEquals(getSinglePath(value), getSinglePath(value));
}
@Test
public void testEqualsWithDeepValue() {
assumeBasicBuilderWorks();
String value = "value-testEqualsWithOnlyValues";
String[] path = {"key1", "key2"};
verifyEquals(getSinglePath(value, path), getSinglePath(value, path));
}
@Test
public void testEqualsWithEmptyWithNoValueTree() {
assumeBasicBuilderWorks();
String[] path = {"key1", "key2"};
verifyEquals(getSinglePath(null, path), ConfigTree.EMPTY);
}
@Test
public void testNotEqualsWithDifferentValues() {
assumeBasicBuilderWorks();
verifyNotEquals(getSinglePath("value1"), getSinglePath("value2"));
verifyNotEquals(getSinglePath("value3"), getSinglePath(null));
}
@Test
public void testNotEqualsWithDifferentChildValues() {
assumeBasicBuilderWorks();
String[] path = {"key1", "key2"};
verifyNotEquals(getSinglePath("value1", path), getSinglePath("value2", path));
verifyNotEquals(getSinglePath("value3", path), getSinglePath(null, path));
}
@Test
public void testNotEqualsWithDifferentPathToChild() {
assumeBasicBuilderWorks();
String[] path1 = {"key1", "key2"};
String[] path2 = {"key1", "key3"};
verifyNotEquals(getSinglePath("value1", path1), getSinglePath("value1", path2));
}
@Test
public void testNotEqualsWithDifferentNumberOfChildren() {
assumeBasicBuilderWorks();
ConfigTree.Builder builder1 = new ConfigTree.Builder();
builder1.addChildBuilder("key1").setValue("value1");
builder1.addChildBuilder("key2").setValue("value2");
ConfigTree.Builder builder2 = new ConfigTree.Builder();
builder2.addChildBuilder("key1").setValue("value1");
verifyNotEquals(builder1.create(), builder2.create());
}
@Test
public void testNotEqualsWithDifferentOrderOfChildren() {
assumeBasicBuilderWorks();
ConfigTree.Builder builder1 = new ConfigTree.Builder();
builder1.addChildBuilder("key1").setValue("value1");
builder1.addChildBuilder("key1").setValue("value2");
ConfigTree.Builder builder2 = new ConfigTree.Builder();
builder2.addChildBuilder("key1").setValue("value2");
builder2.addChildBuilder("key1").setValue("value1");
verifyNotEquals(builder1.create(), builder2.create());
}
}