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 import static org.junit.jupiter.api.Assertions.assertNotNull;
7 import static org.junit.jupiter.api.Assertions.assertNull;
8
9 import de.dlr.shepard.ErrorResponse;
10 import de.dlr.shepard.common.configuration.feature.toggles.VersioningFeatureToggle;
11 import de.dlr.shepard.common.util.Constants;
12 import de.dlr.shepard.context.collection.io.CollectionIO;
13 import de.dlr.shepard.context.collection.io.DataObjectIO;
14 import de.dlr.shepard.context.version.io.VersionIO;
15 import de.dlr.shepard.data.file.io.FileContainerIO;
16 import io.quarkus.test.junit.QuarkusIntegrationTest;
17 import io.restassured.builder.RequestSpecBuilder;
18 import io.restassured.http.ContentType;
19 import io.restassured.specification.RequestSpecification;
20 import java.util.Map;
21 import org.junit.jupiter.api.BeforeAll;
22 import org.junit.jupiter.api.MethodOrderer;
23 import org.junit.jupiter.api.Order;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.TestMethodOrder;
26
27 @QuarkusIntegrationTest
28 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
29 public class CollectionIT extends BaseTestCaseIT {
30
31 private static String collectionsURL;
32 private static CollectionIO collection;
33 private static CollectionIO collectionWithDefaultFileContainer;
34 private static VersionIO firstVersion;
35 private static VersionIO secondVersion;
36 private static String name;
37 private static long VersionizedCollectionShepardId;
38 private static String VersionizedCollectionName;
39 private static String newVersionizedCollectionName;
40 private static FileContainerIO defaultFileContainerIO;
41
42 @BeforeAll
43 public static void setUp() {
44 collectionsURL = "/" + Constants.COLLECTIONS;
45 defaultFileContainerIO = createFileContainer("DefaultFileContainer");
46 }
47
48 @Test
49 @Order(1)
50 public void postCollectionTest_Successful() {
51 var payload = new CollectionIO();
52 name = "CollectionDummy" + System.currentTimeMillis();
53 payload.setName(name);
54 payload.setDescription("My Description");
55 payload.setAttributes(Map.of("a", "1", "b", "2"));
56 CollectionIO actual = given()
57 .spec(requestSpecOfDefaultUser)
58 .body(payload)
59 .when()
60 .post(collectionsURL)
61 .then()
62 .statusCode(201)
63 .extract()
64 .as(CollectionIO.class);
65 collection = actual;
66
67 assertThat(actual.getId()).isNotNull();
68 assertThat(actual.getAttributes()).isEqualTo(Map.of("a", "1", "b", "2"));
69 assertThat(actual.getDescription()).isEqualTo("My Description");
70 assertThat(actual.getCreatedAt()).isNotNull();
71 assertThat(actual.getCreatedBy()).isEqualTo(nameOfDefaultUser);
72 assertThat(actual.getName()).isEqualTo(name);
73 assertThat(actual.getDataObjectIds()).isEmpty();
74 assertThat(actual.getUpdatedAt()).isNull();
75 assertThat(actual.getUpdatedBy()).isNull();
76 assertThat(actual.getDefaultFileContainerId()).isNull();
77 }
78
79 @Test
80 @Order(1)
81 public void postCollectionTest_withDefaultContainer_SuccessDefaultFileContainerExists() {
82 var payload = new CollectionIO();
83 name = "CollectionDummy2" + System.currentTimeMillis();
84 payload.setName(name);
85 payload.setDescription("My Description");
86 payload.setAttributes(Map.of("a", "1", "b", "2"));
87 payload.setDefaultFileContainerId(defaultFileContainerIO.getId());
88
89 CollectionIO actual = given()
90 .spec(requestSpecOfDefaultUser)
91 .body(payload)
92 .when()
93 .post(collectionsURL)
94 .then()
95 .statusCode(201)
96 .extract()
97 .as(CollectionIO.class);
98 collectionWithDefaultFileContainer = actual;
99
100 assertThat(actual.getId()).isNotNull();
101 assertThat(actual.getAttributes()).isEqualTo(Map.of("a", "1", "b", "2"));
102 assertThat(actual.getDescription()).isEqualTo("My Description");
103 assertThat(actual.getCreatedAt()).isNotNull();
104 assertThat(actual.getCreatedBy()).isEqualTo(nameOfDefaultUser);
105 assertThat(actual.getName()).isEqualTo(name);
106 assertThat(actual.getDataObjectIds()).isEmpty();
107 assertThat(actual.getUpdatedAt()).isNull();
108 assertThat(actual.getUpdatedBy()).isNull();
109 assertThat(actual.getDefaultFileContainerId()).isEqualTo(defaultFileContainerIO.getId());
110 }
111
112 @Test
113 @Order(1)
114 public void postCollectionTest_withDefaultContainer_FailureDefaultFileContainerDoesNotExist() {
115 var payload = new CollectionIO();
116 name = "CollectionDummy" + System.currentTimeMillis();
117 payload.setName(name);
118 payload.setDescription("My Description");
119 payload.setAttributes(Map.of("a", "1", "b", "2"));
120 payload.setDefaultFileContainerId(9999999L);
121
122 given().spec(requestSpecOfDefaultUser).body(payload).when().post(collectionsURL).then().statusCode(404);
123 }
124
125 @Test
126 @Order(1)
127 public void postCollectionTest_withDefaultContainer_FailureUserHasNoReadPermissionsOnDefaultFileContainer() {
128 var payload = new CollectionIO();
129 name = "CollectionDummy" + System.currentTimeMillis();
130 payload.setName(name);
131 payload.setDescription("My Description");
132 payload.setAttributes(Map.of("a", "1", "b", "2"));
133 payload.setDefaultFileContainerId(defaultFileContainerIO.getId());
134
135 given().spec(requestSpecOfOtherUser).body(payload).when().post(collectionsURL).then().statusCode(403);
136 }
137
138 @Test
139 @Order(2)
140 public void postCollectionTest_WithoutAuth() {
141 var payload = new CollectionIO();
142 payload.setName(name);
143
144 var wrongSpecification = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
145 given().spec(wrongSpecification).body(payload).when().post(collectionsURL).then().statusCode(401);
146 }
147
148 @Test
149 @Order(3)
150 public void postCollectionTest_BadJson() {
151 String payload = "{,}";
152 given().spec(requestSpecOfDefaultUser).body(payload).when().post(collectionsURL).then().statusCode(400);
153 }
154
155 @Test
156 @Order(4)
157 public void postCollectionTest_BadBody() {
158 String payload = "{\"attribute\":\"value\"}";
159 given().spec(requestSpecOfDefaultUser).body(payload).when().post(collectionsURL).then().statusCode(400);
160 }
161
162 @Test
163 @Order(5)
164 public void getCollectionTest_Successful() {
165 CollectionIO actual = given()
166 .spec(requestSpecOfDefaultUser)
167 .when()
168 .get(collectionsURL + "/" + collection.getId())
169 .then()
170 .statusCode(200)
171 .extract()
172 .as(CollectionIO.class);
173
174 assertThat(actual).isEqualTo(collection);
175 assertThat(actual.getDefaultFileContainerId()).isEqualTo(null);
176 }
177
178 @Test
179 @Order(6)
180 public void getCollectionTest_withDataObject() {
181 var payload = new DataObjectIO();
182 payload.setName(name);
183
184 DataObjectIO dataObject = given()
185 .spec(requestSpecOfDefaultUser)
186 .body(payload)
187 .when()
188 .post(collectionsURL + "/" + collection.getId() + "/" + Constants.DATA_OBJECTS)
189 .then()
190 .statusCode(201)
191 .extract()
192 .as(DataObjectIO.class);
193
194 CollectionIO actual = given()
195 .spec(requestSpecOfDefaultUser)
196 .when()
197 .get(collectionsURL + "/" + collection.getId())
198 .then()
199 .statusCode(200)
200 .extract()
201 .as(CollectionIO.class);
202 collection = actual;
203
204 assertThat(actual.getDataObjectIds()).contains(dataObject.getId());
205 }
206
207 @Test
208 @Order(7)
209 public void getCollectionTest_QueryParamNameSuccessful() {
210 CollectionIO[] response = given()
211 .spec(requestSpecOfDefaultUser)
212 .queryParam("name", collection.getName())
213 .when()
214 .get(collectionsURL)
215 .then()
216 .statusCode(200)
217 .extract()
218 .as(CollectionIO[].class);
219
220 assertThat(response).containsExactly(collection);
221 }
222
223 @Test
224 @Order(8)
225 public void getCollectionTest_wrongId_notFound() {
226 ErrorResponse response = given()
227 .spec(requestSpecOfDefaultUser)
228 .when()
229 .get(collectionsURL + "/99999")
230 .then()
231 .statusCode(404)
232 .extract()
233 .as(ErrorResponse.class);
234 assertThat(response.getMessage()).isEqualTo("ID ERROR - Collection with id 99999 is null or deleted");
235 }
236
237 @Test
238 @Order(8)
239 public void getCollectionTest_doesNotExistNegativeId_badRequest() {
240 var actual = given()
241 .spec(requestSpecOfDefaultUser)
242 .when()
243 .get(collectionsURL + "/-1")
244 .then()
245 .statusCode(400)
246 .extract();
247 assertThat(actual.body().asString()).isEqualTo(
248 "{\"title\":\"Constraint Violation\",\"status\":400,\"violations\":[{\"field\":\"getCollection.collectionId\",\"message\":\"must be greater than or equal to 0\"}]}"
249 );
250 }
251
252 @Test
253 @Order(9)
254 public void getCollectionTest_privateCollection_forbidden() {
255 RequestSpecification otherUserRequestSpecification = new RequestSpecBuilder()
256 .setContentType(ContentType.JSON)
257 .addHeader("X-API-KEY", otherUser.getApiKey().getJws())
258 .build();
259
260 ErrorResponse response = given()
261 .spec(otherUserRequestSpecification)
262 .when()
263 .get(collectionsURL + "/" + collection.getId())
264 .then()
265 .statusCode(403)
266 .extract()
267 .as(ErrorResponse.class);
268 assertThat(response.getMessage()).isEqualTo("The requested action is forbidden by the permission policies");
269 }
270
271 @Test
272 @Order(10)
273 public void getCollectionsTest_Successful() {
274 CollectionIO[] response = given()
275 .spec(requestSpecOfDefaultUser)
276 .when()
277 .get(collectionsURL)
278 .then()
279 .statusCode(200)
280 .extract()
281 .as(CollectionIO[].class);
282
283 assertThat(response).contains(collection);
284 }
285
286 @Test
287 @Order(11)
288 public void putCollectionTest_Successful() {
289 collection.setName("CollectionDummyChanged");
290
291 CollectionIO actualResponse = given()
292 .spec(requestSpecOfDefaultUser)
293 .body(collection)
294 .when()
295 .put(collectionsURL + "/" + collection.getId())
296 .then()
297 .statusCode(200)
298 .extract()
299 .as(CollectionIO.class);
300
301 assertThat(actualResponse.getUpdatedAt()).isNotNull();
302 assertThat(actualResponse.getUpdatedBy()).isEqualTo(nameOfDefaultUser);
303 assertThat(actualResponse)
304 .usingRecursiveComparison()
305 .ignoringFields("updatedBy", "updatedAt")
306 .isEqualTo(collection);
307 }
308
309 @Test
310 @Order(12)
311 public void putCollectionTest_withDefaultContainer_SuccessDefaultFileContainerExists() {
312
313 name = "CollectionDummyChanged" + System.currentTimeMillis();
314 collection.setName(name);
315 collection.setDefaultFileContainerId(defaultFileContainerIO.getId());
316
317 CollectionIO actualResponse = given()
318 .spec(requestSpecOfDefaultUser)
319 .body(collection)
320 .when()
321 .put(collectionsURL + "/" + collection.getId())
322 .then()
323 .statusCode(200)
324 .extract()
325 .as(CollectionIO.class);
326
327 assertThat(actualResponse.getUpdatedAt()).isNotNull();
328 assertThat(actualResponse.getUpdatedBy()).isEqualTo(nameOfDefaultUser);
329 assertThat(actualResponse)
330 .usingRecursiveComparison()
331 .ignoringFields("updatedBy", "updatedAt")
332 .isEqualTo(collection);
333 assertThat(actualResponse.getDefaultFileContainerId()).isEqualTo(defaultFileContainerIO.getId());
334 collection = actualResponse;
335 }
336
337 @Test
338 @Order(12)
339 public void putCollectionTest_unsetDefaultContainer_Success() {
340 name = "CollectionDummyChanged" + System.currentTimeMillis();
341 collection.setName(name);
342 collection.setDefaultFileContainerId(null);
343
344 CollectionIO actualResponse = given()
345 .spec(requestSpecOfDefaultUser)
346 .body(collection)
347 .when()
348 .put(collectionsURL + "/" + collection.getId())
349 .then()
350 .statusCode(200)
351 .extract()
352 .as(CollectionIO.class);
353
354 assertThat(actualResponse.getUpdatedAt()).isNotNull();
355 assertThat(actualResponse.getUpdatedBy()).isEqualTo(nameOfDefaultUser);
356 assertThat(actualResponse)
357 .usingRecursiveComparison()
358 .ignoringFields("updatedBy", "updatedAt")
359 .isEqualTo(collection);
360 assertThat(actualResponse.getDefaultFileContainerId()).isNull();
361 collection = actualResponse;
362 }
363
364 @Test
365 @Order(12)
366 public void putCollectionTest_withDefaultContainer_FailureDefaultFileContainerDoesNotExist() {
367 name = "CollectionDummyChanged" + System.currentTimeMillis();
368 collection.setName(name);
369 collection.setDefaultFileContainerId(9999L);
370
371 given()
372 .spec(requestSpecOfDefaultUser)
373 .body(collection)
374 .when()
375 .put(collectionsURL + "/" + collection.getId())
376 .then()
377 .statusCode(404);
378 }
379
380 @Test
381 @Order(12)
382 public void putCollectionTest_withDefaultContainer_FailureUserHasNoReadPermissionsOnDefaultFileContainer() {
383
384 name = "CollectionDummyChanged" + System.currentTimeMillis();
385 collection.setName(name);
386 collection.setDefaultFileContainerId(defaultFileContainerIO.getId());
387
388 given()
389 .spec(requestSpecOfOtherUser)
390 .body(collection)
391 .when()
392 .put(collectionsURL + "/" + collection.getId())
393 .then()
394 .statusCode(403);
395 }
396
397 @Test
398 @Order(13)
399 public void deleteCollectionTest_Successful() {
400 given()
401 .spec(requestSpecOfDefaultUser)
402 .when()
403 .delete(collectionsURL + "/" + collection.getId())
404 .then()
405 .statusCode(204);
406 given().spec(requestSpecOfDefaultUser).when().get(collectionsURL + "/" + collection.getId()).then().statusCode(404);
407
408 given()
409 .spec(requestSpecOfDefaultUser)
410 .when()
411 .delete(collectionsURL + "/" + collectionWithDefaultFileContainer.getId())
412 .then()
413 .statusCode(204);
414 given().spec(requestSpecOfDefaultUser).when().get(collectionsURL + "/" + collection.getId()).then().statusCode(404);
415 }
416
417 @Test
418 @Order(14)
419 public void getinitialHEADVersion() {
420 if (VersioningFeatureToggle.isEnabled()) {
421 var payload = new CollectionIO();
422 VersionizedCollectionName = "VersionizedCollection";
423 payload.setName(VersionizedCollectionName);
424 payload.setDescription(VersionizedCollectionName);
425 CollectionIO actual = given()
426 .spec(requestSpecOfDefaultUser)
427 .body(payload)
428 .when()
429 .post(collectionsURL)
430 .then()
431 .statusCode(201)
432 .extract()
433 .as(CollectionIO.class);
434 VersionizedCollectionShepardId = actual.getId();
435 VersionIO[] versions = given()
436 .spec(requestSpecOfDefaultUser)
437 .when()
438 .get(collectionsURL + "/" + VersionizedCollectionShepardId + "/versions")
439 .then()
440 .statusCode(200)
441 .extract()
442 .as(VersionIO[].class);
443 assertEquals(versions.length, 1);
444 VersionIO HEADVersion = versions[0];
445 assertEquals(HEADVersion.getName(), "HEAD");
446 assertEquals(HEADVersion.getDescription(), "HEAD version");
447 }
448 }
449
450 @Test
451 @Order(15)
452 public void createNewVersion() {
453 if (VersioningFeatureToggle.isEnabled()) {
454 VersionIO newVersion = new VersionIO();
455 newVersion.setName("first version");
456 newVersion.setDescription("first version of versionized collection");
457 firstVersion = given()
458 .spec(requestSpecOfDefaultUser)
459 .body(newVersion)
460 .when()
461 .post(collectionsURL + "/" + VersionizedCollectionShepardId + "/versions")
462 .then()
463 .statusCode(201)
464 .extract()
465 .as(VersionIO.class);
466 assertEquals(firstVersion.getName(), newVersion.getName());
467 assertEquals(firstVersion.getDescription(), newVersion.getDescription());
468 }
469 }
470
471 @Test
472 @Order(16)
473 public void createSecondVersion() {
474 if (VersioningFeatureToggle.isEnabled()) {
475 VersionIO newVersion = new VersionIO();
476 newVersion.setName("second version");
477 newVersion.setDescription("second version of versionized collection");
478 secondVersion = given()
479 .spec(requestSpecOfDefaultUser)
480 .body(newVersion)
481 .when()
482 .post(collectionsURL + "/" + VersionizedCollectionShepardId + "/versions")
483 .then()
484 .statusCode(201)
485 .extract()
486 .as(VersionIO.class);
487 assertEquals(secondVersion.getName(), newVersion.getName());
488 assertEquals(secondVersion.getDescription(), newVersion.getDescription());
489 }
490 }
491
492 @Test
493 @Order(17)
494 public void getAllVersions() {
495 if (VersioningFeatureToggle.isEnabled()) {
496 VersionIO[] versions = given()
497 .spec(requestSpecOfDefaultUser)
498 .when()
499 .get(collectionsURL + "/" + VersionizedCollectionShepardId + "/versions")
500 .then()
501 .statusCode(200)
502 .extract()
503 .as(VersionIO[].class);
504 assertEquals(versions.length, 3);
505 VersionIO HEADVersionCandidate = null;
506 VersionIO firstVersionCandidate = null;
507 VersionIO secondVersionCandidate = null;
508 for (int i = 0; i < 3; i++) {
509 if (versions[i].getName().equals("HEAD")) HEADVersionCandidate = versions[i];
510 if (versions[i].getUid().equals(firstVersion.getUid())) firstVersionCandidate = versions[i];
511 if (versions[i].getUid().equals(secondVersion.getUid())) secondVersionCandidate = versions[i];
512 }
513 assertNotNull(HEADVersionCandidate);
514 assertNotNull(firstVersionCandidate);
515 assertNotNull(secondVersionCandidate);
516 assertEquals(HEADVersionCandidate.getPredecessorUUID(), secondVersionCandidate.getUid());
517 assertEquals(secondVersionCandidate.getPredecessorUUID(), firstVersionCandidate.getUid());
518 assertNull(firstVersionCandidate.getPredecessorUUID());
519 }
520 }
521
522 @Test
523 @Order(18)
524 public void modifyHEADCollection() {
525 if (VersioningFeatureToggle.isEnabled()) {
526 CollectionIO newVersionizedCollection = new CollectionIO();
527 newVersionizedCollectionName = "updated versionized collection";
528 newVersionizedCollection.setName(newVersionizedCollectionName);
529 CollectionIO actual = given()
530 .spec(requestSpecOfDefaultUser)
531 .body(newVersionizedCollection)
532 .when()
533 .put(collectionsURL + "/" + VersionizedCollectionShepardId)
534 .then()
535 .statusCode(200)
536 .extract()
537 .as(CollectionIO.class);
538 assertEquals(actual.getName(), newVersionizedCollectionName);
539 assertEquals(actual.getId(), VersionizedCollectionShepardId);
540 }
541 }
542
543 @Test
544 @Order(19)
545 public void retrieveModifiedHEADCollection() {
546 if (VersioningFeatureToggle.isEnabled()) {
547 CollectionIO actual = given()
548 .spec(requestSpecOfDefaultUser)
549 .when()
550 .get(collectionsURL + "/" + VersionizedCollectionShepardId)
551 .then()
552 .statusCode(200)
553 .extract()
554 .as(CollectionIO.class);
555 assertEquals(actual.getName(), newVersionizedCollectionName);
556 }
557 }
558
559 @Test
560 @Order(20)
561 public void retrieveSecondVersion() {
562 if (VersioningFeatureToggle.isEnabled()) {
563 VersionIO actual = given()
564 .spec(requestSpecOfDefaultUser)
565 .when()
566 .get(collectionsURL + "/" + VersionizedCollectionShepardId + "/versions/" + secondVersion.getUid().toString())
567 .then()
568 .statusCode(200)
569 .extract()
570 .as(VersionIO.class);
571 assertEquals(actual, secondVersion);
572 }
573 }
574
575 @Test
576 @Order(21)
577 public void retrieveSecondVersionOfCollection() {
578 if (VersioningFeatureToggle.isEnabled()) {
579 CollectionIO actual = given()
580 .spec(requestSpecOfDefaultUser)
581 .queryParam("versionUid", secondVersion.getUid().toString())
582 .when()
583 .get(collectionsURL + "/" + VersionizedCollectionShepardId)
584 .then()
585 .statusCode(200)
586 .extract()
587 .as(CollectionIO.class);
588 assertEquals(actual.getName(), VersionizedCollectionName);
589 }
590 }
591
592 @Test
593 @Order(22)
594 public void updateCollection_deleteAttribute_successfullyDeleteAttribute() {
595
596 CollectionIO collectionIO = new CollectionIO();
597 collectionIO.setName("Some name");
598 collectionIO.setAttributes(Map.of("name", "my data object"));
599 CollectionIO collection = given()
600 .spec(requestSpecOfDefaultUser)
601 .body(collectionIO)
602 .when()
603 .post(collectionsURL)
604 .then()
605 .statusCode(201)
606 .extract()
607 .as(CollectionIO.class);
608
609
610 collectionIO.setAttributes(Map.of());
611 given()
612 .spec(requestSpecOfDefaultUser)
613 .body(collectionIO)
614 .when()
615 .put(collectionsURL + "/" + collection.getId())
616 .then()
617 .statusCode(200)
618 .extract()
619 .as(CollectionIO.class);
620
621
622 CollectionIO updatedCollection = given()
623 .spec(requestSpecOfDefaultUser)
624 .when()
625 .get(collectionsURL + "/" + collection.getId())
626 .then()
627 .statusCode(200)
628 .extract()
629 .as(CollectionIO.class);
630 assertEquals(Map.of(), updatedCollection.getAttributes());
631 }
632 }