Skip to content

Commit

Permalink
CIRCSTORE-521 create test
Browse files Browse the repository at this point in the history
  • Loading branch information
roman-barannyk committed Aug 22, 2024
1 parent d6b9f8d commit d352bfd
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 22 deletions.
3 changes: 2 additions & 1 deletion src/main/java/org/folio/service/BatchResourceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ public Future<Void> executeBatchUpdate(
if (updateResult.failed()) {
log.warn("Batch update rejected", updateResult.cause());

// Rollback transaction and keep original cause.
postgresClient.rollbackTx(connectionResult, rollback -> {
onFinishHandler.handle(Future.failedFuture(updateResult.cause()));
onFinishHandler.handle(failedFuture(updateResult.cause()));
promise.fail(updateResult.cause());
});
} else {
Expand Down
99 changes: 81 additions & 18 deletions src/test/java/org/folio/rest/api/RequestBatchAPITest.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package org.folio.rest.api;

import static org.awaitility.Awaitility.await;
import static org.folio.rest.api.RequestsApiTest.requestStorageUrl;
import static org.folio.rest.api.StorageTestSuite.TENANT_ID;
import static org.folio.rest.api.StorageTestSuite.storageUrl;
import static org.folio.rest.support.kafka.FakeKafkaConsumer.getRequestQueueReorderingEvents;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;

import java.net.URL;
import java.util.Arrays;
Expand All @@ -16,6 +19,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import org.folio.rest.impl.RequestsBatchAPI;
import org.folio.rest.jaxrs.model.Request;
import org.folio.rest.support.ApiTests;
Expand Down Expand Up @@ -52,8 +56,8 @@ public void checkIdsAfterEach() {
public void canUpdateRequestPositionsInBatch() throws Exception {
UUID itemId = UUID.randomUUID();

JsonObject firstRequest = createRequestForItemAtPosition(itemId, 1);
JsonObject secondRequest = createRequestForItemAtPosition(itemId, 2);
JsonObject firstRequest = createRequestAtPosition(itemId, null, 1);
JsonObject secondRequest = createRequestAtPosition(itemId, null, 2);

ReorderRequest firstReorderRequest = new ReorderRequest(firstRequest, 2);
ReorderRequest secondReorderRequest = new ReorderRequest(secondRequest, 1);
Expand Down Expand Up @@ -81,8 +85,8 @@ public void canUpdateRequestPositionsInBatch() throws Exception {
public void canCloseRequestsInBatch() throws Exception {
UUID itemId = UUID.randomUUID();

JsonObject firstRequest = createRequestForItemAtPosition(itemId, 1);
JsonObject secondRequest = createRequestForItemAtPosition(itemId, 2);
JsonObject firstRequest = createRequestAtPosition(itemId, null, 1);
JsonObject secondRequest = createRequestAtPosition(itemId, null, 2);

firstRequest.put("status", Request.Status.CLOSED_FILLED.value());
firstRequest.remove("position");
Expand Down Expand Up @@ -111,8 +115,8 @@ public void canCloseRequestsInBatch() throws Exception {
public void canUpdateRequestFulfillmentPreferenceInBatch() throws Exception {
UUID itemId = UUID.randomUUID();

JsonObject firstRequest = createRequestForItemAtPosition(itemId, 1);
JsonObject secondRequest = createRequestForItemAtPosition(itemId, 2);
JsonObject firstRequest = createRequestAtPosition(itemId, null, 1);
JsonObject secondRequest = createRequestAtPosition(itemId, null, 2);

firstRequest.put("fulfillmentPreference", "Delivery");
secondRequest.put("fulfillmentPreference", "Delivery");
Expand Down Expand Up @@ -153,8 +157,8 @@ public void willAbortBatchUpdateOnPopulateMetadataException() throws Exception {
public void willAbortBatchUpdateForRequestsAtTheSamePositionInAnItemsQueue() throws Exception {
UUID itemId = UUID.randomUUID();

JsonObject firstRequest = createRequestForItemAtPosition(itemId, 1);
JsonObject secondRequest = createRequestForItemAtPosition(itemId, 2);
JsonObject firstRequest = createRequestAtPosition(itemId, null, 1);
JsonObject secondRequest = createRequestAtPosition(itemId, null, 2);

JsonResponse reorderResponse = attemptReorderRequests(ResponseHandler::json,
new ReorderRequest(firstRequest, 1),
Expand All @@ -170,8 +174,8 @@ public void willAbortBatchUpdateForRequestsAtTheSamePositionInAnItemsQueue() thr
public void willAbortBatchUpdateWhenOnlyOnePositionIsModified() throws Exception {
UUID itemId = UUID.randomUUID();

JsonObject firstRequest = createRequestForItemAtPosition(itemId, 1);
JsonObject secondRequest = createRequestForItemAtPosition(itemId, 2);
JsonObject firstRequest = createRequestAtPosition(itemId, null, 1);
JsonObject secondRequest = createRequestAtPosition(itemId, null, 2);

JsonResponse reorderResponse = attemptReorderRequests(ResponseHandler::json,
new ReorderRequest(firstRequest, 2)
Expand All @@ -186,8 +190,8 @@ public void willAbortBatchUpdateWhenOnlyOnePositionIsModified() throws Exception
public void willAbortBatchUpdateOnNullPointerExceptionDueToNoIdInRequest() throws Exception {
UUID itemId = UUID.randomUUID();

JsonObject firstRequest = createRequestForItemAtPosition(itemId, 1);
JsonObject secondRequest = createRequestForItemAtPosition(itemId, 2);
JsonObject firstRequest = createRequestAtPosition(itemId, null, 1);
JsonObject secondRequest = createRequestAtPosition(itemId, null, 2);

JsonObject firstRequestCopy = firstRequest.copy();
firstRequestCopy.remove("id");
Expand All @@ -205,7 +209,7 @@ public void willAbortBatchUpdateOnNullPointerExceptionDueToNoIdInRequest() throw
public void cannotInjectSqlThroughRequestId() throws Exception {
UUID itemId = UUID.randomUUID();

JsonObject firstRequest = createRequestForItemAtPosition(itemId, 1);
JsonObject firstRequest = createRequestAtPosition(itemId, null, 1);

JsonObject firstRequestCopy = firstRequest.copy();
firstRequestCopy.put("id", "1'; DELETE FROM request where id::text is not '1");
Expand All @@ -219,6 +223,37 @@ public void cannotInjectSqlThroughRequestId() throws Exception {
assertRequestsNotUpdated(itemId, firstRequest);
}

@Test
public void canUpdateRequestPositionsInBatchForTheInstance() throws Exception {
UUID instanceId = UUID.randomUUID();

JsonObject firstRequest = createRequestAtPosition(null, instanceId, 1);
JsonObject secondRequest = createRequestAtPosition(null, instanceId, 2);

ReorderRequest firstReorderRequest = new ReorderRequest(firstRequest, 2);
ReorderRequest secondReorderRequest = new ReorderRequest(secondRequest, 1);

reorderRequests(
firstReorderRequest,
secondReorderRequest
);

JsonObject requestsForInstanceReply = getAllRequestsForInstance(instanceId);
assertThat(requestsForInstanceReply.getInteger("totalRecords"), is(2));
JsonArray requestsFromDb = requestsForInstanceReply.getJsonArray("requests");
assertThat(requestsFromDb.size(), is(2));
JsonObject [] r = new JsonObject [] { requestsFromDb.getJsonObject(0), requestsFromDb.getJsonObject(1) };
if (r[0].getInteger("position") == 2) {
r = new JsonObject [] { r[1], r[0] };
}
assertThat(r[0].getInteger("position"), is(1));
assertThat(r[1].getInteger("position"), is(2));
assertThat(r[0].getString("id"), is(secondRequest.getString("id")));
assertThat(r[1].getString("id"), is(firstRequest.getString("id")));

assertCreateRequestQueueReorderingEvent();
}

private JsonObject getAllRequestsForItem(UUID itemId) throws Exception {
CompletableFuture<JsonResponse> getRequestsCompleted = new CompletableFuture<>();

Expand All @@ -228,10 +263,30 @@ private JsonObject getAllRequestsForItem(UUID itemId) throws Exception {
return getRequestsCompleted.get(5, TimeUnit.SECONDS).getJson();
}

private JsonObject createRequestForItemAtPosition(UUID itemId, int position) throws Exception {
JsonObject request = createEntity(
new RequestRequestBuilder()
private JsonObject getAllRequestsForInstance(UUID instanceId) throws Exception {
CompletableFuture<JsonResponse> getRequestsCompleted = new CompletableFuture<>();

client.get(requestStorageUrl() + String.format("?query=instanceId==%s", instanceId),
TENANT_ID, ResponseHandler.json(getRequestsCompleted));

return getRequestsCompleted.get(5, TimeUnit.SECONDS).getJson();
}

private JsonObject createRequestAtPosition(UUID itemId, UUID instanceId, int position)
throws Exception {

RequestRequestBuilder requestBuilder = null;
if (instanceId != null) {
requestBuilder = new RequestRequestBuilder()
.withInstanceId(instanceId)
.withRequestLevel("Title");
} else {
requestBuilder = new RequestRequestBuilder()
.withItemId(itemId)
.withRequestLevel("Item");
}
JsonObject request = createEntity(
requestBuilder
.withPosition(position)
.recall()
.toHoldShelf()
Expand All @@ -240,7 +295,11 @@ private JsonObject createRequestForItemAtPosition(UUID itemId, int position) thr
requestStorageUrl()
).getJson();

assertThat(request.getString("itemId"), is(itemId.toString()));
if (itemId != null) {
assertThat(request.getString("itemId"), is(itemId.toString()));
} else {
assertThat(request.getString("instanceId"), is(instanceId.toString()));
}
assertThat(request.getInteger("position"), is(position));

return request;
Expand Down Expand Up @@ -327,6 +386,10 @@ private void assertValidationError(
errorMessageMatcher);
}

public static void assertCreateRequestQueueReorderingEvent() {
await().until(() -> getRequestQueueReorderingEvents().size(), greaterThan(0));
}

/**
* Holder for request reorder operation. Holds request and new position for it.
*/
Expand Down
17 changes: 14 additions & 3 deletions src/test/java/org/folio/rest/support/kafka/FakeKafkaConsumer.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public final class FakeKafkaConsumer {
private static final String REQUEST_TOPIC_NAME = "folio.test_tenant.circulation.request";
private static final String CHECKIN_TOPIC_NAME = "folio.test_tenant.circulation.check-in";
private static final String CIRCULATION_RULES_TOPIC_NAME = "folio.test_tenant.circulation.rules";
private static final String REQUEST_QUEUE_REORDERING_TOPIC_NAME = "folio.test_tenant.circulation.request-queue-reordering";

private static final Map<String, List<KafkaConsumerRecord<String, JsonObject>>> loanEvents =
new ConcurrentHashMap<>();
Expand All @@ -36,19 +37,21 @@ public final class FakeKafkaConsumer {
new ConcurrentHashMap<>();
private static final Map<String, List<KafkaConsumerRecord<String, JsonObject>>> circulationRulesEvents =
new ConcurrentHashMap<>();

private static final Map<String, List<KafkaConsumerRecord<String, JsonObject>>> requestQueueReorderingEvents =
new ConcurrentHashMap<>();
private static final Map<String, Map<String, List<KafkaConsumerRecord<String, JsonObject>>>> topicToEvents = Map.of(
LOAN_TOPIC_NAME, loanEvents,
REQUEST_TOPIC_NAME, requestEvents,
CHECKIN_TOPIC_NAME, checkInEvents,
CIRCULATION_RULES_TOPIC_NAME, circulationRulesEvents
CIRCULATION_RULES_TOPIC_NAME, circulationRulesEvents,
REQUEST_QUEUE_REORDERING_TOPIC_NAME, requestQueueReorderingEvents
);

public FakeKafkaConsumer consume(Vertx vertx) {
final KafkaConsumer<String, JsonObject> consumer = create(vertx, consumerProperties());

consumer.subscribe(Set.of(LOAN_TOPIC_NAME, REQUEST_TOPIC_NAME, CHECKIN_TOPIC_NAME,
CIRCULATION_RULES_TOPIC_NAME));
CIRCULATION_RULES_TOPIC_NAME, REQUEST_QUEUE_REORDERING_TOPIC_NAME));

consumer.handler(message -> {
var recordEvents = topicToEvents.get(message.topic());
Expand All @@ -69,6 +72,7 @@ public static void removeAllEvents() {
requestEvents.clear();
checkInEvents.clear();
circulationRulesEvents.clear();
requestQueueReorderingEvents.clear();
}

public static int getAllPublishedLoanCount() {
Expand All @@ -94,6 +98,13 @@ public static Collection<KafkaConsumerRecord<String, JsonObject>> getCirculation
.orElseGet(Collections::emptyList);
}

public static Collection<KafkaConsumerRecord<String, JsonObject>> getRequestQueueReorderingEvents() {
return requestQueueReorderingEvents.values()
.stream()
.findFirst()
.orElseGet(Collections::emptyList);
}

public static KafkaConsumerRecord<String, JsonObject> getFirstLoanEvent(String loanId) {
return getFirstEvent(getLoanEvents(loanId));
}
Expand Down

0 comments on commit d352bfd

Please sign in to comment.