Skip to content

Commit 7a26bde

Browse files
Add Create Index Error + Optional-argument integration tests for Pod + Serverless (#82)
## Problem The `createIndex` integration tests are somewhat minimal and we've wanted to add thorough testing for error-cases, and optional configuration arguments for both pod and serverless indexes. ## Solution Update `integration.controlPlane.pod.CreateDescribeAndDeleteIndexTest` and `integration.controlPlane.serverless.CreateDescribeAndDeleteIndexTest` to include additional tests validating error-conditions, and creating indexes with optional arguments. ## Type of Change - [X] Infrastructure change (CI configs, etc) ## Test Plan run `gradle integrationTest` or validate the tests are run as part of the `pr` workflow in GitHub CI.
1 parent c79c2ee commit 7a26bde

File tree

4 files changed

+250
-44
lines changed

4 files changed

+250
-44
lines changed

src/integration/java/io/pinecone/helpers/IndexManager.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static String createNewIndex(Pinecone pinecone, int dimension, String ind
5454
CreateIndexRequestSpecPod podSpec = new CreateIndexRequestSpecPod().environment(environment).podType("p1.x1");
5555
createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
5656
} else {
57-
// Serverless currently has limited availability in specific regions, hardcode us-west-2 for now
57+
// Serverless currently has limited availability in specific regions, hard-code us-west-2 for now
5858
ServerlessSpec serverlessSpec =
5959
new ServerlessSpec().cloud(ServerlessSpec.CloudEnum.AWS).region("us-west-2");
6060
createIndexRequestSpec = new CreateIndexRequestSpec().serverless(serverlessSpec);
@@ -112,7 +112,7 @@ public static Pinecone createNewIndex(Pinecone pinecone, String indexName, int d
112112
return pinecone;
113113
}
114114

115-
public static Index createNewIndexAndConnect(Pinecone pinecone, String indexName, int dimension, IndexMetric metric, CreateIndexRequestSpec spec) throws InterruptedException, PineconeException {
115+
public static Index createNewIndexAndConnectSync(Pinecone pinecone, String indexName, int dimension, IndexMetric metric, CreateIndexRequestSpec spec) throws InterruptedException, PineconeException {
116116
CreateIndexRequest createIndexRequest = new CreateIndexRequest().name(indexName).dimension(dimension).metric(metric).spec(spec);
117117
pinecone.createIndex(createIndexRequest);
118118

src/integration/java/io/pinecone/integration/controlPlane/pod/CollectionTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static void setUp() throws InterruptedException {
4444
CreateIndexRequestSpecPod podSpec =
4545
new CreateIndexRequestSpecPod().pods(1).podType("p1.x1").replicas(1).environment(environment);
4646
CreateIndexRequestSpec spec = new CreateIndexRequestSpec().pod(podSpec);
47-
Index indexClient = createNewIndexAndConnect(pineconeClient, indexName, dimension,
47+
Index indexClient = createNewIndexAndConnectSync(pineconeClient, indexName, dimension,
4848
indexMetric, spec);
4949
indexesToCleanUp.add(indexName);
5050

Original file line numberDiff line numberDiff line change
@@ -1,51 +1,178 @@
11
package io.pinecone.integration.controlPlane.pod;
22

33
import io.pinecone.clients.Pinecone;
4+
import io.pinecone.exceptions.PineconeBadRequestException;
5+
import io.pinecone.exceptions.PineconeUnmappedHttpException;
46
import io.pinecone.helpers.RandomStringBuilder;
5-
import org.junit.jupiter.api.BeforeEach;
7+
import org.junit.jupiter.api.AfterAll;
8+
import org.junit.jupiter.api.BeforeAll;
69
import org.junit.jupiter.api.Test;
710
import org.openapitools.client.model.*;
811

9-
import static org.junit.jupiter.api.Assertions.assertEquals;
10-
import static org.junit.jupiter.api.Assertions.assertNotNull;
12+
import static io.pinecone.helpers.IndexManager.waitUntilIndexIsReady;
13+
import static org.junit.jupiter.api.Assertions.*;
1114

1215
public class CreateDescribeListAndDeleteIndexTest {
13-
private Pinecone controlPlaneClient;
14-
private final String apiKey = System.getenv("PINECONE_API_KEY");
15-
private final String environment = System.getenv("PINECONE_ENVIRONMENT");
16-
17-
@BeforeEach
18-
public void setUp() {
19-
controlPlaneClient = new Pinecone(apiKey);
20-
}
21-
22-
@Test
23-
public void createAndDelete() throws InterruptedException {
24-
String indexName = RandomStringBuilder.build("index-name", 8);
25-
CreateIndexRequestSpecPod podSpec = new CreateIndexRequestSpecPod().environment(environment).podType("p1.x1");
26-
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
16+
private static final String indexName = RandomStringBuilder.build("create-index", 8);
17+
private static final String indexPodType = "p1.x1";
18+
private static Pinecone controlPlaneClient = new Pinecone(System.getenv("PINECONE_API_KEY"));
19+
private static final String environment = System.getenv("PINECONE_ENVIRONMENT");
2720

21+
@BeforeAll
22+
public static void setUp() throws InterruptedException {
2823
// Create the index
24+
CreateIndexRequestSpecPod podSpec = new CreateIndexRequestSpecPod().environment(environment).podType(indexPodType);
25+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
2926
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
3027
.name(indexName)
3128
.metric(IndexMetric.COSINE)
3229
.dimension(10)
3330
.spec(createIndexRequestSpec);
3431
controlPlaneClient.createIndex(createIndexRequest);
32+
waitUntilIndexIsReady(controlPlaneClient, indexName);
33+
}
34+
35+
@AfterAll
36+
public static void cleanUp() {
37+
// Delete the index
38+
controlPlaneClient.deleteIndex(indexName);
39+
}
3540

41+
@Test
42+
public void describeAndListIndex() {
3643
// Describe the index
3744
IndexModel indexModel = controlPlaneClient.describeIndex(indexName);
3845
assertNotNull(indexModel);
3946
assertEquals(10, indexModel.getDimension());
4047
assertEquals(indexName, indexModel.getName());
4148
assertEquals(IndexMetric.COSINE, indexModel.getMetric());
49+
assertNotNull(indexModel.getSpec().getPod());
50+
assertEquals(indexPodType, indexModel.getSpec().getPod().getPodType());
4251

4352
// List the index
4453
IndexList indexList = controlPlaneClient.listIndexes();
4554
assertNotNull(indexList.getIndexes());
55+
assertTrue(indexList.getIndexes().stream().anyMatch(index -> indexName.equals(index.getName())));
56+
}
4657

47-
// Delete the index
48-
controlPlaneClient.deleteIndex(indexName);
49-
Thread.sleep(3500);
58+
@Test
59+
public void createIndexWithPodsAndPodType() {
60+
String podIndexName = RandomStringBuilder.build("create-pod", 8);
61+
String podType = "p1.x2";
62+
CreateIndexRequestSpecPod podSpec = new CreateIndexRequestSpecPod().environment(environment).pods(2).podType(podType);
63+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
64+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
65+
.name(podIndexName)
66+
.dimension(10)
67+
.metric(IndexMetric.EUCLIDEAN)
68+
.spec(createIndexRequestSpec);
69+
70+
IndexModel createdIndex = controlPlaneClient.createIndex(createIndexRequest);
71+
assertEquals(createdIndex.getName(), podIndexName);
72+
assertEquals(createdIndex.getMetric(), IndexMetric.EUCLIDEAN);
73+
assertEquals(createdIndex.getSpec().getPod().getPods(), 2);
74+
assertEquals(createdIndex.getSpec().getPod().getPodType(), podType);
75+
assertEquals(createdIndex.getStatus().getReady(), false);
76+
assertEquals(createdIndex.getStatus().getState(), IndexModelStatus.StateEnum.INITIALIZING);
77+
78+
controlPlaneClient.deleteIndex(podIndexName);
79+
}
80+
81+
@Test
82+
public void createIndexWithInvalidName() {
83+
CreateIndexRequestSpecPod podSpec = new CreateIndexRequestSpecPod().environment(environment).podType(indexPodType);
84+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
85+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
86+
.name("Invalid-name")
87+
.metric(IndexMetric.COSINE)
88+
.dimension(10)
89+
.spec(createIndexRequestSpec);
90+
91+
try {
92+
controlPlaneClient.createIndex(createIndexRequest);
93+
94+
fail("Expected to throw PineconeBadRequestException");
95+
} catch (PineconeBadRequestException expected) {
96+
assertTrue(expected.getLocalizedMessage().contains("Name must consist of lower case alphanumeric characters or '-'"));
97+
}
98+
}
99+
100+
@Test
101+
public void createIndexWithInvalidDimension() {
102+
CreateIndexRequestSpecPod podSpec = new CreateIndexRequestSpecPod().environment(environment).podType(indexPodType);
103+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
104+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
105+
.name("invalid-dimension")
106+
.metric(IndexMetric.COSINE)
107+
.dimension(-1)
108+
.spec(createIndexRequestSpec);
109+
110+
try {
111+
controlPlaneClient.createIndex(createIndexRequest);
112+
113+
fail("Expected to throw PineconeUnmappedHttpException");
114+
} catch (PineconeUnmappedHttpException expected) {
115+
assertTrue(expected.getLocalizedMessage().contains("dimension: invalid value: integer `-1`, expected u32"));
116+
}
117+
}
118+
119+
@Test
120+
public void createIndexWithInvalidPods() {
121+
CreateIndexRequestSpecPod podSpec =
122+
new CreateIndexRequestSpecPod().environment(environment).pods(-1).podType(indexPodType);
123+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
124+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
125+
.name("invalid-pods")
126+
.metric(IndexMetric.COSINE)
127+
.dimension(10)
128+
.spec(createIndexRequestSpec);
129+
130+
try {
131+
controlPlaneClient.createIndex(createIndexRequest);
132+
133+
fail("Expected to throw PineconeBadRequestException");
134+
} catch (PineconeBadRequestException expected) {
135+
assertTrue(expected.getLocalizedMessage().contains("Invalid value for pods: must be greater than 0"));
136+
}
137+
}
138+
139+
@Test
140+
public void createIndexWithInvalidReplicas() {
141+
CreateIndexRequestSpecPod podSpec =
142+
new CreateIndexRequestSpecPod().environment(environment).pods(1).replicas(-1).podType(indexPodType);
143+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
144+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
145+
.name("invalid-replicas")
146+
.metric(IndexMetric.COSINE)
147+
.dimension(10)
148+
.spec(createIndexRequestSpec);
149+
150+
try {
151+
controlPlaneClient.createIndex(createIndexRequest);
152+
153+
fail("Expected to throw PineconeBadRequestException");
154+
} catch (PineconeBadRequestException expected) {
155+
assertTrue(expected.getLocalizedMessage().contains("Invalid value for replicas: must be greater than 0"));
156+
}
157+
}
158+
159+
@Test
160+
public void createIndexWithInvalidPodsToShards() {
161+
CreateIndexRequestSpecPod podSpec =
162+
new CreateIndexRequestSpecPod().environment(environment).pods(5).replicas(2).shards(2).podType(indexPodType);
163+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().pod(podSpec);
164+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
165+
.name("invalid-shards")
166+
.metric(IndexMetric.COSINE)
167+
.dimension(10)
168+
.spec(createIndexRequestSpec);
169+
170+
try {
171+
controlPlaneClient.createIndex(createIndexRequest);
172+
173+
fail("Expected to throw PineconeBadRequestException");
174+
} catch (PineconeBadRequestException expected) {
175+
assertTrue(expected.getLocalizedMessage().contains("Invalid value for pods: total pods must be divisible by number of shards"));
176+
}
50177
}
51178
}
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,131 @@
11
package io.pinecone.integration.controlPlane.serverless;
22

33
import io.pinecone.clients.Pinecone;
4+
import io.pinecone.exceptions.PineconeBadRequestException;
5+
import io.pinecone.exceptions.PineconeNotFoundException;
6+
import io.pinecone.exceptions.PineconeUnmappedHttpException;
47
import io.pinecone.helpers.RandomStringBuilder;
5-
import org.junit.jupiter.api.BeforeEach;
8+
import org.junit.jupiter.api.AfterAll;
9+
import org.junit.jupiter.api.BeforeAll;
610
import org.junit.jupiter.api.Test;
711
import org.openapitools.client.model.*;
812

913
import static io.pinecone.helpers.IndexManager.waitUntilIndexIsReady;
10-
import static org.junit.jupiter.api.Assertions.assertEquals;
11-
import static org.junit.jupiter.api.Assertions.assertNotNull;
14+
import static org.junit.jupiter.api.Assertions.*;
1215

1316
public class CreateDescribeListAndDeleteIndexTest {
14-
private Pinecone controlPlaneClient;
15-
16-
@BeforeEach
17-
public void setUp() {
18-
controlPlaneClient = new Pinecone(System.getenv("PINECONE_API_KEY"));
19-
}
20-
21-
@Test
22-
public void createAndDelete() throws InterruptedException {
23-
String indexName = RandomStringBuilder.build("index-name", 8);
24-
ServerlessSpec serverlessSpec = new ServerlessSpec().cloud(ServerlessSpec.CloudEnum.AWS).region("us-west-2");
25-
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().serverless(serverlessSpec);
26-
17+
private static final String indexName = RandomStringBuilder.build("create-index", 8);
18+
// Serverless currently has limited availability in specific regions, hard-code us-west-2 for now
19+
private static final String serverlessRegion = "us-west-2";
20+
private static Pinecone controlPlaneClient = new Pinecone(System.getenv("PINECONE_API_KEY"));
21+
@BeforeAll
22+
public static void setUp() throws InterruptedException {
2723
// Create the index
24+
ServerlessSpec serverlessSpec = new ServerlessSpec().cloud(ServerlessSpec.CloudEnum.AWS).region(serverlessRegion);
25+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().serverless(serverlessSpec);
2826
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
2927
.name(indexName)
30-
.metric(IndexMetric.COSINE)
3128
.dimension(10)
3229
.spec(createIndexRequestSpec);
3330
controlPlaneClient.createIndex(createIndexRequest);
34-
3531
waitUntilIndexIsReady(controlPlaneClient, indexName);
32+
}
33+
34+
@AfterAll
35+
public static void cleanUp() {
36+
// Delete the index
37+
controlPlaneClient.deleteIndex(indexName);
38+
}
3639

40+
@Test
41+
public void describeAndListIndex() {
3742
// Describe the index
3843
IndexModel indexModel = controlPlaneClient.describeIndex(indexName);
3944
assertNotNull(indexModel);
4045
assertEquals(10, indexModel.getDimension());
4146
assertEquals(indexName, indexModel.getName());
4247
assertEquals(IndexMetric.COSINE, indexModel.getMetric());
48+
assertNotNull(indexModel.getSpec().getServerless());
4349

4450
// List the index
4551
IndexList indexList = controlPlaneClient.listIndexes();
4652
assertNotNull(indexList.getIndexes());
53+
assertTrue(indexList.getIndexes().stream().anyMatch(index -> indexName.equals(index.getName())));
54+
}
4755

48-
// Delete the index
49-
controlPlaneClient.deleteIndex(indexName);
50-
Thread.sleep(3500);
56+
@Test
57+
public void createIndexWithInvalidName() {
58+
ServerlessSpec serverlessSpec = new ServerlessSpec().cloud(ServerlessSpec.CloudEnum.AWS).region(serverlessRegion);
59+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().serverless(serverlessSpec);
60+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
61+
.name("Invalid-name")
62+
.metric(IndexMetric.COSINE)
63+
.dimension(10)
64+
.spec(createIndexRequestSpec);
65+
66+
try {
67+
controlPlaneClient.createIndex(createIndexRequest);
68+
69+
fail("Expected to throw PineconeBadRequestException");
70+
} catch (PineconeBadRequestException expected) {
71+
assertTrue(expected.getLocalizedMessage().contains("Name must consist of lower case alphanumeric characters or '-'"));
72+
}
73+
}
74+
75+
@Test
76+
public void createIndexWithInvalidDimension() {
77+
ServerlessSpec serverlessSpec = new ServerlessSpec().cloud(ServerlessSpec.CloudEnum.AWS).region(serverlessRegion);
78+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().serverless(serverlessSpec);
79+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
80+
.name("invalid-dimension")
81+
.metric(IndexMetric.COSINE)
82+
.dimension(-1)
83+
.spec(createIndexRequestSpec);
84+
85+
try {
86+
controlPlaneClient.createIndex(createIndexRequest);
87+
88+
fail("Expected to throw PineconeUnmappedHttpException");
89+
} catch (PineconeUnmappedHttpException expected) {
90+
assertTrue(expected.getLocalizedMessage().contains("dimension: invalid value: integer `-1`, expected u32"));
91+
}
92+
}
93+
94+
@Test
95+
public void createIndexInvalidCloud() {
96+
ServerlessSpec serverlessSpec = new ServerlessSpec().cloud(ServerlessSpec.CloudEnum.AZURE).region(serverlessRegion);
97+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().serverless(serverlessSpec);
98+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
99+
.name("invalid-cloud")
100+
.metric(IndexMetric.COSINE)
101+
.dimension(1)
102+
.spec(createIndexRequestSpec);
103+
104+
try {
105+
controlPlaneClient.createIndex(createIndexRequest);
106+
107+
fail("Expected to throw PineconeNotFoundException");
108+
} catch (PineconeNotFoundException expected) {
109+
assertTrue(expected.getLocalizedMessage().contains("Resource cloud: azure region: us-west-2 not found"));
110+
}
111+
}
112+
113+
@Test
114+
public void createIndexInvalidRegion() {
115+
ServerlessSpec serverlessSpec = new ServerlessSpec().cloud(ServerlessSpec.CloudEnum.AWS).region("invalid-region");
116+
CreateIndexRequestSpec createIndexRequestSpec = new CreateIndexRequestSpec().serverless(serverlessSpec);
117+
CreateIndexRequest createIndexRequest = new CreateIndexRequest()
118+
.name("invalid-region")
119+
.metric(IndexMetric.COSINE)
120+
.dimension(1)
121+
.spec(createIndexRequestSpec);
122+
123+
try {
124+
controlPlaneClient.createIndex(createIndexRequest);
125+
126+
fail("Expected to throw PineconeNotFoundException");
127+
} catch (PineconeNotFoundException expected) {
128+
assertTrue(expected.getLocalizedMessage().contains("Resource cloud: aws region: invalid-region not found"));
129+
}
51130
}
52131
}

0 commit comments

Comments
 (0)