Skip to content

Commit f825aa0

Browse files
Rewrite deleted tests using rx/TestSuiteBase.java with public APIs
Per reviewer feedback, rewrote tests to use rx/TestSuiteBase.java base class and public APIs (CosmosAsyncClient, CosmosAsyncContainer) instead of internal AsyncDocumentClient APIs. Rewritten tests: - ChangeFeedTest.java - uses CosmosAsyncContainer.queryChangeFeed() - OfferQueryTest.java - uses container.readThroughput() - ReadFeedOffersTest.java - uses container.readThroughput() - ResourceTokenTest.java - uses CosmosAsyncUser and CosmosPermissionProperties Co-authored-by: kushagraThapar <14034156+kushagraThapar@users.noreply.github.com>
1 parent b0a8f20 commit f825aa0

4 files changed

Lines changed: 661 additions & 0 deletions

File tree

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.azure.cosmos.rx;
4+
5+
import com.azure.cosmos.CosmosAsyncClient;
6+
import com.azure.cosmos.CosmosAsyncContainer;
7+
import com.azure.cosmos.CosmosAsyncDatabase;
8+
import com.azure.cosmos.CosmosClientBuilder;
9+
import com.azure.cosmos.CosmosDatabaseForTest;
10+
import com.azure.cosmos.TestObject;
11+
import com.azure.cosmos.models.CosmosChangeFeedRequestOptions;
12+
import com.azure.cosmos.models.CosmosContainerProperties;
13+
import com.azure.cosmos.models.CosmosContainerRequestOptions;
14+
import com.azure.cosmos.models.CosmosItemRequestOptions;
15+
import com.azure.cosmos.models.FeedRange;
16+
import com.azure.cosmos.models.FeedResponse;
17+
import com.azure.cosmos.models.PartitionKey;
18+
import com.azure.cosmos.models.ThroughputProperties;
19+
import com.fasterxml.jackson.databind.JsonNode;
20+
import org.testng.annotations.AfterClass;
21+
import org.testng.annotations.BeforeClass;
22+
import org.testng.annotations.DataProvider;
23+
import org.testng.annotations.Factory;
24+
import org.testng.annotations.Test;
25+
26+
import java.time.Instant;
27+
import java.util.ArrayList;
28+
import java.util.Arrays;
29+
import java.util.Iterator;
30+
import java.util.List;
31+
import java.util.UUID;
32+
33+
import static org.assertj.core.api.Assertions.assertThat;
34+
35+
/**
36+
* Tests for Change Feed using public APIs.
37+
*/
38+
public class ChangeFeedTest extends TestSuiteBase {
39+
40+
private static final int SETUP_TIMEOUT = 40000;
41+
private static final int TIMEOUT = 30000;
42+
43+
private CosmosAsyncDatabase createdDatabase;
44+
private CosmosAsyncContainer createdCollection;
45+
private CosmosAsyncClient client;
46+
47+
@Factory(dataProvider = "clientBuilders")
48+
public ChangeFeedTest(CosmosClientBuilder clientBuilder) {
49+
super(clientBuilder);
50+
this.subscriberValidationTimeout = TIMEOUT;
51+
}
52+
53+
@DataProvider(name = "changeFeedStartFromParam")
54+
public Object[][] changeFeedStartFromParam() {
55+
return new Object[][] {
56+
{ "fromBeginning" },
57+
{ "fromNow" }
58+
};
59+
}
60+
61+
@Test(groups = { "query", "emulator" }, timeOut = TIMEOUT, dataProvider = "changeFeedStartFromParam")
62+
public void changeFeedWithPartitionKey(String startFrom) {
63+
String partitionKeyValue = UUID.randomUUID().toString();
64+
65+
// Create some items
66+
List<TestObject> createdItems = new ArrayList<>();
67+
for (int i = 0; i < 3; i++) {
68+
TestObject item = new TestObject(
69+
UUID.randomUUID().toString(),
70+
partitionKeyValue,
71+
Arrays.asList(),
72+
"prop" + i
73+
);
74+
createdCollection.createItem(item).block();
75+
createdItems.add(item);
76+
}
77+
78+
// Query change feed
79+
CosmosChangeFeedRequestOptions options;
80+
if ("fromBeginning".equals(startFrom)) {
81+
options = CosmosChangeFeedRequestOptions
82+
.createForProcessingFromBeginning(FeedRange.forLogicalPartition(new PartitionKey(partitionKeyValue)));
83+
} else {
84+
options = CosmosChangeFeedRequestOptions
85+
.createForProcessingFromNow(FeedRange.forLogicalPartition(new PartitionKey(partitionKeyValue)));
86+
}
87+
88+
List<JsonNode> results = createdCollection
89+
.queryChangeFeed(options, JsonNode.class)
90+
.byPage()
91+
.flatMapIterable(FeedResponse::getResults)
92+
.collectList()
93+
.block();
94+
95+
if ("fromBeginning".equals(startFrom)) {
96+
assertThat(results).isNotNull();
97+
assertThat(results.size()).isGreaterThanOrEqualTo(createdItems.size());
98+
}
99+
}
100+
101+
@Test(groups = { "query", "emulator" }, timeOut = TIMEOUT)
102+
public void changeFeedWithContinuationToken() {
103+
String partitionKeyValue = UUID.randomUUID().toString();
104+
105+
// Get initial continuation token
106+
CosmosChangeFeedRequestOptions options = CosmosChangeFeedRequestOptions
107+
.createForProcessingFromBeginning(FeedRange.forLogicalPartition(new PartitionKey(partitionKeyValue)));
108+
109+
Iterator<FeedResponse<JsonNode>> iterator = createdCollection
110+
.queryChangeFeed(options, JsonNode.class)
111+
.byPage()
112+
.toIterable()
113+
.iterator();
114+
115+
String continuationToken = null;
116+
while (iterator.hasNext()) {
117+
FeedResponse<JsonNode> response = iterator.next();
118+
continuationToken = response.getContinuationToken();
119+
}
120+
assertThat(continuationToken).isNotNull();
121+
122+
// Create an item
123+
TestObject item = new TestObject(
124+
UUID.randomUUID().toString(),
125+
partitionKeyValue,
126+
Arrays.asList(),
127+
"testProp"
128+
);
129+
createdCollection.createItem(item).block();
130+
131+
// Query from continuation token
132+
CosmosChangeFeedRequestOptions optionsFromContinuation = CosmosChangeFeedRequestOptions
133+
.createForProcessingFromContinuation(continuationToken);
134+
135+
List<JsonNode> results = createdCollection
136+
.queryChangeFeed(optionsFromContinuation, JsonNode.class)
137+
.byPage()
138+
.flatMapIterable(FeedResponse::getResults)
139+
.collectList()
140+
.block();
141+
142+
assertThat(results).isNotNull();
143+
assertThat(results.size()).isGreaterThanOrEqualTo(1);
144+
}
145+
146+
@Test(groups = { "query", "emulator" }, timeOut = TIMEOUT)
147+
public void changeFeedEntireContainer() {
148+
String partitionKeyValue1 = UUID.randomUUID().toString();
149+
String partitionKeyValue2 = UUID.randomUUID().toString();
150+
151+
// Create items in different partitions
152+
TestObject item1 = new TestObject(UUID.randomUUID().toString(), partitionKeyValue1, Arrays.asList(), "prop1");
153+
TestObject item2 = new TestObject(UUID.randomUUID().toString(), partitionKeyValue2, Arrays.asList(), "prop2");
154+
createdCollection.createItem(item1).block();
155+
createdCollection.createItem(item2).block();
156+
157+
// Query change feed for entire container
158+
CosmosChangeFeedRequestOptions options = CosmosChangeFeedRequestOptions
159+
.createForProcessingFromBeginning(FeedRange.forFullRange());
160+
161+
List<JsonNode> results = createdCollection
162+
.queryChangeFeed(options, JsonNode.class)
163+
.byPage()
164+
.flatMapIterable(FeedResponse::getResults)
165+
.collectList()
166+
.block();
167+
168+
assertThat(results).isNotNull();
169+
assertThat(results.size()).isGreaterThanOrEqualTo(2);
170+
}
171+
172+
@Test(groups = { "query", "emulator" }, timeOut = TIMEOUT)
173+
public void changeFeedFromPointInTime() throws InterruptedException {
174+
String partitionKeyValue = UUID.randomUUID().toString();
175+
176+
// Create initial items
177+
TestObject item1 = new TestObject(UUID.randomUUID().toString(), partitionKeyValue, Arrays.asList(), "before");
178+
createdCollection.createItem(item1).block();
179+
180+
// Wait a moment to ensure point in time is distinguishable
181+
Thread.sleep(2000);
182+
Instant pointInTime = Instant.now();
183+
Thread.sleep(1000);
184+
185+
// Create more items after point in time
186+
TestObject item2 = new TestObject(UUID.randomUUID().toString(), partitionKeyValue, Arrays.asList(), "after");
187+
createdCollection.createItem(item2).block();
188+
189+
// Query change feed from point in time
190+
CosmosChangeFeedRequestOptions options = CosmosChangeFeedRequestOptions
191+
.createForProcessingFromPointInTime(pointInTime, FeedRange.forLogicalPartition(new PartitionKey(partitionKeyValue)));
192+
193+
List<JsonNode> results = createdCollection
194+
.queryChangeFeed(options, JsonNode.class)
195+
.byPage()
196+
.flatMapIterable(FeedResponse::getResults)
197+
.collectList()
198+
.block();
199+
200+
assertThat(results).isNotNull();
201+
assertThat(results.size()).isGreaterThanOrEqualTo(1);
202+
}
203+
204+
@BeforeClass(groups = { "query", "emulator" }, timeOut = SETUP_TIMEOUT)
205+
public void before_ChangeFeedTest() {
206+
client = getClientBuilder().buildAsyncClient();
207+
createdDatabase = createDatabase(client, CosmosDatabaseForTest.generateId());
208+
209+
CosmosContainerProperties containerProperties = getCollectionDefinition();
210+
createdDatabase.createContainer(
211+
containerProperties,
212+
ThroughputProperties.createManualThroughput(10100),
213+
new CosmosContainerRequestOptions()
214+
).block();
215+
createdCollection = createdDatabase.getContainer(containerProperties.getId());
216+
}
217+
218+
@AfterClass(groups = { "query", "emulator" }, timeOut = SHUTDOWN_TIMEOUT, alwaysRun = true)
219+
public void afterClass() {
220+
safeDeleteDatabase(createdDatabase);
221+
safeClose(client);
222+
}
223+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
package com.azure.cosmos.rx;
4+
5+
import com.azure.cosmos.CosmosAsyncClient;
6+
import com.azure.cosmos.CosmosAsyncContainer;
7+
import com.azure.cosmos.CosmosAsyncDatabase;
8+
import com.azure.cosmos.CosmosClientBuilder;
9+
import com.azure.cosmos.CosmosDatabaseForTest;
10+
import com.azure.cosmos.models.CosmosContainerProperties;
11+
import com.azure.cosmos.models.CosmosContainerRequestOptions;
12+
import com.azure.cosmos.models.ThroughputProperties;
13+
import com.azure.cosmos.models.ThroughputResponse;
14+
import org.testng.annotations.AfterClass;
15+
import org.testng.annotations.BeforeClass;
16+
import org.testng.annotations.Factory;
17+
import org.testng.annotations.Test;
18+
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.UUID;
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
/**
26+
* Tests for throughput (offer) operations using public APIs.
27+
*/
28+
public class OfferQueryTest extends TestSuiteBase {
29+
30+
private static final int SETUP_TIMEOUT = 40000;
31+
private static final int TIMEOUT = 30000;
32+
private static final int INITIAL_THROUGHPUT = 10100;
33+
34+
private final String databaseId = CosmosDatabaseForTest.generateId();
35+
private List<CosmosAsyncContainer> createdContainers = new ArrayList<>();
36+
37+
private CosmosAsyncClient client;
38+
private CosmosAsyncDatabase database;
39+
40+
@Factory(dataProvider = "clientBuilders")
41+
public OfferQueryTest(CosmosClientBuilder clientBuilder) {
42+
super(clientBuilder);
43+
}
44+
45+
@Test(groups = { "query" }, timeOut = TIMEOUT)
46+
public void readThroughputForContainer() {
47+
CosmosAsyncContainer container = createdContainers.get(0);
48+
49+
ThroughputResponse response = container.readThroughput().block();
50+
51+
assertThat(response).isNotNull();
52+
assertThat(response.getProperties()).isNotNull();
53+
assertThat(response.getProperties().getManualThroughput()).isEqualTo(INITIAL_THROUGHPUT);
54+
}
55+
56+
@Test(groups = { "query" }, timeOut = TIMEOUT)
57+
public void readThroughputForMultipleContainers() {
58+
// Read throughput for all created containers
59+
for (CosmosAsyncContainer container : createdContainers) {
60+
ThroughputResponse response = container.readThroughput().block();
61+
62+
assertThat(response).isNotNull();
63+
assertThat(response.getProperties()).isNotNull();
64+
assertThat(response.getProperties().getManualThroughput()).isEqualTo(INITIAL_THROUGHPUT);
65+
}
66+
}
67+
68+
@Test(groups = { "query" }, timeOut = TIMEOUT)
69+
public void readThroughputForDatabase() {
70+
// Create a database with throughput
71+
String dbWithThroughputId = CosmosDatabaseForTest.generateId();
72+
client.createDatabase(dbWithThroughputId, ThroughputProperties.createManualThroughput(4000)).block();
73+
CosmosAsyncDatabase dbWithThroughput = client.getDatabase(dbWithThroughputId);
74+
75+
try {
76+
ThroughputResponse response = dbWithThroughput.readThroughput().block();
77+
78+
assertThat(response).isNotNull();
79+
assertThat(response.getProperties()).isNotNull();
80+
assertThat(response.getProperties().getManualThroughput()).isEqualTo(4000);
81+
} finally {
82+
safeDeleteDatabase(dbWithThroughput);
83+
}
84+
}
85+
86+
@BeforeClass(groups = { "query" }, timeOut = SETUP_TIMEOUT)
87+
public void before_OfferQueryTest() {
88+
client = getClientBuilder().buildAsyncClient();
89+
client.createDatabase(databaseId).block();
90+
database = client.getDatabase(databaseId);
91+
92+
// Create multiple containers with throughput
93+
for (int i = 0; i < 3; i++) {
94+
CosmosContainerProperties containerProperties = new CosmosContainerProperties(
95+
UUID.randomUUID().toString(),
96+
"/mypk"
97+
);
98+
database.createContainer(
99+
containerProperties,
100+
ThroughputProperties.createManualThroughput(INITIAL_THROUGHPUT),
101+
new CosmosContainerRequestOptions()
102+
).block();
103+
createdContainers.add(database.getContainer(containerProperties.getId()));
104+
}
105+
}
106+
107+
@AfterClass(groups = { "query" }, timeOut = 2 * SHUTDOWN_TIMEOUT, alwaysRun = true)
108+
public void afterClass() {
109+
safeDeleteDatabase(database);
110+
safeClose(client);
111+
}
112+
}

0 commit comments

Comments
 (0)