1 package de.dlr.shepard.data.migrations.neo4j;
2
3 import static org.junit.jupiter.api.Assertions.assertEquals;
4 import static org.neo4j.cypherdsl.core.Cypher.*;
5
6 import de.dlr.shepard.common.neo4j.MigrationsRunner;
7 import de.dlr.shepard.common.neo4j.NeoConnector;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.stream.StreamSupport;
13 import org.apache.commons.lang3.RandomStringUtils;
14 import org.junit.jupiter.api.BeforeAll;
15 import org.junit.jupiter.api.MethodOrderer;
16 import org.junit.jupiter.api.Test;
17 import org.junit.jupiter.api.TestMethodOrder;
18 import org.neo4j.cypherdsl.core.Cypher;
19 import org.neo4j.cypherdsl.core.Node;
20 import org.neo4j.cypherdsl.core.Statement;
21 import org.neo4j.cypherdsl.core.renderer.Renderer;
22 import org.neo4j.ogm.model.Result;
23 import org.neo4j.ogm.session.Session;
24
25 @TestMethodOrder(MethodOrderer.MethodName.class)
26 public class TestNeo4jMigrations {
27
28 private static final String randomElement = RandomStringUtils.insecure().next(6, true, true);
29 private static final Renderer cypherRenderer = Renderer.getDefaultRenderer();
30 private static Session session;
31
32 @BeforeAll
33 public static void setUp() {
34 var conn = NeoConnector.getInstance();
35 conn.connect();
36 session = conn.getNeo4jSession();
37 }
38
39 private static Result query(Statement statement) {
40 var cypherQuery = cypherRenderer.render(statement);
41 return session.query(cypherQuery, Collections.emptyMap());
42 }
43
44 private static void testNodeMigrated(Node old, Node migrated) {
45 assertEquals(0, match(old).size());
46 assertEquals(1, match(migrated).size());
47 }
48
49 private static void runMigrations(String targetVersion) {
50 new MigrationsRunner(targetVersion).apply();
51 }
52
53 private static void create(Node node) {
54 var statement = Cypher.create(node).build();
55 query(statement);
56 }
57
58 private static List<Object> match(Node node) {
59 var statement = Cypher.match(node).returning(node).build();
60 var result = query(statement);
61 return StreamSupport.stream(result.spliterator(), false).map(Map::values).flatMap(Collection::stream).toList();
62 }
63
64 private static <K, V> void assertEqualsMaps(Map<K, V> expected, Map<K, V> actual) {
65 assertEquals(expected.keySet(), actual.keySet());
66 }
67
68 @Test
69 public void testV09() {
70 var collectionWithBadAttributes = node("Collection").withProperties(
71 "name",
72 Cypher.literalOf(randomElement),
73 "attributes.a",
74 Cypher.literalOf(0),
75 "attributes.b.c",
76 Cypher.literalOf(1)
77 );
78 create(collectionWithBadAttributes);
79
80 runMigrations("V9");
81
82 var collectionWithGoodAttributes = node("Collection").withProperties(
83 "name",
84 Cypher.literalOf(randomElement),
85 "attributes||a",
86 Cypher.literalOf(0),
87 "attributes||b.c",
88 Cypher.literalOf(1)
89 );
90
91 testNodeMigrated(collectionWithBadAttributes, collectionWithGoodAttributes);
92
93
94 var migratedCollection = (de.dlr.shepard.context.collection.entities.Collection) match(
95 collectionWithGoodAttributes
96 ).get(0);
97 assertEqualsMaps(Map.of("a", "0", "b.c", "1"), migratedCollection.getAttributes());
98 }
99
100 @Test
101 public void testV10() {
102 var legacyAnnotation = node("SemanticAnnotation").withProperties(
103 "name",
104 Cypher.literalOf("prop-" + randomElement + "::" + "value-" + randomElement),
105 "propertyIRI",
106 Cypher.literalOf("piri"),
107 "valueIRI",
108 Cypher.literalOf("viri")
109 );
110 create(legacyAnnotation);
111
112 runMigrations("V10");
113
114 var migratedAnnotation = node("SemanticAnnotation").withProperties(
115 "propertyName",
116 Cypher.literalOf("prop-" + randomElement),
117 "valueName",
118 Cypher.literalOf("value-" + randomElement)
119 );
120
121 testNodeMigrated(legacyAnnotation, migratedAnnotation);
122 }
123 }