From 5b1a2e41c0a4eb3b653908e2dd9b39aa06845baf Mon Sep 17 00:00:00 2001 From: "J.R. Hill" Date: Fri, 17 Nov 2023 16:52:14 -0800 Subject: [PATCH] test(client): add tests on non-transactional write --- .../openfga/sdk/api/client/OpenFgaClient.java | 2 +- .../sdk/api/client/OpenFgaClientTest.java | 48 +++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java b/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java index 4818c35..35f02ec 100644 --- a/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java +++ b/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java @@ -327,7 +327,7 @@ private CompletableFuture writeTransactions( } private List> chunksOf(int chunkSize, List list) { - int nChunks = list.size() / chunkSize; + int nChunks = (int) Math.ceil(list.size() / (double) chunkSize); int finalEndExclusive = list.size(); List> chunks = new ArrayList<>(); diff --git a/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java b/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java index f766c1d..fb06d0d 100644 --- a/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java +++ b/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java @@ -49,13 +49,12 @@ public class OpenFgaClientTest { private OpenFgaClient fga; private ClientConfiguration clientConfiguration; private HttpClientMock mockHttpClient; - private HttpClient.Builder mockHttpClientBuilder; @BeforeEach public void beforeEachTest() throws Exception { mockHttpClient = new HttpClientMock(); - mockHttpClientBuilder = mock(HttpClient.Builder.class); + HttpClient.Builder mockHttpClientBuilder = mock(HttpClient.Builder.class); when(mockHttpClientBuilder.executor(any())).thenReturn(mockHttpClientBuilder); when(mockHttpClientBuilder.build()).thenReturn(mockHttpClient); @@ -955,7 +954,7 @@ public void read_emptyRequestSendsNoTupleKey() throws Exception { ClientReadRequest request = new ClientReadRequest(); // When - ClientReadResponse response = fga.read(request).get(); + fga.read(request).get(); // Then mockHttpClient.verify().post(postUrl).withBody(is(expectedBody)).called(1); @@ -1088,6 +1087,46 @@ public void writeTest_deletes() throws Exception { mockHttpClient.verify().post(postPath).withBody(is(expectedBody)).called(1); } + @Test + public void writeTest_transactions() throws Exception { + // Given + String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; + String tupleBody = String.format("{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}", DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + ClientTupleKey tuple = new ClientTupleKey() + ._object(DEFAULT_OBJECT) + .relation(DEFAULT_RELATION) + .user(DEFAULT_USER); + String write2Body = String.format( + "{\"writes\":{\"tuple_keys\":[%s,%s]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", + tupleBody, tupleBody, DEFAULT_AUTH_MODEL_ID); + String write1Body = String.format( + "{\"writes\":{\"tuple_keys\":[%s]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", + tupleBody, DEFAULT_AUTH_MODEL_ID); + String delete2Body = String.format( + "{\"writes\":null,\"deletes\":{\"tuple_keys\":[%s,%s]},\"authorization_model_id\":\"%s\"}", + tupleBody, tupleBody, DEFAULT_AUTH_MODEL_ID); + String delete1Body = String.format( + "{\"writes\":null,\"deletes\":{\"tuple_keys\":[%s]},\"authorization_model_id\":\"%s\"}", + tupleBody, DEFAULT_AUTH_MODEL_ID); + mockHttpClient.onPost(postPath).withBody(isOneOf(write2Body, write1Body, delete2Body, delete1Body)).doReturn(200, EMPTY_RESPONSE_BODY); + ClientWriteRequest request = new ClientWriteRequest() + .writes(List.of(tuple, tuple, tuple, tuple, tuple)) + .deletes(List.of(tuple, tuple, tuple, tuple, tuple)); + ClientWriteOptions options = new ClientWriteOptions() + .enableTransactions(true) + .transactionChunkSize(2); + + // When + var response = fga.write(request, options).get(); + + // Then + mockHttpClient.verify().post(postPath).withBody(is(write2Body)).called(2); + mockHttpClient.verify().post(postPath).withBody(is(write1Body)).called(1); + mockHttpClient.verify().post(postPath).withBody(is(delete2Body)).called(2); + mockHttpClient.verify().post(postPath).withBody(is(delete1Body)).called(1); + assertEquals(200, response.getStatusCode()); + } + @Test public void writeTuplesTest() throws Exception { // Given @@ -1354,8 +1393,7 @@ public void batchCheck_twentyTimes() throws Exception { ClientBatchCheckOptions options = new ClientBatchCheckOptions().authorizationModelId(DEFAULT_AUTH_MODEL_ID); // When - List responses = - fga.batchCheck(requests, options).get(); + fga.batchCheck(requests, options).get(); // Then mockHttpClient.verify().post(postUrl).withBody(is(expectedBody)).called(20);