blob: e9630f0f59986519ce25f658e24dff850b3350c8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tinkerpop.gremlin.process.traversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.ImmutablePath;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath;
import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedPath;
import org.apache.tinkerpop.gremlin.structure.util.reference.ReferencePath;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public class PathTest {
private final static List<Supplier<Path>> PATH_SUPPLIERS =
Arrays.asList(MutablePath::make, ImmutablePath::make, DetachedPath::make, ReferencePath::make);
@Test
public void shouldHaveStandardSemanticsImplementedCorrectly() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
assertTrue(path.isSimple());
assertEquals(0, path.size());
path = path.extend(1, Collections.singleton("a"));
path = path.extend(2, Collections.singleton("b"));
path = path.extend(3, Collections.singleton("c"));
assertEquals(3, path.size());
assertEquals(Integer.valueOf(1), path.get("a"));
assertEquals(Integer.valueOf(2), path.get("b"));
assertEquals(Integer.valueOf(3), path.get("c"));
path = path.extend(Collections.singleton("d"));
assertEquals(3, path.size());
assertEquals(Integer.valueOf(1), path.get("a"));
assertEquals(Integer.valueOf(2), path.get("b"));
assertEquals(Integer.valueOf(3), path.get("c"));
assertEquals(Integer.valueOf(3), path.get("d"));
assertTrue(path.hasLabel("a"));
assertTrue(path.hasLabel("b"));
assertTrue(path.hasLabel("c"));
assertTrue(path.hasLabel("d"));
assertFalse(path.hasLabel("e"));
assertTrue(path.isSimple());
path = path.extend(3, Collections.singleton("e"));
assertFalse(path.isSimple());
assertTrue(path.hasLabel("e"));
assertEquals(4, path.size());
assertEquals(Integer.valueOf(1), path.get(0));
assertEquals(Integer.valueOf(2), path.get(1));
assertEquals(Integer.valueOf(3), path.get(2));
assertEquals(Integer.valueOf(3), path.get(3));
Path retractedPath = path.retract(Collections.singleton("f")).clone();
assertFalse(path.hasLabel("f"));
assertEquals(4, path.size());
assertEquals(retractedPath, path);
path = path.retract(Collections.singleton("b"));
assertFalse(path.hasLabel("b"));
assertEquals(3, path.size());
assertEquals(retractedPath.retract(Collections.singleton("b")), path);
path = path.retract(Collections.singleton("a"));
assertEquals(2, path.size());
assertFalse(path.hasLabel("a"));
assertTrue(path.hasLabel("d"));
path = path.retract(new HashSet<>(Arrays.asList("c", "d")));
assertFalse(path.hasLabel("c"));
assertFalse(path.hasLabel("d"));
assertTrue(path.hasLabel("e"));
assertEquals(1, path.size());
path = path.retract(Collections.singleton("e"));
assertFalse(path.hasLabel("c"));
assertFalse(path.hasLabel("d"));
assertFalse(path.hasLabel("e"));
assertNotEquals(retractedPath, path);
assertEquals(0, path.size());
});
}
@Test
public void shouldHandleMultiLabelPaths() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
path = path.extend("marko", Collections.singleton("a"));
path = path.extend("stephen", Collections.singleton("b"));
path = path.extend("matthias", Collections.singleton("a"));
assertEquals(3, path.size());
assertEquals(3, path.objects().size());
assertEquals(3, path.labels().size());
assertEquals(2, new HashSet<>(path.labels()).size());
assertTrue(path.get("a") instanceof List);
assertTrue(path.get("b") instanceof String);
assertEquals(2, path.<List<String>>get("a").size());
assertTrue(path.<List<String>>get("a").contains("marko"));
assertTrue(path.<List<String>>get("a").contains("matthias"));
});
}
@Test
public void shouldExcludeUnlabeledLabelsFromPath() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
path = path.extend("marko", Collections.singleton("a"));
path = path.extend("stephen", Collections.singleton("b"));
path = path.extend("matthias", new LinkedHashSet<>(Arrays.asList("c", "d")));
assertEquals(3, path.size());
assertEquals(3, path.objects().size());
assertEquals(3, path.labels().size());
assertEquals(1, path.labels().get(0).size());
assertEquals(1, path.labels().get(1).size());
assertEquals("b", path.labels().get(1).iterator().next());
assertEquals(2, path.labels().get(2).size());
assertTrue(path.labels().get(2).contains("c"));
assertTrue(path.labels().get(2).contains("d"));
});
}
@Test
public void shouldHaveOrderedPathLabels() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
path = path.extend("marko", new LinkedHashSet<>(Arrays.asList("a", "b")));
path = path.extend("stephen", new LinkedHashSet<>(Arrays.asList("c", "a")));
path = path.extend("matthias", new LinkedHashSet<>(Arrays.asList("a", "b")));
assertEquals(3, path.size());
assertEquals(3, path.objects().size());
assertEquals(3, path.labels().size());
assertEquals(2, path.labels().get(0).size());
assertEquals(2, path.labels().get(1).size());
assertEquals(2, path.labels().get(2).size());
///
Iterator<String> labels = path.labels().get(0).iterator();
assertEquals("a", labels.next());
assertEquals("b", labels.next());
assertFalse(labels.hasNext());
labels = path.labels().get(1).iterator();
assertEquals("c", labels.next());
assertEquals("a", labels.next());
assertFalse(labels.hasNext());
labels = path.labels().get(2).iterator();
assertEquals("a", labels.next());
assertEquals("b", labels.next());
assertFalse(labels.hasNext());
///
List<String> names = path.get("a");
assertEquals("marko", names.get(0));
assertEquals("stephen", names.get(1));
assertEquals("matthias", names.get(2));
names = path.get("b");
assertEquals("marko", names.get(0));
assertEquals("matthias", names.get(1));
assertEquals("stephen", path.get("c"));
});
}
@Test
public void shouldSelectSingleCorrectly() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
path = path.extend("marko", new LinkedHashSet<String>(Arrays.asList("a", "b")));
path = path.extend("stephen", new LinkedHashSet<>(Arrays.asList("a", "c")));
path = path.extend("matthias", new LinkedHashSet<>(Arrays.asList("c", "d")));
assertEquals(3, path.size());
assertEquals("marko", path.get(Pop.first, "a"));
assertEquals("marko", path.get(Pop.first, "b"));
assertEquals("stephen", path.get(Pop.first, "c"));
assertEquals("matthias", path.get(Pop.first, "d"));
///
assertEquals("marko", path.get(Pop.last, "b"));
assertEquals("stephen", path.get(Pop.last, "a"));
assertEquals("matthias", path.get(Pop.last, "c"));
assertEquals("matthias", path.get(Pop.last, "d"));
});
}
@Test
public void shouldSelectListCorrectly() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
path = path.extend("marko", new LinkedHashSet<>(Arrays.asList("a", "b")));
path = path.extend("stephen", new LinkedHashSet<>(Arrays.asList("a", "c")));
path = path.extend("matthias", new LinkedHashSet<>(Arrays.asList("c", "d")));
assertEquals(3, path.size());
assertEquals(2, path.<List>get(Pop.all, "a").size());
assertEquals("marko", path.<List>get(Pop.all, "a").get(0));
assertEquals("stephen", path.<List>get(Pop.all, "a").get(1));
assertEquals(1, path.<List>get(Pop.all, "b").size());
assertEquals("marko", path.<List>get(Pop.all, "b").get(0));
assertEquals(2, path.<List>get(Pop.all, "c").size());
assertEquals("stephen", path.<List>get(Pop.all, "c").get(0));
assertEquals("matthias", path.<List>get(Pop.all, "c").get(1));
assertEquals(1, path.<List>get(Pop.all, "d").size());
assertEquals("matthias", path.<List>get(Pop.all, "d").get(0));
///
assertEquals(0, path.<List>get(Pop.all, "noExist").size());
});
}
@Test
public void shouldHaveEquality() {
PATH_SUPPLIERS.forEach(supplier -> {
Path pathA1 = supplier.get();
Path pathA2 = supplier.get();
Path pathB1 = supplier.get();
Path pathB2 = supplier.get();
assertEquals(pathA1, pathA2);
assertEquals(pathA1.hashCode(), pathA2.hashCode());
assertEquals(pathA2, pathB1);
assertEquals(pathA2.hashCode(), pathB1.hashCode());
assertEquals(pathB1, pathB2);
assertEquals(pathB1.hashCode(), pathB2.hashCode());
///
pathA1 = pathA1.extend("marko", Collections.singleton("a"));
pathA2 = pathA2.extend("marko", Collections.singleton("a"));
pathB1 = pathB1.extend("marko", Collections.singleton("b"));
pathB2 = pathB2.extend("marko", Collections.singleton("b"));
assertEquals(pathA1, pathA2);
assertEquals(pathA1.hashCode(), pathA2.hashCode());
assertNotEquals(pathA2, pathB1);
assertEquals(pathB1, pathB2);
assertEquals(pathB1.hashCode(), pathB2.hashCode());
///
pathA1 = pathA1.extend("daniel", new LinkedHashSet<>(Arrays.asList("aa", "aaa")));
pathA2 = pathA2.extend("daniel", new LinkedHashSet<>(Arrays.asList("aa", "aaa")));
pathB1 = pathB1.extend("stephen", new LinkedHashSet<>(Arrays.asList("bb", "bbb")));
pathB2 = pathB2.extend("stephen", Collections.singleton("bb"));
assertEquals(pathA1, pathA2);
assertEquals(pathA1.hashCode(), pathA2.hashCode());
assertNotEquals(pathA2, pathB1);
assertNotEquals(pathB1, pathB2);
///
pathA1 = pathA1.extend("matthias", new LinkedHashSet<>(Arrays.asList("aaaa", "aaaaa")));
pathA2 = pathA2.extend("bob", new LinkedHashSet<>(Arrays.asList("aaaa", "aaaaa")));
pathB1 = pathB1.extend("byn", Collections.singleton("bbbb"));
pathB2 = pathB2.extend("bryn", Collections.singleton("bbbb"));
assertNotEquals(pathA1, pathA2);
assertNotEquals(pathA2, pathB1);
assertNotEquals(pathB1, pathB2);
});
}
@Test
public void shouldHavePopEquality() {
PATH_SUPPLIERS.forEach(supplier -> {
Path pathA1 = supplier.get();
Path pathA2 = supplier.get();
Path pathB1 = supplier.get();
Path pathB2 = supplier.get();
assertTrue(pathA1.popEquals(Pop.all, pathA2));
assertTrue(pathA2.popEquals(Pop.all, pathB1));
assertTrue(pathB1.popEquals(Pop.all, pathB2));
assertTrue(pathA1.popEquals(Pop.first, pathA2));
assertTrue(pathA2.popEquals(Pop.first, pathB1));
assertTrue(pathB1.popEquals(Pop.first, pathB2));
assertTrue(pathA1.popEquals(Pop.last, pathA2));
assertTrue(pathA2.popEquals(Pop.last, pathB1));
assertTrue(pathB1.popEquals(Pop.last, pathB2));
///
pathA1 = pathA1.extend("marko", Collections.singleton("a"));
pathA2 = pathA2.extend("marko", Collections.singleton("a"));
pathB1 = pathB1.extend("matthias", Collections.singleton("a"));
pathB2 = pathB2.extend("matthias", Collections.singleton("a"));
assertTrue(pathA1.popEquals(Pop.all, pathA2));
assertFalse(pathA2.popEquals(Pop.all, pathB1));
assertTrue(pathB1.popEquals(Pop.all, pathB2));
assertTrue(pathA1.popEquals(Pop.first, pathA2));
assertFalse(pathA2.popEquals(Pop.first, pathB1));
assertTrue(pathB1.popEquals(Pop.first, pathB2));
assertTrue(pathA1.popEquals(Pop.last, pathA2));
assertFalse(pathA2.popEquals(Pop.last, pathB1));
assertTrue(pathB1.popEquals(Pop.last, pathB2));
///
pathA1 = pathA1.extend("matthias", Collections.singleton("a"));
pathA2 = pathA2.extend("matthias", Collections.singleton("a"));
pathB1 = pathB1.extend("marko", Collections.singleton("a"));
pathB2 = pathB2.extend("marko", Collections.singleton("a"));
assertTrue(pathA1.popEquals(Pop.all, pathA2));
assertFalse(pathA2.popEquals(Pop.all, pathB1));
assertTrue(pathB1.popEquals(Pop.all, pathB2));
assertTrue(pathA1.popEquals(Pop.first, pathA2));
assertFalse(pathA2.popEquals(Pop.first, pathB1));
assertTrue(pathB1.popEquals(Pop.first, pathB2));
assertTrue(pathA1.popEquals(Pop.last, pathA2));
assertFalse(pathA2.popEquals(Pop.last, pathB1));
assertTrue(pathB1.popEquals(Pop.last, pathB2));
///
pathA1 = pathA1.extend("bob", Collections.singleton("a"));
pathA2 = pathA2.extend("bob", Collections.singleton("a"));
pathB1 = pathB1.extend("bob", Collections.singleton("a"));
pathB2 = pathB2.extend("bob", Collections.singleton("a"));
assertTrue(pathA1.popEquals(Pop.all, pathA2));
assertFalse(pathA2.popEquals(Pop.all, pathB1));
assertTrue(pathB1.popEquals(Pop.all, pathB2));
assertTrue(pathA1.popEquals(Pop.first, pathA2));
assertFalse(pathA2.popEquals(Pop.first, pathB1));
assertTrue(pathB1.popEquals(Pop.first, pathB2));
assertTrue(pathA1.popEquals(Pop.last, pathA2));
assertTrue(pathA2.popEquals(Pop.last, pathB1));
assertTrue(pathB1.popEquals(Pop.last, pathB2));
///
pathA1 = pathA1.extend("stephen", Collections.singleton("b"));
pathA2 = pathA2.extend("stephen", Collections.singleton("b"));
pathB1 = pathB1.extend("stephen", Collections.singleton("b"));
pathB2 = pathB2.extend("stephen", Collections.singleton("b"));
assertTrue(pathA1.popEquals(Pop.all, pathA2));
assertFalse(pathA2.popEquals(Pop.all, pathB1));
assertTrue(pathB1.popEquals(Pop.all, pathB2));
assertTrue(pathA1.popEquals(Pop.first, pathA2));
assertFalse(pathA2.popEquals(Pop.first, pathB1));
assertTrue(pathB1.popEquals(Pop.first, pathB2));
assertTrue(pathA1.popEquals(Pop.last, pathA2));
assertTrue(pathA2.popEquals(Pop.last, pathB1));
assertTrue(pathB1.popEquals(Pop.last, pathB2));
///
pathA1 = pathA1.extend("stephen", Collections.singleton("c"));
pathA2 = pathA2.extend("stephen", Collections.singleton("d"));
pathB1 = pathB1.extend("marko", Collections.singleton("e"));
pathB2 = pathB2.extend("stephen", Collections.singleton("f"));
assertTrue(pathA1.popEquals(Pop.all, pathA1));
assertFalse(pathA1.popEquals(Pop.all, pathA2));
assertFalse(pathA2.popEquals(Pop.all, pathB1));
assertFalse(pathB1.popEquals(Pop.all, pathB2));
assertFalse(pathA1.popEquals(Pop.first, pathA2));
assertFalse(pathA2.popEquals(Pop.first, pathB1));
assertFalse(pathB1.popEquals(Pop.first, pathB2));
assertTrue(pathB1.popEquals(Pop.first, pathB1));
assertFalse(pathA1.popEquals(Pop.last, pathA2));
assertFalse(pathA2.popEquals(Pop.last, pathB1));
assertFalse(pathB1.popEquals(Pop.last, pathB2));
assertTrue(pathB2.popEquals(Pop.last, pathB2));
});
}
@Test
public void shouldHaveCrossTypeEquality() {
List<Path> paths = PATH_SUPPLIERS.stream()
.map(Supplier::get)
.map(path -> path.extend("marko", new LinkedHashSet<>(Arrays.asList("a", "aa"))))
.map(path -> path.extend("daniel", Collections.singleton("b")))
.collect(Collectors.toList());
for (final Path pathA : paths) {
for (final Path pathB : paths) {
assertEquals(pathA, pathB);
assertEquals(pathA.hashCode(), pathB.hashCode());
}
}
}
@Test
public void shouldHaveSubPathSupport() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
path = path.extend("marko", Collections.singleton("a"));
path = path.extend("stephen", Collections.singleton("b"));
path = path.extend("matthias", new HashSet<>(Arrays.asList("c", "x")));
path = path.extend("bob", Collections.singleton("d"));
assertEquals(4, path.size());
assertEquals(4, path.objects().size());
assertEquals(4, path.labels().size());
///
Path subPath = path.subPath("b", "c");
assertEquals(2, subPath.size());
assertEquals(2, subPath.objects().size());
assertEquals(2, subPath.labels().size());
assertEquals("stephen", subPath.objects().get(0));
assertEquals("matthias", subPath.objects().get(1));
assertTrue(subPath.labels().get(0).contains("b"));
assertEquals(1, subPath.labels().get(0).size());
assertTrue(subPath.labels().get(1).contains("c"));
assertTrue(subPath.labels().get(1).contains("x"));
assertEquals(2, subPath.labels().get(1).size());
///
subPath = path.subPath("b", "b");
assertEquals(1, subPath.size());
assertEquals(1, subPath.objects().size());
assertEquals(1, subPath.labels().size());
assertEquals("stephen", subPath.objects().get(0));
///
subPath = path.subPath("b", "b");
assertEquals(1, subPath.size());
assertEquals(1, subPath.objects().size());
assertEquals(1, subPath.labels().size());
assertEquals("stephen", subPath.objects().get(0));
///
subPath = path.subPath("c", "d");
assertEquals(2, subPath.size());
assertEquals(2, subPath.objects().size());
assertEquals(2, subPath.labels().size());
assertEquals("matthias", subPath.objects().get(0));
assertEquals("bob", subPath.objects().get(1));
assertTrue(subPath.labels().get(0).contains("c"));
assertTrue(subPath.labels().get(0).contains("x"));
assertEquals(2, subPath.labels().get(0).size());
assertTrue(subPath.labels().get(1).contains("d"));
assertEquals(1, subPath.labels().get(1).size());
///
subPath = path.subPath("c", null);
assertEquals(2, subPath.size());
assertEquals(2, subPath.objects().size());
assertEquals(2, subPath.labels().size());
assertEquals("matthias", subPath.objects().get(0));
assertEquals("bob", subPath.objects().get(1));
assertTrue(subPath.labels().get(0).contains("c"));
assertTrue(subPath.labels().get(0).contains("x"));
assertEquals(2, subPath.labels().get(0).size());
assertTrue(subPath.labels().get(1).contains("d"));
assertEquals(1, subPath.labels().get(1).size());
///
subPath = path.subPath("a", "d");
assertEquals(4, subPath.size());
assertEquals(4, subPath.objects().size());
assertEquals(4, subPath.labels().size());
///
subPath = path.subPath(null, "d");
assertEquals(4, subPath.size());
assertEquals(4, subPath.objects().size());
assertEquals(4, subPath.labels().size());
///
try {
subPath = path.subPath("d", "a");
fail("Path labels must be ordered along path");
} catch (final IllegalArgumentException e) {
assertEquals(Path.Exceptions.couldNotIsolatedSubPath("d", "a").getMessage(), e.getMessage());
}
///
try {
subPath = path.subPath("a", "e");
fail("End path label was not found");
} catch (final IllegalArgumentException e) {
assertEquals(Path.Exceptions.couldNotLocatePathToLabel("e").getMessage(), e.getMessage());
}
///
try {
subPath = path.subPath("e", "b");
fail("Start path label was not found");
} catch (final IllegalArgumentException e) {
assertEquals(Path.Exceptions.couldNotLocatePathFromLabel("e").getMessage(), e.getMessage());
}
});
}
@Test
public void shouldHaveSubPathPopSupport() {
PATH_SUPPLIERS.forEach(supplier -> {
Path path = supplier.get();
path = path.extend("marko", Collections.singleton("a"));
path = path.extend("stephen", Collections.singleton("a"));
path = path.extend("matthias", new HashSet<>(Arrays.asList("c", "x")));
path = path.extend("bob", Collections.singleton("c"));
assertEquals(4, path.size());
assertEquals(4, path.objects().size());
assertEquals(4, path.labels().size());
///
Path subPath = path.subPath("a", "c");
assertEquals(3, subPath.size());
assertEquals(3, subPath.objects().size());
assertEquals(3, subPath.labels().size());
assertEquals("stephen", subPath.objects().get(0));
assertEquals("matthias", subPath.objects().get(1));
assertEquals("bob", subPath.objects().get(2));
assertTrue(subPath.labels().get(0).contains("a"));
assertEquals(1, subPath.labels().get(0).size());
assertTrue(subPath.labels().get(1).contains("c"));
assertTrue(subPath.labels().get(1).contains("x"));
assertEquals(2, subPath.labels().get(1).size());
assertTrue(subPath.labels().get(2).contains("c"));
assertEquals(1, subPath.labels().get(2).size());
});
}
}