Skip to content

Commit 0495a20

Browse files
committed
test(fts): add integration tests for FTS control plane
Add comprehensive integration tests for the new Full-Text Search (FTS) control plane functionality including: - Schema-based index creation (dict format, field type classes, SchemaBuilder) - Deployment configuration (explicit ServerlessDeployment, default deployment) - describe_index compatibility (.spec.serverless.cloud, dimension, metric) - FTS-only indexes (return None for vector properties) - Error handling (spec/schema mutual exclusion, validation) - Legacy spec-based creation compatibility These tests verify the new schema-based API for creating Pinecone indexes with full-text search and vector capabilities. Relates to: SDK-113
1 parent ca90753 commit 0495a20

File tree

7 files changed

+815
-0
lines changed

7 files changed

+815
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# FTS control plane integration tests
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""Fixtures for FTS control plane integration tests."""
2+
3+
import pytest
4+
import uuid
5+
import logging
6+
import dotenv
7+
from pinecone import Pinecone
8+
from tests.integration.helpers import delete_indexes_from_run, index_tags, get_environment_var
9+
10+
dotenv.load_dotenv()
11+
12+
logger = logging.getLogger(__name__)
13+
14+
# Generate a unique ID for the entire test run
15+
RUN_ID = str(uuid.uuid4())
16+
17+
18+
@pytest.fixture()
19+
def pc():
20+
"""Create a Pinecone client."""
21+
return Pinecone()
22+
23+
24+
@pytest.fixture()
25+
def index_name():
26+
"""Generate a unique index name for each test."""
27+
return f"{str(uuid.uuid4())}"
28+
29+
30+
@pytest.fixture()
31+
def index_name_and_tags(request):
32+
"""Generate a unique index name and tags for each test."""
33+
name = f"{str(uuid.uuid4())}"
34+
tags = index_tags(request, RUN_ID)
35+
return name, tags
36+
37+
38+
@pytest.fixture()
39+
def serverless_cloud():
40+
"""Get the serverless cloud provider."""
41+
return get_environment_var("SERVERLESS_CLOUD", "aws")
42+
43+
44+
@pytest.fixture()
45+
def serverless_region():
46+
"""Get the serverless region."""
47+
return get_environment_var("SERVERLESS_REGION", "us-east-1")
48+
49+
50+
def pytest_sessionfinish(session, exitstatus):
51+
"""Clean up indexes created during the test session."""
52+
logger.info("Running final cleanup after FTS control plane tests...")
53+
pc = Pinecone()
54+
delete_indexes_from_run(pc, RUN_ID)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""Integration tests for index deployment configurations.
2+
3+
These tests verify the deployment parameter for schema-based index creation,
4+
including explicit ServerlessDeployment and default deployment behavior.
5+
"""
6+
7+
from pinecone import Pinecone, DenseVectorField, ServerlessDeployment
8+
9+
10+
class TestCreateIndexWithDefaultDeployment:
11+
"""Test creating indexes with default deployment (aws/us-east-1)."""
12+
13+
def test_create_index_with_default_deployment(self, pc: Pinecone, index_name_and_tags):
14+
"""Test that omitting deployment defaults to aws/us-east-1."""
15+
index_name, tags = index_name_and_tags
16+
schema = {"embedding": DenseVectorField(dimension=512, metric="cosine")}
17+
resp = pc.db.index.create(name=index_name, schema=schema, tags=tags)
18+
assert resp.name == index_name
19+
20+
desc = pc.db.index.describe(name=index_name)
21+
assert desc.name == index_name
22+
assert desc.spec.serverless.cloud == "aws"
23+
assert desc.spec.serverless.region == "us-east-1"
24+
25+
26+
class TestCreateIndexWithExplicitDeployment:
27+
"""Test creating indexes with explicit ServerlessDeployment."""
28+
29+
def test_create_index_with_serverless_deployment_aws(self, pc: Pinecone, index_name_and_tags):
30+
"""Test creating an index with explicit AWS ServerlessDeployment."""
31+
index_name, tags = index_name_and_tags
32+
schema = {"embedding": DenseVectorField(dimension=512, metric="cosine")}
33+
resp = pc.db.index.create(
34+
name=index_name,
35+
schema=schema,
36+
deployment=ServerlessDeployment(cloud="aws", region="us-east-1"),
37+
tags=tags,
38+
)
39+
assert resp.name == index_name
40+
41+
desc = pc.db.index.describe(name=index_name)
42+
assert desc.name == index_name
43+
assert desc.spec.serverless.cloud == "aws"
44+
assert desc.spec.serverless.region == "us-east-1"
45+
46+
def test_create_index_with_serverless_deployment_us_west(
47+
self, pc: Pinecone, index_name_and_tags
48+
):
49+
"""Test creating an index with AWS us-west-2 ServerlessDeployment."""
50+
index_name, tags = index_name_and_tags
51+
schema = {"embedding": DenseVectorField(dimension=512, metric="cosine")}
52+
resp = pc.db.index.create(
53+
name=index_name,
54+
schema=schema,
55+
deployment=ServerlessDeployment(cloud="aws", region="us-west-2"),
56+
tags=tags,
57+
)
58+
assert resp.name == index_name
59+
60+
desc = pc.db.index.describe(name=index_name)
61+
assert desc.name == index_name
62+
assert desc.spec.serverless.cloud == "aws"
63+
assert desc.spec.serverless.region == "us-west-2"
64+
65+
66+
class TestDeploymentCompatibilityAccess:
67+
"""Test that deployment info is accessible via compatibility shim."""
68+
69+
def test_spec_serverless_access_pattern(self, pc: Pinecone, index_name_and_tags):
70+
"""Test that .spec.serverless.cloud access pattern works."""
71+
index_name, tags = index_name_and_tags
72+
schema = {"embedding": DenseVectorField(dimension=512, metric="cosine")}
73+
pc.db.index.create(
74+
name=index_name,
75+
schema=schema,
76+
deployment=ServerlessDeployment(cloud="aws", region="us-east-1"),
77+
tags=tags,
78+
)
79+
80+
desc = pc.db.index.describe(name=index_name)
81+
82+
# Verify the compatibility shim provides .spec.serverless access
83+
assert desc.spec is not None
84+
assert desc.spec.serverless is not None
85+
assert desc.spec.serverless.cloud == "aws"
86+
assert desc.spec.serverless.region == "us-east-1"
87+
88+
# Verify .spec.pod and .spec.byoc return None for serverless index
89+
assert desc.spec.pod is None
90+
assert desc.spec.byoc is None
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""Integration tests for schema-based index creation error handling.
2+
3+
These tests verify proper error handling for invalid configurations
4+
and mutual exclusion of spec and schema parameters.
5+
"""
6+
7+
import pytest
8+
from pinecone import Pinecone, DenseVectorField, ServerlessSpec, CloudProvider, AwsRegion
9+
10+
11+
class TestSpecAndSchemaMutualExclusion:
12+
"""Test that spec and schema parameters are mutually exclusive."""
13+
14+
def test_error_when_both_spec_and_schema_provided(self, pc: Pinecone, index_name_and_tags):
15+
"""Test that providing both spec and schema raises ValueError."""
16+
index_name, tags = index_name_and_tags
17+
schema = {"embedding": DenseVectorField(dimension=512, metric="cosine")}
18+
spec = ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1)
19+
20+
with pytest.raises(ValueError) as exc_info:
21+
pc.db.index.create(name=index_name, spec=spec, schema=schema, tags=tags)
22+
23+
assert "spec" in str(exc_info.value).lower()
24+
assert "schema" in str(exc_info.value).lower()
25+
26+
def test_error_when_neither_spec_nor_schema_provided(self, pc: Pinecone, index_name_and_tags):
27+
"""Test that providing neither spec nor schema raises ValueError."""
28+
index_name, tags = index_name_and_tags
29+
30+
with pytest.raises(ValueError) as exc_info:
31+
pc.db.index.create(name=index_name, dimension=512, metric="cosine", tags=tags)
32+
33+
assert "spec" in str(exc_info.value).lower() or "schema" in str(exc_info.value).lower()
34+
35+
36+
class TestSchemaValidation:
37+
"""Test schema field configuration validation."""
38+
39+
def test_error_when_schema_is_empty(self, pc: Pinecone, index_name_and_tags):
40+
"""Test that an empty schema raises an error from the API."""
41+
index_name, tags = index_name_and_tags
42+
schema = {}
43+
44+
with pytest.raises(Exception):
45+
pc.db.index.create(name=index_name, schema=schema, tags=tags)
46+
47+
48+
class TestLegacySpecBasedCreation:
49+
"""Test that legacy spec-based creation still works correctly."""
50+
51+
def test_legacy_serverless_spec_creation(self, pc: Pinecone, index_name_and_tags):
52+
"""Test that legacy ServerlessSpec-based creation still works."""
53+
index_name, tags = index_name_and_tags
54+
resp = pc.db.index.create(
55+
name=index_name,
56+
dimension=1024,
57+
metric="cosine",
58+
spec=ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1),
59+
tags=tags,
60+
)
61+
assert resp.name == index_name
62+
63+
desc = pc.db.index.describe(name=index_name)
64+
assert desc.name == index_name
65+
assert desc.dimension == 1024
66+
assert desc.metric == "cosine"
67+
assert desc.spec.serverless.cloud == "aws"
68+
assert desc.spec.serverless.region == "us-east-1"
69+
70+
def test_legacy_dict_spec_creation(self, pc: Pinecone, index_name_and_tags):
71+
"""Test that legacy dict-based spec creation still works."""
72+
index_name, tags = index_name_and_tags
73+
resp = pc.db.index.create(
74+
name=index_name,
75+
dimension=768,
76+
metric="euclidean",
77+
spec={"serverless": {"cloud": "aws", "region": "us-east-1"}},
78+
tags=tags,
79+
)
80+
assert resp.name == index_name
81+
82+
desc = pc.db.index.describe(name=index_name)
83+
assert desc.name == index_name
84+
assert desc.dimension == 768
85+
assert desc.metric == "euclidean"
86+
87+
def test_legacy_vector_type_parameter(self, pc: Pinecone, index_name_and_tags):
88+
"""Test that legacy vector_type parameter works with spec."""
89+
index_name, tags = index_name_and_tags
90+
resp = pc.db.index.create(
91+
name=index_name,
92+
dimension=512,
93+
metric="cosine",
94+
vector_type="dense",
95+
spec=ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1),
96+
tags=tags,
97+
)
98+
assert resp.name == index_name
99+
100+
desc = pc.db.index.describe(name=index_name)
101+
assert desc.vector_type == "dense"
102+
103+
def test_legacy_sparse_index_creation(self, pc: Pinecone, index_name_and_tags):
104+
"""Test that legacy sparse index creation still works."""
105+
index_name, tags = index_name_and_tags
106+
resp = pc.db.index.create(
107+
name=index_name,
108+
metric="dotproduct",
109+
vector_type="sparse",
110+
spec=ServerlessSpec(cloud=CloudProvider.AWS, region=AwsRegion.US_EAST_1),
111+
tags=tags,
112+
)
113+
assert resp.name == index_name
114+
115+
desc = pc.db.index.describe(name=index_name)
116+
assert desc.metric == "dotproduct"
117+
assert desc.vector_type == "sparse"
118+
assert desc.dimension is None # Sparse indexes have no dimension

0 commit comments

Comments
 (0)