From cf0e01a47258c46a1b4431920b8d7cd24ae9b801 Mon Sep 17 00:00:00 2001
From: Joe Wang <106995533+JoeWang1127@users.noreply.github.com>
Date: Tue, 11 Apr 2023 20:47:15 +0000
Subject: [PATCH] feat: add stream methods for `Page` (#1425)
* feat: add stream methods
* add clirr ignore rule
* add comments for stream methods
* fix format
* add tests for stream methods
* modify tests
* add showcase tests
* Revert "add showcase tests"
This reverts commit 6fcfa9b595b1a6f3c380366855d965c596d7c2f7.
* add a integration test for stream methods
* add copyright
* change client builder
* set page token
* remove page token in stream all
* remove page token in stream values
* modify paged request
* modify tests
* create users only once
* delete showcase it
* add comments
* change unit test name
---
gax-java/gax/clirr-ignored-differences.xml | 10 ++++
.../java/com/google/api/gax/paging/Page.java | 21 +++++++-
.../com/google/api/gax/rpc/PagingTest.java | 48 +++++++++++++++++++
3 files changed, 77 insertions(+), 2 deletions(-)
create mode 100644 gax-java/gax/clirr-ignored-differences.xml
diff --git a/gax-java/gax/clirr-ignored-differences.xml b/gax-java/gax/clirr-ignored-differences.xml
new file mode 100644
index 0000000000..dcc0be350d
--- /dev/null
+++ b/gax-java/gax/clirr-ignored-differences.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ 7012
+ com/google/api/gax/paging/Page
+ * stream*(*)
+
+
diff --git a/gax-java/gax/src/main/java/com/google/api/gax/paging/Page.java b/gax-java/gax/src/main/java/com/google/api/gax/paging/Page.java
index abacde970c..de1cbc0ab9 100644
--- a/gax-java/gax/src/main/java/com/google/api/gax/paging/Page.java
+++ b/gax-java/gax/src/main/java/com/google/api/gax/paging/Page.java
@@ -29,6 +29,9 @@
*/
package com.google.api.gax.paging;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
/**
* A Page object wraps an API list method response.
*
@@ -52,12 +55,26 @@ public interface Page {
Page getNextPage();
/**
- * Returns an iterable that traverses all of the elements of the underlying data source. The data
- * is fetched lazily page by page, where each page may contain multiple elements. A new page is
+ * Returns an iterable that traverses all the elements of the underlying data source. The data is
+ * fetched lazily page by page, where each page may contain multiple elements. A new page is
* fetched whenever the elements of any particular page are exhausted.
*/
Iterable iterateAll();
/** Returns an iterable over the elements in this page. */
Iterable getValues();
+
+ /**
+ * Returns a stream that traverses all the elements of the underlying data source. The data is
+ * fetched lazily page by page, where each page may contain multiple elements. A new page is
+ * fetched whenever the elements of any particular page are exhausted.
+ */
+ default Stream streamAll() {
+ return StreamSupport.stream(iterateAll().spliterator(), false);
+ }
+
+ /** Returns a stream over the elements in this page. */
+ default Stream streamValues() {
+ return StreamSupport.stream(getValues().spliterator(), false);
+ }
}
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/rpc/PagingTest.java b/gax-java/gax/src/test/java/com/google/api/gax/rpc/PagingTest.java
index e1655b6bf7..f7f02c0f74 100644
--- a/gax-java/gax/src/test/java/com/google/api/gax/rpc/PagingTest.java
+++ b/gax-java/gax/src/test/java/com/google/api/gax/rpc/PagingTest.java
@@ -133,6 +133,54 @@ public void pagedByPage() {
Truth.assertThat(requestCapture.getAllValues()).containsExactly(0, 2, 4).inOrder();
}
+ @Test
+ public void streamValues_streamIsCorrectPerPage() {
+ ArgumentCaptor requestCapture = ArgumentCaptor.forClass(Integer.class);
+ Mockito.when(callIntList.futureCall(requestCapture.capture(), Mockito.any()))
+ .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1, 2)))
+ .thenReturn(ApiFutures.immediateFuture(Arrays.asList(3, 4)))
+ .thenReturn(ApiFutures.immediateFuture(Collections.emptyList()));
+
+ Page page =
+ FakeCallableFactory.createPagedCallable(
+ callIntList,
+ PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(),
+ clientContext)
+ .call(0)
+ .getPage();
+
+ Truth.assertThat(page.streamValues().count()).isEqualTo(3);
+ Truth.assertThat(page.hasNextPage()).isTrue();
+
+ page = page.getNextPage();
+ Truth.assertThat(page.streamValues().count()).isEqualTo(2);
+ Truth.assertThat(page.hasNextPage()).isTrue();
+
+ page = page.getNextPage();
+ Truth.assertThat(page.streamValues().count()).isEqualTo(0);
+ Truth.assertThat(page.hasNextPage()).isFalse();
+ Truth.assertThat(page.getNextPage()).isNull();
+ }
+
+ @Test
+ public void streamAll_streamIsCorrectInAllPages() {
+ ArgumentCaptor requestCapture = ArgumentCaptor.forClass(Integer.class);
+ Mockito.when(callIntList.futureCall(requestCapture.capture(), Mockito.any()))
+ .thenReturn(ApiFutures.immediateFuture(Arrays.asList(0, 1, 2)))
+ .thenReturn(ApiFutures.immediateFuture(Arrays.asList(3, 4)))
+ .thenReturn(ApiFutures.immediateFuture(Collections.emptyList()));
+
+ Page page =
+ FakeCallableFactory.createPagedCallable(
+ callIntList,
+ PagedCallSettings.newBuilder(new ListIntegersPagedResponseFactory()).build(),
+ clientContext)
+ .call(0)
+ .getPage();
+
+ Truth.assertThat(page.streamAll().count()).isEqualTo(5);
+ }
+
@Test
public void pagedByFixedSizeCollection() {
ArgumentCaptor requestCapture = ArgumentCaptor.forClass(Integer.class);