From ac7ea1913385b8e1a17432fa99ffdf02ba754850 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Tue, 12 Dec 2023 11:14:14 -0500 Subject: [PATCH 1/3] fix: Better error message when Transaction/WriteBatch is modified after commit. --- .../google/cloud/firestore/UpdateBuilder.java | 5 ++- .../cloud/firestore/LocalFirestoreHelper.java | 16 ++++++++ .../cloud/firestore/TransactionTest.java | 36 ++++++++++++++++++ .../cloud/firestore/WriteBatchTest.java | 37 +++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UpdateBuilder.java b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UpdateBuilder.java index d7f98808a1..87cf833079 100644 --- a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UpdateBuilder.java +++ b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UpdateBuilder.java @@ -161,7 +161,10 @@ private T performCreate( private void verifyNotCommitted() { Preconditions.checkState( - !isCommitted(), "Cannot modify a WriteBatch that has already been committed."); + !isCommitted(), + String.format( + "Cannot modify a %s that has already been committed.", + this.getClass().getSimpleName())); } /** diff --git a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/LocalFirestoreHelper.java b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/LocalFirestoreHelper.java index b86cc0bc95..9ee7f6ff59 100644 --- a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/LocalFirestoreHelper.java +++ b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/LocalFirestoreHelper.java @@ -1242,4 +1242,20 @@ public static List bundleToElementList(ByteBuffer bundle) { return result; } + + @FunctionalInterface + interface VoidFunction { + void apply(); + } + + static void assertException(VoidFunction voidFunction, String expectedErrorMessage) { + String errorMessage = ""; + try { + voidFunction.apply(); + } catch (Exception e) { + errorMessage = e.getMessage(); + } finally { + assertEquals(errorMessage, expectedErrorMessage); + } + } } diff --git a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java index eeef59e0c8..0ddb145ad5 100644 --- a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java +++ b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java @@ -36,6 +36,7 @@ import static com.google.cloud.firestore.LocalFirestoreHelper.rollbackResponse; import static com.google.cloud.firestore.LocalFirestoreHelper.set; import static com.google.cloud.firestore.LocalFirestoreHelper.update; +import static com.google.cloud.firestore.it.ITQueryTest.map; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -959,6 +960,41 @@ public void getShouldThrowWhenInvokedAfterAWriteWithAnAggregateQuery() throws Ex assertThat(executionException.getCause()).isInstanceOf(IllegalStateException.class); } + @Test + public void givesProperErrorMessageForCommittedTransaction() throws Exception { + doReturn(beginResponse()) + .doReturn(commitResponse(0, 0)) + .when(firestoreMock) + .sendRequest( + requestCapture.capture(), ArgumentMatchers.>any()); + String expectedErrorMessage = "Cannot modify a Transaction that has already been committed."; + + // Commit a transaction. + Transaction t = firestoreMock.runTransaction(transaction -> transaction).get(); + + // Then run other operations in the same transaction. + LocalFirestoreHelper.assertException( + () -> { + t.set(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + }, + expectedErrorMessage); + LocalFirestoreHelper.assertException( + () -> { + t.update(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + }, + expectedErrorMessage); + LocalFirestoreHelper.assertException( + () -> { + t.create(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + }, + expectedErrorMessage); + LocalFirestoreHelper.assertException( + () -> { + t.delete(firestoreMock.collection("foo").document("bar")); + }, + expectedErrorMessage); + } + private ApiException exception(Status.Code code, boolean shouldRetry) { return exception(code, "Test exception", shouldRetry); } diff --git a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java index 92ca905c79..5f1bd8e43b 100644 --- a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java +++ b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java @@ -341,4 +341,41 @@ public void deleteDocument() throws Exception { CommitRequest commitRequest = commitCapture.getValue(); assertEquals(commit(writes.toArray(new Write[] {})), commitRequest); } + + @Test + public void throwsWhenModifyingACommittedWriteBatch() throws Exception { + doReturn(commitResponse(0, 0)) + .when(firestoreMock) + .sendRequest( + commitCapture.capture(), + ArgumentMatchers.>any()); + + String expectedErrorMessage = "Cannot modify a WriteBatch that has already been committed."; + + // Commit a batch. + WriteBatch batch = firestoreMock.batch(); + batch.commit().get(); + + // Then run other operations in the same batch. + LocalFirestoreHelper.assertException( + () -> { + batch.set(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + }, + expectedErrorMessage); + LocalFirestoreHelper.assertException( + () -> { + batch.update(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + }, + expectedErrorMessage); + LocalFirestoreHelper.assertException( + () -> { + batch.create(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + }, + expectedErrorMessage); + LocalFirestoreHelper.assertException( + () -> { + batch.delete(firestoreMock.collection("foo").document("bar")); + }, + expectedErrorMessage); + } } From 12a85516e3f9e97a296ab524b115809ded7ce278 Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Fri, 15 Dec 2023 10:06:18 -0500 Subject: [PATCH 2/3] Address feedback. --- .../com/google/cloud/firestore/TransactionTest.java | 10 ++++++---- .../com/google/cloud/firestore/WriteBatchTest.java | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java index 0ddb145ad5..df9c72cedb 100644 --- a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java +++ b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java @@ -969,28 +969,30 @@ public void givesProperErrorMessageForCommittedTransaction() throws Exception { requestCapture.capture(), ArgumentMatchers.>any()); String expectedErrorMessage = "Cannot modify a Transaction that has already been committed."; + DocumentReference docRef = firestoreMock.collection("foo").document("bar"); + // Commit a transaction. Transaction t = firestoreMock.runTransaction(transaction -> transaction).get(); // Then run other operations in the same transaction. LocalFirestoreHelper.assertException( () -> { - t.set(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + t.set(docRef, map("foo", "bar")); }, expectedErrorMessage); LocalFirestoreHelper.assertException( () -> { - t.update(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + t.update(docRef, map("foo", "bar")); }, expectedErrorMessage); LocalFirestoreHelper.assertException( () -> { - t.create(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + t.create(docRef, map("foo", "bar")); }, expectedErrorMessage); LocalFirestoreHelper.assertException( () -> { - t.delete(firestoreMock.collection("foo").document("bar")); + t.delete(docRef); }, expectedErrorMessage); } diff --git a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java index 5f1bd8e43b..1fec528406 100644 --- a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java +++ b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/WriteBatchTest.java @@ -352,6 +352,8 @@ public void throwsWhenModifyingACommittedWriteBatch() throws Exception { String expectedErrorMessage = "Cannot modify a WriteBatch that has already been committed."; + DocumentReference docRef = firestoreMock.collection("foo").document("bar"); + // Commit a batch. WriteBatch batch = firestoreMock.batch(); batch.commit().get(); @@ -359,22 +361,22 @@ public void throwsWhenModifyingACommittedWriteBatch() throws Exception { // Then run other operations in the same batch. LocalFirestoreHelper.assertException( () -> { - batch.set(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + batch.set(docRef, map("foo", "bar")); }, expectedErrorMessage); LocalFirestoreHelper.assertException( () -> { - batch.update(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + batch.update(docRef, map("foo", "bar")); }, expectedErrorMessage); LocalFirestoreHelper.assertException( () -> { - batch.create(firestoreMock.collection("foo").document("bar"), map("foo", "bar")); + batch.create(docRef, map("foo", "bar")); }, expectedErrorMessage); LocalFirestoreHelper.assertException( () -> { - batch.delete(firestoreMock.collection("foo").document("bar")); + batch.delete(docRef); }, expectedErrorMessage); } From 3be963657553fd3f43c17b68197c0e96435d5abd Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Fri, 15 Dec 2023 15:08:21 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20po?= =?UTF-8?q?st-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 681a74b699..8f1f51f62d 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ If you are using Maven without the BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies: ```Groovy -implementation platform('com.google.cloud:libraries-bom:26.28.0') +implementation platform('com.google.cloud:libraries-bom:26.29.0') implementation 'com.google.cloud:google-cloud-firestore' ```