1 package de.dlr.shepard.integrationtests;
2
3 import static io.restassured.RestAssured.given;
4 import static org.assertj.core.api.Assertions.assertThat;
5 import static org.junit.jupiter.api.Assertions.assertEquals;
6
7 import de.dlr.shepard.auth.permission.io.PermissionsIO;
8 import de.dlr.shepard.auth.users.io.UserGroupIO;
9 import de.dlr.shepard.common.neo4j.io.BasicEntityIO;
10 import de.dlr.shepard.common.search.io.QueryType;
11 import de.dlr.shepard.common.search.io.ResponseBody;
12 import de.dlr.shepard.common.search.io.ResultTriple;
13 import de.dlr.shepard.common.search.io.SearchBody;
14 import de.dlr.shepard.common.search.io.SearchParams;
15 import de.dlr.shepard.common.search.io.SearchScope;
16 import de.dlr.shepard.common.util.Constants;
17 import de.dlr.shepard.common.util.TraversalRules;
18 import de.dlr.shepard.context.collection.io.CollectionIO;
19 import de.dlr.shepard.context.collection.io.DataObjectIO;
20 import de.dlr.shepard.context.references.structureddata.io.StructuredDataReferenceIO;
21 import de.dlr.shepard.data.structureddata.entities.StructuredData;
22 import de.dlr.shepard.data.structureddata.entities.StructuredDataPayload;
23 import de.dlr.shepard.data.structureddata.io.StructuredDataContainerIO;
24 import io.quarkus.test.junit.QuarkusIntegrationTest;
25 import io.restassured.builder.RequestSpecBuilder;
26 import io.restassured.http.ContentType;
27 import io.restassured.specification.RequestSpecification;
28 import java.util.Arrays;
29 import java.util.HashSet;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.MethodOrderer;
32 import org.junit.jupiter.api.Order;
33 import org.junit.jupiter.api.Test;
34 import org.junit.jupiter.api.TestMethodOrder;
35
36 @QuarkusIntegrationTest
37 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
38 public class StructuredDataSearcherIT extends BaseTestCaseIT {
39
40 private static String containerURL;
41 private static CollectionIO collection;
42 private static DataObjectIO rootObject;
43 private static DataObjectIO firstChild;
44 private static DataObjectIO secondChild;
45 private static DataObjectIO secondChildFirstGrandchild;
46 private static DataObjectIO cyclicSuccessor;
47 private static DataObjectIO firstSuccessor;
48 private static StructuredDataContainerIO structuredDataContainer;
49 private static StructuredDataContainerIO structuredDataContainerSuccessor;
50 private static StructuredData structuredData;
51 private static StructuredData structuredData1;
52 private static StructuredData structuredDataSuccessor;
53 private static StructuredDataPayload payload;
54 private static StructuredDataPayload payload1;
55 private static StructuredDataPayload payloadSuccessor;
56 private static String structuredDataOID;
57 private static String structuredDataOID1;
58 private static String structuredDataOIDSuccessor;
59 private static StructuredDataReferenceIO reference;
60 private static StructuredDataReferenceIO reference1;
61 private static StructuredDataReferenceIO referenceSuccessor;
62 private static String searchURL;
63 private static UserWithApiKey user1;
64 private static String jws1;
65 private static RequestSpecification searchRequestSpec1;
66 private static UserWithApiKey user2;
67 private static String jws2;
68 private static RequestSpecification searchRequestSpec2;
69
70 @BeforeAll
71 public static void setUp() {
72 collection = createCollection("SearchTestCollection");
73 rootObject = createDataObject("RootDataObject", collection.getId());
74 firstChild = createDataObjectWithParent("firstChild", collection.getId(), rootObject.getId());
75 secondChild = createDataObjectWithParent("secondChild", collection.getId(), rootObject.getId());
76 secondChildFirstGrandchild = createDataObjectWithParent(
77 "secondChildFirstGrandchild",
78 collection.getId(),
79 secondChild.getId()
80 );
81 long[] firstPredecessorIDs = { firstChild.getId(), secondChild.getId() };
82 firstSuccessor = createDataObjectWithPredecessors("firstSuccessor", collection.getId(), firstPredecessorIDs);
83 structuredDataContainer = createDataContainer("DataContainer");
84 structuredDataContainerSuccessor = createDataContainer("DataContainerSuccessor");
85 cyclicSuccessor = createDataObjectWithPredecessors(
86 "cyclicSuccessor",
87 collection.getId(),
88 new long[] { firstSuccessor.getId() }
89 );
90 long[] newPredecessorIDs = new long[firstSuccessor.getPredecessorIds().length + 1];
91 for (int i = 0; i < firstSuccessor.getPredecessorIds().length; i++) newPredecessorIDs[i] =
92 firstSuccessor.getPredecessorIds()[i];
93 newPredecessorIDs[newPredecessorIDs.length - 1] = cyclicSuccessor.getId();
94 firstSuccessor.setPredecessorIds(newPredecessorIDs);
95 putDataObject(firstSuccessor.getId(), collection.getId(), firstSuccessor);
96
97 var structuredDataToCreate = new StructuredData();
98 structuredDataToCreate.setName("StructuredData");
99 payload = new StructuredDataPayload(structuredDataToCreate, "{\"number1\":3,\"number2\":456}");
100 structuredData = createStructuredData(structuredDataToCreate, structuredDataContainer.getId(), payload);
101 payload.setStructuredData(structuredData);
102 structuredDataOID = structuredData.getOid();
103 String[] dataOIDs = { structuredDataOID };
104 reference = createStructuredDataReference("reference", dataOIDs, structuredDataContainer, secondChild);
105
106 var structuredDataToCreate1 = new StructuredData();
107 structuredDataToCreate1.setName("StructuredData1");
108 payload1 = new StructuredDataPayload(structuredDataToCreate, "{\"number1\":0,\"number2\":123}");
109 structuredData1 = createStructuredData(structuredDataToCreate1, structuredDataContainer.getId(), payload1);
110 payload1.setStructuredData(structuredData1);
111 structuredDataOID1 = structuredData1.getOid();
112 String[] dataOIDs1 = { structuredDataOID1 };
113 reference1 = createStructuredDataReference("reference1", dataOIDs1, structuredDataContainer, firstChild);
114
115 var structuredDataToCreateSuccessor = new StructuredData();
116 structuredDataToCreateSuccessor.setName("StructuredDataSuccessor");
117 payloadSuccessor = new StructuredDataPayload(structuredDataToCreateSuccessor, "{\"success\":0,\"number2\":123}");
118 structuredDataSuccessor = createStructuredData(
119 structuredDataToCreateSuccessor,
120 structuredDataContainerSuccessor.getId(),
121 payloadSuccessor
122 );
123 payloadSuccessor.setStructuredData(structuredDataSuccessor);
124 structuredDataOIDSuccessor = structuredDataSuccessor.getOid();
125 String[] dataOIDsSuccessor = { structuredDataOIDSuccessor };
126 referenceSuccessor = createStructuredDataReference(
127 "referenceSucessor",
128 dataOIDsSuccessor,
129 structuredDataContainerSuccessor,
130 firstSuccessor
131 );
132
133 searchURL = "/search";
134 user1 = getNewUserWithApiKey("user1" + System.currentTimeMillis());
135 jws1 = user1.getApiKey().getJws();
136 searchRequestSpec1 = new RequestSpecBuilder().setContentType(ContentType.JSON).addHeader("X-API-KEY", jws1).build();
137 user2 = getNewUserWithApiKey("user2" + System.currentTimeMillis());
138 jws2 = user2.getApiKey().getJws();
139 searchRequestSpec2 = new RequestSpecBuilder().setContentType(ContentType.JSON).addHeader("X-API-KEY", jws2).build();
140 }
141
142 @Test
143 @Order(1)
144 public void testFindViaChildren() {
145 SearchBody searchBody = new SearchBody();
146 SearchScope searchScope = new SearchScope();
147 searchScope.setCollectionId(collection.getId());
148 searchScope.setDataObjectId(rootObject.getId());
149 TraversalRules[] traversalRules = { TraversalRules.children };
150 searchScope.setTraversalRules(traversalRules);
151 SearchScope[] scopes = { searchScope };
152 searchBody.setScopes(scopes);
153 SearchParams searchParams = new SearchParams();
154 searchParams.setQueryType(QueryType.StructuredData);
155 String query = "number1: {$gt: 1}";
156 searchParams.setQuery(query);
157 searchBody.setSearchParams(searchParams);
158 var result = given()
159 .spec(requestSpecOfDefaultUser)
160 .body(searchBody)
161 .when()
162 .post(searchURL)
163 .then()
164 .statusCode(200)
165 .extract()
166 .as(ResponseBody.class);
167 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
168 assertThat(result.getResultSet()).containsExactly(triple);
169 assertThat(result.getSearchParams()).isEqualTo(searchParams);
170 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
171 reference.getId()
172 );
173 }
174
175 @Test
176 @Order(2)
177 public void testFindWithoutDataObjectId() {
178 SearchBody searchBody = new SearchBody();
179 SearchScope searchScope = new SearchScope();
180 searchScope.setCollectionId(collection.getId());
181 TraversalRules[] traversalRules = {};
182 searchScope.setTraversalRules(traversalRules);
183 SearchScope[] scopes = { searchScope };
184 searchBody.setScopes(scopes);
185 SearchParams searchParams = new SearchParams();
186 searchParams.setQueryType(QueryType.StructuredData);
187 String query = "number1: {$gt: 1}";
188 searchParams.setQuery(query);
189 searchBody.setSearchParams(searchParams);
190 var result = given()
191 .spec(requestSpecOfDefaultUser)
192 .body(searchBody)
193 .when()
194 .post(searchURL)
195 .then()
196 .statusCode(200)
197 .extract()
198 .as(ResponseBody.class);
199 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
200 assertThat(result.getResultSet()).containsExactly(triple);
201 assertThat(result.getSearchParams()).isEqualTo(searchParams);
202 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
203 reference.getId()
204 );
205 }
206
207 @Test
208 @Order(3)
209 public void testFindViaChildrenUniversalSyntaxAND() {
210 SearchBody searchBody = new SearchBody();
211 SearchScope searchScope = new SearchScope();
212 searchScope.setCollectionId(collection.getId());
213 searchScope.setDataObjectId(rootObject.getId());
214 TraversalRules[] traversalRules = { TraversalRules.children };
215 searchScope.setTraversalRules(traversalRules);
216 SearchScope[] scopes = { searchScope };
217 searchBody.setScopes(scopes);
218 SearchParams searchParams = new SearchParams();
219 searchParams.setQueryType(QueryType.StructuredData);
220 String query =
221 "{\"AND\": [{\"property\": \"number1\", \"value\": 3, \"operator\": \"ge\"},{\"property\": \"number1\",\"value\": 3, \"operator\": \"le\"}]}";
222 searchParams.setQuery(query);
223 searchBody.setSearchParams(searchParams);
224 var result = given()
225 .spec(requestSpecOfDefaultUser)
226 .body(searchBody)
227 .when()
228 .post(searchURL)
229 .then()
230 .statusCode(200)
231 .extract()
232 .as(ResponseBody.class);
233 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
234 assertThat(result.getResultSet()).containsExactly(triple);
235 assertEquals(query, result.getSearchParams().getQuery());
236 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
237 reference.getId()
238 );
239 }
240
241 @Test
242 @Order(4)
243 public void testDoNotFindViaChildren() {
244 SearchBody searchBody = new SearchBody();
245 SearchScope searchScope = new SearchScope();
246 searchScope.setCollectionId(collection.getId());
247 searchScope.setDataObjectId(rootObject.getId());
248 TraversalRules[] traversalRules = { TraversalRules.children };
249 searchScope.setTraversalRules(traversalRules);
250 SearchScope[] scopes = { searchScope };
251 searchBody.setScopes(scopes);
252 SearchParams searchParams = new SearchParams();
253 searchParams.setQueryType(QueryType.StructuredData);
254 String query = "number1: {$lt: 0}";
255 searchParams.setQuery(query);
256 searchBody.setSearchParams(searchParams);
257 var result = given()
258 .spec(requestSpecOfDefaultUser)
259 .body(searchBody)
260 .when()
261 .post(searchURL)
262 .then()
263 .statusCode(200)
264 .extract()
265 .as(ResponseBody.class);
266 assertEquals(0, result.getResultSet().length);
267 assertEquals(0, result.getResults().length);
268 assertThat(result.getSearchParams()).isEqualTo(searchParams);
269 }
270
271 @Test
272 @Order(5)
273 public void testFindViaChildrenUniversalSyntaxOR() {
274 SearchBody searchBody = new SearchBody();
275 SearchScope searchScope = new SearchScope();
276 searchScope.setCollectionId(collection.getId());
277 searchScope.setDataObjectId(rootObject.getId());
278 TraversalRules[] traversalRules = { TraversalRules.children };
279 searchScope.setTraversalRules(traversalRules);
280 SearchScope[] scopes = { searchScope };
281 searchBody.setScopes(scopes);
282 SearchParams searchParams = new SearchParams();
283 searchParams.setQueryType(QueryType.StructuredData);
284 String query =
285 "{\"OR\": [{\"property\": \"number1\", \"value\": 3, \"operator\": \"ge\"}," +
286 "{\"property\": \"number1\",\"value\": 3, \"operator\": \"le\"}]}";
287 searchParams.setQuery(query);
288 searchBody.setSearchParams(searchParams);
289 var result = given()
290 .spec(requestSpecOfDefaultUser)
291 .body(searchBody)
292 .when()
293 .post(searchURL)
294 .then()
295 .statusCode(200)
296 .extract()
297 .as(ResponseBody.class);
298 assertEquals(2, result.getResultSet().length);
299 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
300 ResultTriple triple1 = new ResultTriple(collection.getId(), firstChild.getId(), reference1.getId());
301 assertThat(result.getResultSet()).contains(triple);
302 assertThat(result.getResultSet()).contains(triple1);
303 assertEquals(query, result.getSearchParams().getQuery());
304 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
305 reference.getId(),
306 reference1.getId()
307 );
308 }
309
310 @Test
311 @Order(6)
312 public void testFindViaPredecessor() {
313 SearchBody searchBody = new SearchBody();
314 SearchScope searchScope = new SearchScope();
315 searchScope.setCollectionId(collection.getId());
316 searchScope.setDataObjectId(firstSuccessor.getId());
317 TraversalRules[] traversalRules = { TraversalRules.predecessors };
318 searchScope.setTraversalRules(traversalRules);
319 SearchScope[] scopes = { searchScope };
320 searchBody.setScopes(scopes);
321 SearchParams searchParams = new SearchParams();
322 searchParams.setQueryType(QueryType.StructuredData);
323 String query = "number1: {$gt: 1}";
324 searchParams.setQuery(query);
325 searchBody.setSearchParams(searchParams);
326 var result = given()
327 .spec(requestSpecOfDefaultUser)
328 .body(searchBody)
329 .when()
330 .post(searchURL)
331 .then()
332 .statusCode(200)
333 .extract()
334 .as(ResponseBody.class);
335 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
336 assertThat(result.getResultSet()).containsExactly(triple);
337 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
338 reference.getId()
339 );
340 assertThat(result.getSearchParams()).isEqualTo(searchParams);
341 }
342
343 @Test
344 @Order(7)
345 public void testFindViaChildrenUniversalSyntaxNOT() {
346 SearchBody searchBody = new SearchBody();
347 SearchScope searchScope = new SearchScope();
348 searchScope.setCollectionId(collection.getId());
349 searchScope.setDataObjectId(rootObject.getId());
350 TraversalRules[] traversalRules = { TraversalRules.children };
351 searchScope.setTraversalRules(traversalRules);
352 SearchScope[] scopes = { searchScope };
353 searchBody.setScopes(scopes);
354 SearchParams searchParams = new SearchParams();
355 searchParams.setQueryType(QueryType.StructuredData);
356 String query = "{\"NOT\": {\"property\": \"number1\", \"value\": 3, \"operator\": \"eq\"}}";
357 searchParams.setQuery(query);
358 searchBody.setSearchParams(searchParams);
359 var result = given()
360 .spec(requestSpecOfDefaultUser)
361 .body(searchBody)
362 .when()
363 .post(searchURL)
364 .then()
365 .statusCode(200)
366 .extract()
367 .as(ResponseBody.class);
368 assertEquals(1, result.getResultSet().length);
369 ResultTriple triple1 = new ResultTriple(collection.getId(), firstChild.getId(), reference1.getId());
370 assertThat(result.getResultSet()).contains(triple1);
371 assertEquals(query, result.getSearchParams().getQuery());
372 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).contains(reference1.getId());
373 }
374
375 @Test
376 @Order(8)
377 public void testDoNotFindViaPredecessor() {
378 SearchBody searchBody = new SearchBody();
379 SearchScope searchScope = new SearchScope();
380 searchScope.setCollectionId(collection.getId());
381 searchScope.setDataObjectId(firstSuccessor.getId());
382 TraversalRules[] traversalRules = { TraversalRules.predecessors };
383 searchScope.setTraversalRules(traversalRules);
384 SearchScope[] scopes = { searchScope };
385 searchBody.setScopes(scopes);
386 SearchParams searchParams = new SearchParams();
387 searchParams.setQueryType(QueryType.StructuredData);
388 String query = "number1: {$lt: 0}";
389 searchParams.setQuery(query);
390 searchBody.setSearchParams(searchParams);
391 var result = given()
392 .spec(requestSpecOfDefaultUser)
393 .body(searchBody)
394 .when()
395 .post(searchURL)
396 .then()
397 .statusCode(200)
398 .extract()
399 .as(ResponseBody.class);
400 assertEquals(0, result.getResultSet().length);
401 assertEquals(0, result.getResults().length);
402 assertThat(result.getSearchParams()).isEqualTo(searchParams);
403 }
404
405 @Test
406 @Order(9)
407 public void testFindViaChildrenUniversalSyntaxDeMorgan() {
408 SearchBody searchBody = new SearchBody();
409 SearchScope searchScope = new SearchScope();
410 searchScope.setCollectionId(collection.getId());
411 searchScope.setDataObjectId(rootObject.getId());
412 TraversalRules[] traversalRules = { TraversalRules.children };
413 searchScope.setTraversalRules(traversalRules);
414 SearchScope[] scopes = { searchScope };
415 searchBody.setScopes(scopes);
416 SearchParams searchParams = new SearchParams();
417 searchParams.setQueryType(QueryType.StructuredData);
418 String query =
419 "{\"NOT\": {\"OR\": [{\"property\": \"number1\", \"value\": 4, \"operator\": \"gt\"}," +
420 " {\"property\": \"number1\", \"value\": 1, \"operator\": \"lt\"}]}}";
421 searchParams.setQuery(query);
422 searchBody.setSearchParams(searchParams);
423 var result = given()
424 .spec(requestSpecOfDefaultUser)
425 .body(searchBody)
426 .when()
427 .post(searchURL)
428 .then()
429 .statusCode(200)
430 .extract()
431 .as(ResponseBody.class);
432 assertEquals(1, result.getResultSet().length);
433 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
434 assertThat(result.getResultSet()).contains(triple);
435 assertEquals(query, result.getSearchParams().getQuery());
436 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).contains(reference.getId());
437 }
438
439 @Test
440 @Order(10)
441 public void testFindViaParent() {
442 SearchBody searchBody = new SearchBody();
443 SearchScope searchScope = new SearchScope();
444 searchScope.setCollectionId(collection.getId());
445 searchScope.setDataObjectId(secondChildFirstGrandchild.getId());
446 TraversalRules[] traversalRules = { TraversalRules.parents };
447 searchScope.setTraversalRules(traversalRules);
448 SearchScope[] scopes = { searchScope };
449 searchBody.setScopes(scopes);
450 SearchParams searchParams = new SearchParams();
451 searchParams.setQueryType(QueryType.StructuredData);
452 String query = "number1: {$gt: 1}";
453 searchParams.setQuery(query);
454 searchBody.setSearchParams(searchParams);
455 var result = given()
456 .spec(requestSpecOfDefaultUser)
457 .body(searchBody)
458 .when()
459 .post(searchURL)
460 .then()
461 .statusCode(200)
462 .extract()
463 .as(ResponseBody.class);
464 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
465 assertThat(result.getResultSet()).containsExactly(triple);
466 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
467 reference.getId()
468 );
469 assertThat(result.getSearchParams()).isEqualTo(searchParams);
470 }
471
472 @Test
473 @Order(11)
474 public void testFindViaSuccessor() {
475 SearchBody searchBody = new SearchBody();
476 SearchScope searchScope = new SearchScope();
477 searchScope.setCollectionId(collection.getId());
478 searchScope.setDataObjectId(secondChild.getId());
479 TraversalRules[] traversalRules = { TraversalRules.successors };
480 searchScope.setTraversalRules(traversalRules);
481 SearchScope[] scopes = { searchScope };
482 searchBody.setScopes(scopes);
483 SearchParams searchParams = new SearchParams();
484 searchParams.setQueryType(QueryType.StructuredData);
485 String query = "success: {$eq: 0}";
486 searchParams.setQuery(query);
487 searchBody.setSearchParams(searchParams);
488 var result = given()
489 .spec(requestSpecOfDefaultUser)
490 .body(searchBody)
491 .when()
492 .post(searchURL)
493 .then()
494 .statusCode(200)
495 .extract()
496 .as(ResponseBody.class);
497 ResultTriple triple = new ResultTriple(collection.getId(), firstSuccessor.getId(), referenceSuccessor.getId());
498 assertThat(result.getResultSet()).containsExactly(triple);
499 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
500 referenceSuccessor.getId()
501 );
502 assertThat(result.getSearchParams()).isEqualTo(searchParams);
503 }
504
505 @Test
506 @Order(12)
507 public void testFindMultipleResults() {
508 SearchBody searchBody = new SearchBody();
509 SearchScope searchScope = new SearchScope();
510 searchScope.setCollectionId(collection.getId());
511 searchScope.setDataObjectId(rootObject.getId());
512 TraversalRules[] traversalRules = { TraversalRules.children };
513 searchScope.setTraversalRules(traversalRules);
514 SearchScope[] scopes = { searchScope };
515 searchBody.setScopes(scopes);
516 SearchParams searchParams = new SearchParams();
517 searchParams.setQueryType(QueryType.StructuredData);
518 String query = "number2: {$gt: 0}";
519 searchParams.setQuery(query);
520 searchBody.setSearchParams(searchParams);
521 var result = given()
522 .spec(requestSpecOfDefaultUser)
523 .body(searchBody)
524 .when()
525 .post(searchURL)
526 .then()
527 .statusCode(200)
528 .extract()
529 .as(ResponseBody.class);
530 assertEquals(2, result.getResultSet().length);
531 HashSet<ResultTriple> resultTriples = new HashSet<>();
532 resultTriples.add(result.getResultSet()[0]);
533 resultTriples.add(result.getResultSet()[1]);
534 ResultTriple expectedResult0 = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
535 ResultTriple expectedResult1 = new ResultTriple(collection.getId(), firstChild.getId(), reference1.getId());
536 assertThat(resultTriples).containsExactlyInAnyOrder(expectedResult0, expectedResult1);
537 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
538 reference.getId(),
539 reference1.getId()
540 );
541 assertThat(result.getSearchParams()).isEqualTo(searchParams);
542 }
543
544 @Test
545 @Order(13)
546 public void testFindViaPredecessorCycle() {
547 SearchBody searchBody = new SearchBody();
548 SearchScope searchScope = new SearchScope();
549 searchScope.setCollectionId(collection.getId());
550 searchScope.setDataObjectId(cyclicSuccessor.getId());
551 TraversalRules[] traversalRules = { TraversalRules.predecessors };
552 searchScope.setTraversalRules(traversalRules);
553 SearchScope[] scopes = { searchScope };
554 searchBody.setScopes(scopes);
555 SearchParams searchParams = new SearchParams();
556 searchParams.setQueryType(QueryType.StructuredData);
557 String query = "success: {$eq: 0}";
558 searchParams.setQuery(query);
559 searchBody.setSearchParams(searchParams);
560 var result = given()
561 .spec(requestSpecOfDefaultUser)
562 .body(searchBody)
563 .when()
564 .post(searchURL)
565 .then()
566 .statusCode(200)
567 .extract()
568 .as(ResponseBody.class);
569 assertEquals(1, result.getResultSet().length);
570 assertThat(result.getSearchParams()).isEqualTo(searchParams);
571 }
572
573 @Test
574 @Order(14)
575 public void testFindViaPredecessorCycleUnauthorized() {
576 SearchBody searchBody = new SearchBody();
577 SearchScope searchScope = new SearchScope();
578 searchScope.setCollectionId(collection.getId());
579 searchScope.setDataObjectId(cyclicSuccessor.getId());
580 TraversalRules[] traversalRules = { TraversalRules.predecessors };
581 searchScope.setTraversalRules(traversalRules);
582 SearchScope[] scopes = { searchScope };
583 searchBody.setScopes(scopes);
584 SearchParams searchParams = new SearchParams();
585 searchParams.setQueryType(QueryType.StructuredData);
586 String query = "success: {$eq: 0}";
587 searchParams.setQuery(query);
588 searchBody.setSearchParams(searchParams);
589 var result = given()
590 .spec(searchRequestSpec1)
591 .body(searchBody)
592 .when()
593 .post(searchURL)
594 .then()
595 .statusCode(200)
596 .extract()
597 .as(ResponseBody.class);
598 assertEquals(0, result.getResultSet().length);
599 assertEquals(0, result.getResults().length);
600 assertThat(result.getSearchParams()).isEqualTo(searchParams);
601 }
602
603 @Test
604 @Order(15)
605 public void testFindViaPredecessorCyclePermissionsReader() {
606 String permissionsURL = "/collections/" + collection.getId() + "/permissions";
607
608 PermissionsIO permissions = given()
609 .spec(requestSpecOfDefaultUser)
610 .when()
611 .get(permissionsURL)
612 .then()
613 .statusCode(200)
614 .extract()
615 .as(PermissionsIO.class);
616 String[] reader = { user1.getUser().getUsername() };
617 permissions.setReader(reader);
618 given()
619 .spec(requestSpecOfDefaultUser)
620 .body(permissions)
621 .when()
622 .put(permissionsURL)
623 .then()
624 .statusCode(200)
625 .extract()
626 .as(PermissionsIO.class);
627 SearchBody searchBody = new SearchBody();
628 SearchScope searchScope = new SearchScope();
629 searchScope.setCollectionId(collection.getId());
630 searchScope.setDataObjectId(cyclicSuccessor.getId());
631 TraversalRules[] traversalRules = { TraversalRules.predecessors };
632 searchScope.setTraversalRules(traversalRules);
633 SearchScope[] scopes = { searchScope };
634 searchBody.setScopes(scopes);
635 SearchParams searchParams = new SearchParams();
636 searchParams.setQueryType(QueryType.StructuredData);
637 String query = "success: {$eq: 0}";
638 searchParams.setQuery(query);
639 searchBody.setSearchParams(searchParams);
640 var result = given()
641 .spec(searchRequestSpec1)
642 .body(searchBody)
643 .when()
644 .post(searchURL)
645 .then()
646 .statusCode(200)
647 .extract()
648 .as(ResponseBody.class);
649 assertEquals(1, result.getResultSet().length);
650 assertThat(result.getSearchParams()).isEqualTo(searchParams);
651 }
652
653 @Test
654 @Order(16)
655 public void testFindViaPredecessorCycleReaderGroup() {
656 String userGroupURL = "/" + Constants.USERGROUPS;
657 UserGroupIO userGroup = new UserGroupIO();
658 userGroup.setName("userGroup");
659 userGroup.setUsernames(new String[] { user2.getUser().getUsername() });
660 UserGroupIO userGroupCreated = given()
661 .spec(requestSpecOfDefaultUser)
662 .body(userGroup)
663 .when()
664 .post(userGroupURL)
665 .then()
666 .statusCode(201)
667 .extract()
668 .as(UserGroupIO.class);
669
670 String permissionsURL = "/" + Constants.COLLECTIONS + "/" + collection.getId() + "/" + Constants.PERMISSIONS;
671 PermissionsIO permissions = given()
672 .spec(requestSpecOfDefaultUser)
673 .when()
674 .get(permissionsURL)
675 .then()
676 .statusCode(200)
677 .extract()
678 .as(PermissionsIO.class);
679 long[] readerGroupsIds = { userGroupCreated.getId() };
680 permissions.setReaderGroupIds(readerGroupsIds);
681 given()
682 .spec(requestSpecOfDefaultUser)
683 .body(permissions)
684 .when()
685 .put(permissionsURL)
686 .then()
687 .statusCode(200)
688 .extract()
689 .as(PermissionsIO.class);
690 SearchBody searchBody = new SearchBody();
691 SearchScope searchScope = new SearchScope();
692 searchScope.setCollectionId(collection.getId());
693 searchScope.setDataObjectId(cyclicSuccessor.getId());
694 TraversalRules[] traversalRules = { TraversalRules.predecessors };
695 searchScope.setTraversalRules(traversalRules);
696 SearchScope[] scopes = { searchScope };
697 searchBody.setScopes(scopes);
698 SearchParams searchParams = new SearchParams();
699 searchParams.setQueryType(QueryType.StructuredData);
700 String query = "success: {$eq: 0}";
701 searchParams.setQuery(query);
702 searchBody.setSearchParams(searchParams);
703 var result = given()
704 .spec(searchRequestSpec2)
705 .body(searchBody)
706 .when()
707 .post(searchURL)
708 .then()
709 .statusCode(200)
710 .extract()
711 .as(ResponseBody.class);
712 assertEquals(1, result.getResultSet().length);
713 assertThat(result.getSearchParams()).isEqualTo(searchParams);
714 }
715
716 @Test
717 @Order(17)
718 public void testDoNotFindViaDeletedNode() {
719 deleteDataObject(secondChild);
720 SearchBody searchBody = new SearchBody();
721 SearchScope searchScope = new SearchScope();
722 searchScope.setCollectionId(collection.getId());
723 searchScope.setDataObjectId(rootObject.getId());
724 TraversalRules[] traversalRules = { TraversalRules.children };
725 searchScope.setTraversalRules(traversalRules);
726 SearchScope[] scopes = { searchScope };
727 searchBody.setScopes(scopes);
728 SearchParams searchParams = new SearchParams();
729 searchParams.setQueryType(QueryType.StructuredData);
730 String query = "number1: {$gt: 1}";
731 searchParams.setQuery(query);
732 searchBody.setSearchParams(searchParams);
733 var result = given()
734 .spec(requestSpecOfDefaultUser)
735 .body(searchBody)
736 .when()
737 .post(searchURL)
738 .then()
739 .statusCode(200)
740 .extract()
741 .as(ResponseBody.class);
742 assertEquals(0, result.getResultSet().length);
743 assertThat(result.getSearchParams()).isEqualTo(searchParams);
744 }
745
746 private static DataObjectIO createDataObjectWithParent(String name, long collectionId, long parentID) {
747 var dataObjectsURL = String.format("/%s/%d/%s/", Constants.COLLECTIONS, collectionId, Constants.DATA_OBJECTS);
748 DataObjectIO dataObjectIO = new DataObjectIO();
749 dataObjectIO.setName(name);
750 dataObjectIO.setParentId(parentID);
751 var dataObject = given()
752 .spec(requestSpecOfDefaultUser)
753 .body(dataObjectIO)
754 .when()
755 .post(dataObjectsURL)
756 .then()
757 .statusCode(201)
758 .extract()
759 .as(DataObjectIO.class);
760 return dataObject;
761 }
762
763 private static DataObjectIO createDataObjectWithPredecessors(String name, long collectionId, long[] predecessorsIDs) {
764 var dataObjectsURL = String.format("/%s/%d/%s/", Constants.COLLECTIONS, collectionId, Constants.DATA_OBJECTS);
765 DataObjectIO dataObjectIO = new DataObjectIO();
766 dataObjectIO.setName(name);
767 dataObjectIO.setPredecessorIds(predecessorsIDs);
768 var dataObject = given()
769 .spec(requestSpecOfDefaultUser)
770 .body(dataObjectIO)
771 .when()
772 .post(dataObjectsURL)
773 .then()
774 .statusCode(201)
775 .extract()
776 .as(DataObjectIO.class);
777 return dataObject;
778 }
779
780 private static StructuredDataContainerIO createDataContainer(String name) {
781 containerURL = "/" + Constants.STRUCTURED_DATA_CONTAINERS;
782 StructuredDataContainerIO containerToCreate = new StructuredDataContainerIO();
783 containerToCreate.setName(name);
784 return given()
785 .spec(requestSpecOfDefaultUser)
786 .body(containerToCreate)
787 .when()
788 .post(containerURL)
789 .then()
790 .statusCode(201)
791 .extract()
792 .as(StructuredDataContainerIO.class);
793 }
794
795 private static StructuredData createStructuredData(
796 StructuredData structuredDataToCreate,
797 long containerID,
798 StructuredDataPayload payload
799 ) {
800 containerURL = "/" + Constants.STRUCTURED_DATA_CONTAINERS;
801 return given()
802 .spec(requestSpecOfDefaultUser)
803 .body(payload)
804 .when()
805 .post(String.format("%s/%d/%s", containerURL, containerID, Constants.PAYLOAD))
806 .then()
807 .statusCode(201)
808 .extract()
809 .as(StructuredData.class);
810 }
811
812 private static StructuredDataReferenceIO createStructuredDataReference(
813 String name,
814 String[] structuredDataOIDs,
815 StructuredDataContainerIO container,
816 DataObjectIO dataObject
817 ) {
818 StructuredDataReferenceIO toCreate = new StructuredDataReferenceIO();
819 toCreate.setName(name);
820 toCreate.setStructuredDataOids(structuredDataOIDs);
821 toCreate.setStructuredDataContainerId(container.getId());
822 String referencesURL = String.format(
823 "/%s/%d/%s/%d/%s",
824 Constants.COLLECTIONS,
825 collection.getId(),
826 Constants.DATA_OBJECTS,
827 dataObject.getId(),
828 Constants.STRUCTURED_DATA_REFERENCES
829 );
830 return given()
831 .spec(requestSpecOfDefaultUser)
832 .body(toCreate)
833 .when()
834 .post(referencesURL)
835 .then()
836 .statusCode(201)
837 .extract()
838 .as(StructuredDataReferenceIO.class);
839 }
840
841 private static void deleteDataObject(DataObjectIO dataObject) {
842 String dataObjectsURL = String.format(
843 "/%s/%d/%s",
844 Constants.COLLECTIONS,
845 collection.getId(),
846 Constants.DATA_OBJECTS
847 );
848 given()
849 .spec(requestSpecOfDefaultUser)
850 .when()
851 .delete(dataObjectsURL + "/" + dataObject.getId())
852 .then()
853 .statusCode(204);
854 }
855
856 private static void putDataObject(Long dataObjectToChangeID, Long collectionID, DataObjectIO changedDataObject) {
857 String putURL = String.format("/%s/%d/%s", Constants.COLLECTIONS, collection.getId(), Constants.DATA_OBJECTS);
858 putURL = putURL + "/" + dataObjectToChangeID;
859 given().spec(requestSpecOfDefaultUser).body(changedDataObject).when().put(putURL).then().statusCode(200);
860 }
861 }