100 Commits
Author SHA1 Message Date
yanliang567andGitHub b542464f30 test: Add JSON filtering e2e coverage (#51171)
## What does this PR do?

Adds Python e2e coverage for JSON filtering UNKNOWN semantics in
`tests/python_client/milvus_client/expressions/test_milvus_client_json_filtering.py`.

This PR covers:
- raw filtering paths on growing and sealed segments
- JSON arithmetic/filtering UNKNOWN behavior for missing, null, and
type-mismatch values
- JSON array predicate behavior for missing and non-array values
- ARRAY subscript UNKNOWN behavior for null, empty, and out-of-range
values
- contradiction rewrite cases, including outer `not (...)`, to ensure
UNKNOWN is not rewritten into TRUE
- JSON path index filtering with `json_cast_type=DOUBLE`
- JSON path index filtering with `json_cast_type=VARCHAR`
- JSON flat index coverage for currently passing UNKNOWN cases
- query/search filter consistency for representative JSON filters,
including indexed collections
- L2 coverage for boolean JSON values, fractional double values,
additional comparison/logical operators, JSON path array subscripts,
mixed arrays, and `ARRAY_DOUBLE` JSON path index

The known JSON flat index array-vs-scalar comparison mismatch is
documented in #51193 and covered by a skipped regression case so the
coverage can land first without taking server-side fixes in this PR.

issue: #50976
issue: #51193
Related #50699 #50698

## Test Plan

- [x] `git diff --check`
  - result: passed
- [x] `uvx ruff check --config tests/ruff.toml
tests/python_client/milvus_client/expressions/test_milvus_client_json_filtering.py`
  - result: passed
- [x] `uvx ruff format --check --config tests/ruff.toml
tests/python_client/milvus_client/expressions/test_milvus_client_json_filtering.py`
  - result: passed
- [x] `/Users/yanliang.qiao/fork/milvus/tests/.venv/bin/python -W ignore
-m pytest milvus_client/expressions/test_milvus_client_json_filtering.py
--collect-only -q`
  - result: `29 tests collected`
- [x] `milvus-dev-cli deploy create
harbor.milvus.io/manta/milvus:master-20260709-9a0d7f2 --name
json-filtering-l2-9a0d7f2 --namespace chaos-testing --no-auth
--wait-timeout 1800 --wait-interval 10`
  - result: Healthy
  - endpoint: `lb-6d57ndgl-sw4giqjhodl3bn15.clb.bj-tencentclb.net:19530`
- [x] `/Users/yanliang.qiao/fork/milvus/tests/.venv/bin/python -W ignore
-m pytest milvus_client/expressions/test_milvus_client_json_filtering.py
--uri http://lb-6d57ndgl-sw4giqjhodl3bn15.clb.bj-tencentclb.net:19530
--token "" -s -v --tb=short`
  - result: `28 passed, 1 skipped in 215.82s`

## Notes

The skipped case is
`test_json_flat_index_array_scalar_comparison_unknown_semantics_query`,
linked to #51193. The skip can be removed after the server-side JSON
flat index UNKNOWN semantics issue is fixed.

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-07-09 17:46:34 +08:00
yanliang567andGitHub 24e43c6dfd fix: Validate quick-create binary metrics by auto index (#51168)
## Summary
- validate REST quick-create BinaryVector metricType against the
configured binary auto-index support set
- keep default BIN_IVF_FLAT quick-create limited to HAMMING/JACCARD so
SUBSTRUCTURE/SUPERSTRUCTURE/MHJACCARD fail before collection creation
- add Go handler coverage and RESTful e2e params for the previously
missed binary metrics

Follow-up for review comment on #51088.
related issue: https://github.com/milvus-io/milvus/issues/51084

## Test Plan
- [x] git diff --check
- [x] python3 -m py_compile
tests/restful_client_v2/testcases/test_collection_operations.py
- [ ] go test ./internal/distributed/proxy/httpserver -run
TestCreateCollectionQuickVectorFieldType -count=1 (blocked locally:
missing rocksdb.pc and milvus_core.pc pkg-config files)

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-07-09 14:40:34 +08:00
yanliang567andGitHub e0857f1bd9 fix: Validate REST quick-create enum fields (#51088)
## What

Validate REST v2 quick-create enum-like fields before creating the
collection.

This PR fixes `vectorFieldType` handling for quick collection creation:
- rejects invalid `vectorFieldType` values instead of silently using
`FloatVector`
- supports `FloatVector`, `BinaryVector`, `Float16Vector`,
`BFloat16Vector`, and `SparseFloatVector`
- defaults quick-create index metric by vector type: dense `COSINE`,
binary `HAMMING`, sparse `IP`
- validates explicit binary/sparse `metricType` before collection
creation
- rejects `SparseFloatVector` quick-create with `dimension`

It also fixes top-level quick-create `consistencyLevel` handling:
- parses and validates top-level `consistencyLevel`
- preserves existing `params.consistencyLevel` behavior
- rejects conflicting top-level and `params.consistencyLevel` values

Fixes #51085
Fixes #51084

## Why

Previously, `/v2/vectordb/collections/create` ignored top-level
`vectorFieldType` and always generated a `FloatVector` schema in
quick-create mode. A typo such as `InvalidVectorType` could return
success and mask client-side bugs.

Binary and sparse quick-create requests without `metricType` could also
create the collection first and then fail index creation because the old
fallback metric was `COSINE`, which is incompatible with those vector
types.

For #51084, top-level `consistencyLevel` was not present in
`CollectionReq`, so JSON decoding silently dropped it. Invalid values
such as `"consistencyLevel": "Invalid"` were ignored and the collection
could be created with the default consistency level.

## Tests

- `./bin/gofumpt -w internal/distributed/proxy/httpserver/request_v2.go
internal/distributed/proxy/httpserver/handler_v2.go
internal/distributed/proxy/httpserver/handler_v2_test.go`
- `./bin/gci write internal/distributed/proxy/httpserver/request_v2.go
internal/distributed/proxy/httpserver/handler_v2.go
internal/distributed/proxy/httpserver/handler_v2_test.go
--skip-generated -s standard -s default -s
"prefix(github.com/milvus-io)" --custom-order`
- `git diff --check`
- `python3 -m py_compile
tests/restful_client_v2/testcases/test_collection_operations.py`
- `rg -n
"string\\(paramtable\\.(BinaryVectorDefaultMetricType|SparseFloatVectorDefaultMetricType)\\)|interface\\("
internal/distributed/proxy/httpserver/handler_v2.go
internal/distributed/proxy/httpserver/handler_v2_test.go`

Attempted locally but blocked by missing native dependencies:

```
go test ./internal/distributed/proxy/httpserver -run 'TestCreateCollection(QuickVectorFieldType|TopLevelConsistencyLevel)$' -count=1
# missing rocksdb.pc and milvus_core.pc
```

CI investigation before this push:

```
# build-ut-cov/code-check failed on c6 predecessor because of unconvert:
# internal/distributed/proxy/httpserver/handler_v2.go:2054:16 unnecessary conversion
# internal/distributed/proxy/httpserver/handler_v2.go:2056:16 unnecessary conversion
# internal/distributed/proxy/httpserver/handler_v2_test.go:2185:28 unnecessary conversion
# internal/distributed/proxy/httpserver/handler_v2_test.go:2217:28 unnecessary conversion
# Fixed by removing string(...) around paramtable default metric constants.

# e2e-default failed in job 40810 on:
# testcases/test_geometry_operations.py::TestGeometryCollection::test_spatial_query_and_search[False-True-sealed-ST_CROSSES]
# error: Connection refused to /v2/vectordb/collections/flush on port 19530
# the same job showed querynode/streamingnode restarts and proxy ContainerCreating during cleanup.
# REST collection tests in that job had already passed, so this looked unrelated to this PR.

# e2e-default failed again in dispatcher 13914 / job-1 32439 on:
# testcases/test_collection_operations.py::TestCreateCollectionNegative::test_create_collection_quick_setup_with_invalid_consistency_level
# root cause: the test used collection_create(), whose wrapper auto-injects params.consistencyLevel=Strong.
# That made the request hit the new conflict branch instead of the intended top-level invalid consistencyLevel branch.
# Fixed in 3e190eee56 by sending the request through raw client.post() to avoid wrapper mutation.
```

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-07-08 17:20:34 +08:00
yanliang567andGitHub 9c3c33062a test: Clean up Helm test values (#51007)
## Summary

- remove redundant Milvus runtime overrides from tests/_helm values
- delete stale standalone-one-pod values files from tests/_helm/values
- merge duplicate dataCoord.compaction keys in woodpecker nightly values
- add e2e-amd distributed woodpecker service boundary values preset

Fixes #51006

## Test Plan

- [x] strict duplicate-key YAML check for tests/_helm/values and
embedded user.yaml blocks
- [x] verified targetVecIndexVersion and standalone-one-pod no longer
exist under tests/_helm/values
- [x] git diff --check

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-07-03 11:34:28 +08:00
yanliang567andGitHub 182134e29e test: Update aggregation and groupby E2E coverage (#50963)
## Summary
- strengthen search aggregation reject coverage for unsupported
group-by, iterator, and dynamic-field combinations
- add controlled search order_by + group_by_field + offset regression
coverage
- update query aggregation GROUP BY limit and output projection coverage
to current semantics

issue: #50960

## Test Plan
- [x] PYTHONPATH=.
/Users/yanliang.qiao/Documents/Codex/2026-06-30/new-chat/work/milvus-e2e-venv/bin/python
-m pytest -q --tb=short --disable-warnings --timeout=300 --host
127.0.0.1 --port 19530 --user root --password Milvus <targeted
agg/groupby cases>: 11 passed, 1 xfailed in 51.81s
- [x] git diff --check --
tests/python_client/milvus_client/test_milvus_client_search_aggregation.py
tests/python_client/milvus_client/test_milvus_client_search_order.py
tests/python_client/testcases/test_query_aggregation.py

Milvus test target:
qa-milvus/yanliang-mas2-milvus-standalone-6686d94498-lhp7k, Running 1/1,
restart count 0

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-07-02 16:22:29 +08:00
yanliang567andGitHub c61863f419 test: Add bulk insert UTF-8 coverage (#50746)
## Summary

Add UTF-8 coverage to the existing all-field parquet bulk insert test.

- Add opt-in UTF-8 string generation for parquet bulk insert data.
- Enable UTF-8 generation in the existing all-field parquet case.
- Validate imported UTF-8 values for VARCHAR, analyzer-enabled VARCHAR,
ARRAY<VARCHAR>, and JSON fields.

issue: #50745

## Test Plan

- [x] `python -m py_compile
tests/python_client/common/bulk_insert_data.py
tests/python_client/testcases/test_bulk_insert.py`
- [x] `git diff --check`
- [x] `python -W ignore -m pytest
'testcases/test_bulk_insert.py::TestBulkInsert::test_bulk_insert_all_field_with_parquet[False-False-False-False-False-2000-128-False]'
--host 10.104.26.151 --port 19530 --minio_host 10.104.26.126
--minio_bucket yanliang-26x -q`

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-24 19:20:25 +08:00
yanliang567andGitHub d95c31c5a4 test: Add RBAC description coverage (#50634)
issue: #50183 #50179

Related to #50183
Related to #50179

### What this PR does

Adds focused RBAC description coverage by reusing existing RBAC tests
instead of adding new cases:

- Extends RBAC backup/restore integration coverage to assert role
descriptions are preserved.
- Extends Go client RBAC E2E coverage for user description create/read
and password update/read-back.
- Extends REST v2 role E2E coverage for create/describe description
persistence across grant/revoke.
- Extends REST v2 user E2E coverage for create/describe/update_password
description behavior.

### Tests

- `git diff --check`
- `python3 -m py_compile
tests/restful_client_v2/testcases/test_role_operation.py
tests/restful_client_v2/testcases/test_user_operation.py`
- `cd tests/go_client && go test -count=1 -tags rbac
./testcases/advcases -run
'^(TestRbacDefault|TestUpdatePassword|TestRoleDescription)$' -v -args
-addr http://10.104.6.197:19530 -user root -password Milvus`
- `/Users/yanliang.qiao/fork/.venv-py312/bin/python3 -m pytest
testcases/test_role_operation.py::TestRoleE2E::test_role_e2e --endpoint
http://10.104.6.197:19530 --token root:Milvus -v -q -x`
- `/Users/yanliang.qiao/fork/.venv-py312/bin/python3 -m pytest
testcases/test_user_operation.py::TestUserE2E::test_user_e2e --endpoint
http://10.104.6.197:19530 --token root:Milvus -v -q -x`
- Verified RBAC backup/restore role description preservation against
`10.104.6.197:19530` using a temporary Go client admin API check.

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-22 14:42:25 +08:00
yanliang567andGitHub 081a3e3fa7 test: Enable vortex storage in Helm test values (#50442)
## Summary

Enable the DataNode vortex storage format in the Helm values that
already enable Loon FFI storage:

- tests/_helm/values/e2e/standalone
- tests/_helm/values/e2e/distributed-pulsar
- tests/_helm/values/e2e-amd/standalone
- tests/_helm/values/e2e-amd/distributed-pulsar
- tests/_helm/values/e2e-arm/standalone
- tests/_helm/values/e2e-arm/distributed-pulsar
- tests/_helm/values/nightly/distributed-woodpecker
- tests/_helm/values/nightly/distributed-woodpecker-service

Fixes #50441

## Test Plan

- [x] ruby YAML parse check for the eight target values files, verifying
common.storage.useLoonFFI is true and dataNode.storage.format is vortex
- [x] git diff scope check confirmed only the two nightly woodpecker
files were added in the follow-up amend

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-18 10:54:22 +08:00
yanliang567andGitHub d2bf17e734 test: Add external table add field E2E tests (#50420)
Related to #50416

### What changed

- Add MilvusClient E2E coverage for external table
`add_collection_field` on scalar and vector fields.
- Cover refresh/load/search/query behavior after adding fields,
including about 10% NULL values in newly added scalar/vector fields.
- Add non-Parquet source coverage for add scalar field on Lance,
Iceberg, and Vortex.
- Add full supported DataType matrix coverage for external add field,
including scalar, array, geometry, and vector fields.
- Add negative coverage for missing/duplicate `external_field`, type/dim
mismatch, unsupported public data types, add/drop function, and drop
field APIs.
- Update Python client test dependency pin to `pymilvus==3.1.0rc35`.

### Verification

- `python -m py_compile
tests/python_client/milvus_client/test_milvus_client_external_table.py
tests/python_client/common/external_table_common.py
tests/python_client/base/client_v2_base.py
tests/python_client/check/func_check.py`
- `python -m ruff check
tests/python_client/milvus_client/test_milvus_client_external_table.py
tests/python_client/common/external_table_common.py
tests/python_client/base/client_v2_base.py
tests/python_client/check/func_check.py`
- `python -m pytest -n 4
milvus_client/test_milvus_client_external_table.py --host 10.104.18.101
--port 19530 --minio_host 10.104.18.27 --minio_bucket yanliang-mas2
--tb=short -q -s`

Result:

```text
182 passed, 1 xfailed in 318.94s (0:05:18)
```

The xfailed case is linked to #50416 and validates that old-field search
still works before the server returns the current internal QueryNode
assert for newly added fields before refresh.

---------

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-17 14:02:23 +08:00
yanliang567andGitHub dc5b3d069a enhance: Add REST search aggregation support (#50472)
Related: #49046

## What changed
- Add REST v2 searchAggregation request parsing, validation, and proxy
conversion for search requests.
- Return aggregation buckets with top hits, metrics, optional recall
information, cost, and storage metadata.
- Reject searchAggregation on unsupported REST v1 / low-level search
paths and hybrid sub-search inputs.
- Add Go unit coverage and RESTful v2 e2e coverage for happy paths,
nested aggregations, metrics/order, filters, and validation failures.

## Verification
- /Users/yanliang.qiao/fork/.venv-py312/bin/python -m ruff check
tests/restful_client_v2/testcases/test_vector_operations.py
- /Users/yanliang.qiao/fork/.venv-py312/bin/python -m ruff format
--check tests/restful_client_v2/testcases/test_vector_operations.py
- /Users/yanliang.qiao/fork/.venv-py312/bin/python -m py_compile
tests/restful_client_v2/testcases/test_vector_operations.py
- /Users/yanliang.qiao/fork/.venv-py312/bin/python -m pytest
--collect-only
testcases/test_vector_operations.py::TestSearchAggregationVector -q
- git diff --check

Note: local Go unit test build is blocked by missing native Milvus
dependencies on this machine: rocksdb.pc and milvus_core.pc.

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-12 11:26:20 +08:00
yanliang567andGitHub 4f2489fb3b test: Restore CSV nullable vector bulk writer coverage (#50482)
## Summary

Restore the CSV branch in the nullable vector RemoteBulkWriter
regression test.

This removes the previous skip and the explicit `nullkey="null"`
workaround so the test now covers the default CSV import path for
nullable `FLOAT_VECTOR` values.

Fixes #49678

## Test Plan

- [x] `/Users/yanliang.qiao/fork/.venv-py312/bin/python -m pytest
testcases/test_bulk_insert.py::TestBulkInsertNullableVector::test_bulk_writer_nullable_float_vector
--collect-only -q`
- [x] `/Users/yanliang.qiao/fork/.venv-py312/bin/python -m pytest -q -s
'testcases/test_bulk_insert.py::TestBulkInsertNullableVector::test_bulk_writer_nullable_float_vector[60-32-4]'
--host 10.104.30.186 --port 19530 --minio_host 10.104.18.198
--minio_bucket yanliang-mas2`

Note: I also ran the full JSON/CSV/Parquet parametrized test against the
same temporary cluster. JSON and CSV passed; the Parquet parameter later
hit a `get_bulk_insert_state` RPC `DEADLINE_EXCEEDED` while polling
import state, unrelated to this CSV regression change.

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-12 10:28:20 +08:00
yanliang567andGitHub a040281e20 enhance: Add Go SDK search aggregation support (#50448)
issue: #49046

## What
- Add Go SDK builders for search aggregation and top hits, including
validation and proto request wiring.
- Parse search aggregation responses from `AggBuckets`/`AggTopks` into
`ResultSet.AggregationBuckets`.
- Reject incompatible search options such as legacy group-by, offset,
and search iterator usage.
- Add unit tests, a Go SDK example, and Go E2E coverage for search
aggregation.

## Tests
- `cd client && go test ./... -count=1`
- `cd tests/go_client && GO_CLIENT_SKIP_EXTERNAL_TABLE_DEPS_INSTALL=true
go test ./testcases -run TestSearchAggregation -count=1 -args -addr
http://10.104.18.101:19530`

## Notes
- `make static-check` was attempted locally but blocked by missing LLVM:
`ERROR: Valid LLVM (14-18) not installed. Run: brew install llvm@17`.

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-11 14:10:20 +08:00
yanliang567andGitHub a87bc5844c test: Add hybrid search partition isolation coverage (#50401)
## What changed

- Add Python client, RESTful v2, and Go SDK regression coverage for
hybrid search on collections with `partitionkey.isolation=true`.
- Verify normal search still rejects unsupported partition-key isolation
filters:
  - `tenant in ["tenant_a", "tenant_b"]`
  - missing tenant filter
- Keep the current hybrid search server bug as conditional xfail/skip,
so baseline search regressions are not hidden.
- Add RESTful v2 coverage for MinHash + dense hybrid search with
explicit `partitionNames`.

## Issues

Related to #50398
Related to #50396

## Verification

- `ruff check
../tests/python_client/milvus_client/test_milvus_client_partition_key_isolation.py
../tests/restful_client_v2/testcases/test_vector_operations.py`
- `python -m py_compile
tests/python_client/milvus_client/test_milvus_client_partition_key_isolation.py
tests/restful_client_v2/testcases/test_vector_operations.py`
- `git diff --check`
- Python client 50398 case against `10.104.18.101`: `1 xfailed`
- RESTful v2 50398 case against `10.104.18.101`: `1 xfailed`
- Go SDK 50398 case against `10.104.18.101`: reproduces current bug and
conditionally skips

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-06-10 10:26:19 +08:00
yanliang567andGitHub d10a9f5dd9 test: [skip e2e] Increase standalone CPU requests in helm test values (#50419)
Related to #50384

This increases standalone Milvus CPU requests from 2 cores to 3 cores in
E2E and nightly standalone Helm values.

On the Go SDK ARM CI nodes, allocatable CPU is about 7.91 cores. With a
2-core request, three standalone Milvus pods can be scheduled onto the
same 8-core node while each pod can burst up to an 8-core limit. Raising
the request to 3 cores prevents three standalone pods from fitting on
one node and reduces CPU contention during index build / snapshot
restore heavy tests.

Validation:
- `git diff --check origin/master..HEAD`
- Parsed all updated YAML values with Ruby `YAML.load_file`
- Confirmed all updated standalone CPU requests are `"3"`

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-09 20:12:18 +08:00
yanliang567andGitHub 2baaebd775 test: Adjust standalone helm test resources (#50402)
## What
- Set standalone Helm test resource requests to 2 CPU / 8Gi memory.
- Set standalone Helm test resource limits to 8 CPU / 16Gi memory.
- Add the same standalone resources to one-pod values that previously
omitted them.

## Related
Related #50384

## Verification
- ruby -ryaml validation for all 11 standalone values files
- git diff --check HEAD~1..HEAD

Signed-off-by: Yanliang Qiao <yanliang.qiao@zilliz.com>
2026-06-09 14:40:20 +08:00
yanliang567andGitHub 8a9710a6fd test: Add search order pagination regression coverage (#50397)
issue: #49879

## What changed

- Add an independent Python client regression test for search with
`order_by_fields` plus `offset`, using controlled ANN candidates from
#49879.
- Mark the regression as strict xfail because current behavior still
applies offset before scalar ordering.
- Mark `search_aggregation` top_hits sorting by dynamic fields as strict
xfail because dynamic fields are explicitly rejected for search
aggregation today.

## Verification

```bash
/Users/yanliang.qiao/fork/.venv-py312/bin/python -m pytest -s --tb=short --host 10.104.18.101 --port 19530 \
  milvus_client/test_milvus_client_search_order.py::TestMilvusClientSearchOrderIndependent::test_milvus_client_search_order_by_with_offset \
  milvus_client/test_milvus_client_search_aggregation.py::TestSearchAggregationIndependent::test_search_aggregation_top_hits_sort_by_dynamic_field
```

Result: `2 xfailed in 13.46s`.

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-06-09 14:36:19 +08:00
yanliang567andGitHub 2f37c0b481 fix: Restrict Kafka chaos selectors to broker pods (#50380)
issue: #50379

Fixes #50379

This PR narrows Kafka chaos selectors to broker pods by adding
`app.kubernetes.io/component: kafka`. The previous selector matched both
broker pods and the Kafka exporter pod because both use
`app.kubernetes.io/name: kafka`.

Changes:
- Add `app.kubernetes.io/component: kafka` to Kafka container-kill
chaos.
- Add the same broker selector to Kafka pod-kill chaos.
- Update Kafka pod-failure chaos from the legacy `component: kafka`
selector to `app.kubernetes.io/component: kafka`.

Verification:
- `git diff --check`
- Parsed the three Kafka chaos YAML files and verified each selector
contains `app.kubernetes.io/component=kafka` with no stale `component`
selector.

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-06-09 10:02:18 +08:00
yanliang567andGitHub 28cfc6dd2c test: Add nullable vector field coverage (#49649)
issue: #47846

Related to #49337

## What this PR does

Adds release-level nullable vector field coverage in Python E2E tests:

- Use nullable dense and sparse vector fields in group-by search shared
collection, with inserted `None` vector rows.
- Use nullable dense and sparse vector fields in pagination search
shared collection, and exclude null vector rows from expected
vector-search candidates.
- Add embedding-list boundary coverage for `clips nullable=True`: schema
creation succeeds, inserting `clips=None` is rejected.
- Add BM25 nullable boundary coverage:
  - nullable BM25 function output sparse vector is rejected;
- nullable text input accepts `None`, and BM25 search does not return
the null-text row.

## Verification

```bash
cd tests && make ci BASE_REF=origin/master
# All checks passed!
# 4 files already formatted
```

```bash
python3 -m py_compile \
  tests/python_client/milvus_client/test_milvus_client_search_group_by.py \
  tests/python_client/milvus_client/test_milvus_client_search_pagination.py \
  tests/python_client/milvus_client/test_milvus_client_struct_array.py \
  tests/python_client/testcases/test_full_text_search.py
```

```bash
cd tests/python_client
../../.venv-python-client/bin/python -m pytest \
  milvus_client/test_milvus_client_search_group_by.py::TestGroupSearch::test_search_group_size \
  milvus_client/test_milvus_client_search_group_by.py::TestGroupSearch::test_hybrid_search_group_size \
  milvus_client/test_milvus_client_search_group_by.py::TestGroupSearch::test_search_pagination_group_by \
  milvus_client/test_milvus_client_search_pagination.py::TestMilvusClientSearchPagination::test_search_float_vectors_with_pagination_default \
  milvus_client/test_milvus_client_search_pagination.py::TestMilvusClientSearchPagination::test_search_sparse_with_pagination_default \
  milvus_client/test_milvus_client_search_pagination.py::TestMilvusClientSearchPagination::test_search_pagination_with_expression \
  milvus_client/test_milvus_client_struct_array.py::TestMilvusClientStructArrayInvalid::test_embedding_list_field_nullable_insert_none_not_supported \
  testcases/test_full_text_search.py::TestCreateCollectionWithFullTextSearchNegative::test_create_collection_for_full_text_search_with_nullable_function_output \
  testcases/test_full_text_search.py::TestSearchWithFullTextSearch::test_full_text_search_with_nullable_text_input \
  --host 10.104.18.67 --port 19530 -q
# 18 passed in 168.10s
```

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-05-22 11:34:30 +08:00
yanliang567andGitHub 880c2241e2 test: Enable storage v3 for CI helm values (#49893)
## What this PR does

Enable Storage V3 explicitly in CI Helm values by setting
`common.storage.useLoonFFI: true` with an inline comment for e2e,
e2e-amd, e2e-arm, and nightly deployments.

## Related dev PR

Related to #49880

## Verification

- Parsed all updated values files and their embedded
`extraConfigFiles.user.yaml` successfully.
- Verified all 18 target values files set `common.storage.useLoonFFI ==
true`.
- Ran `git diff --check`.

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-05-19 17:26:30 +08:00
yanliang567andGitHub 6920647ff7 test: add search aggregation python e2e coverage (#49876)
## Summary

Add Python E2E coverage for MilvusClient `search_aggregation`.

issue: #49046

## Coverage

- Basic/minimal parameter behavior, invalid parameter validation,
nesting depth, result-entry boundary, and mutually-exclusive search
params.
- Aggregation key, metric, order, and top-hits coverage across nullable
scalar fields, dynamic fields, explicit JSON fields, and smaller integer
key types.
- Vector compatibility coverage for dense/sparse/binary vectors,
nullable vector rows, range search, text match, BM25 search,
hybrid-search rejection, search iterator behavior, and StructArray
element / embedding-list search behavior.
- Strict xfail coverage for suspected Milvus issues: #49840, #49841, and
#49842.

## Test Plan

- [x] `uvx ruff check --config tests/ruff.toml
tests/python_client/milvus_client/test_milvus_client_search_aggregation.py`
- [x] `uvx ruff format --check --config tests/ruff.toml
tests/python_client/milvus_client/test_milvus_client_search_aggregation.py`
- [x]
`/Users/yanliang.qiao/fork/milvus-search-agg-e2e-plan-tests/.venv/bin/python
-m py_compile
tests/python_client/milvus_client/test_milvus_client_search_aggregation.py`
- [x] `git diff --check`
- [x]
`/Users/yanliang.qiao/fork/milvus-search-agg-e2e-plan-tests/.venv/bin/python
-m pytest milvus_client/test_milvus_client_search_aggregation.py
--collect-only -q`
- [x]
`/Users/yanliang.qiao/fork/milvus-search-agg-e2e-plan-tests/.venv/bin/python
-m pytest
milvus_client/test_milvus_client_search_aggregation.py::TestSearchAggregation::test_search_aggregation_integer_group_key_types
milvus_client/test_milvus_client_search_aggregation.py::TestSearchAggregation::test_search_aggregation_order_by_key_and_multi_criteria
milvus_client/test_milvus_client_search_aggregation.py::TestSearchAggregationIndependent::test_struct_array_embedding_list_search_reject_search_aggregation
--host 10.104.33.106 --port 19530 -q --tb=short -rxX`

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-05-18 19:30:30 +08:00
yanliang567andGitHub 3043c7f271 test: add container-kill chaos coverage (#49800)
## What changed

- Add Chaos Mesh `container-kill` schedules for Milvus components and
dependencies.
- Add container-kill coverage for etcd, MinIO, Pulsar, and Kafka targets
to match pod-kill coverage.
- Resolve real pod container names before creating container-kill
resources, which is required for release-prefixed Pulsar containers.
- Add selected-pod container-kill support for etcd leader/follower chaos
scenarios.

## Validation

- `python3 -m py_compile tests/python_client/chaos/test_chaos_apply.py
tests/python_client/chaos/test_chaos_apply_to_determined_pod.py
tests/python_client/utils/util_k8s.py`
- Parsed 17 container-kill YAML/template files with PyYAML.
- `git diff --check`
- Verified 4am Chaos Mesh v2.8.0 CRD supports `container-kill` and
`containerNames`.
- Server-side dry-run passed for static container-kill manifests against
4am Chaos Mesh, excluding Pulsar static YAML because Pulsar container
names are filled dynamically at runtime.
- Server-side dry-run passed for a Pulsar container-kill Schedule after
filling real containerNames.
- Server-side dry-run passed for etcd selected-pod PodChaos after
filling real containerNames.

Fixes #49798

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-05-14 19:42:11 +08:00
yanliang567andGitHub 371ee7aab6 test: Add nullable vector coverage for bulk insert (#49685)
issue: #49678

## What this PR does

Adds Python E2E coverage for nullable vector fields in bulk
insert/import paths:

- JSON import with nullable dense vector, nullable sparse vector,
nullable scalar fields, explicit `null`, and omitted vector fields.
- Parquet import with nullable scalar and nullable float vector columns
using Arrow null validity.
- RemoteBulkWriter JSON/CSV/Parquet output with nullable float vectors,
including generated multi-batch Parquet import coverage.
- Negative coverage that non-nullable float vector import rejects
`null`, with `failed_reason` assertions.
- JSON import coverage for nullable values across FLOAT, BINARY,
FLOAT16, BFLOAT16, SPARSE, and INT8 vector types.

CSV BulkWriter import currently passes `nullkey="null"` to match the
existing writer output behavior tracked in #49678.

## Verification

```bash
.venv-python-client/bin/ruff check tests/python_client/testcases/test_bulk_insert.py
# All checks passed!
```

```bash
.venv-python-client/bin/ruff format --check tests/python_client/testcases/test_bulk_insert.py
# 1 file already formatted
```

```bash
python3 -m py_compile tests/python_client/testcases/test_bulk_insert.py
```

```bash
PYTHONPATH=tests/python_client .venv-python-client/bin/python -m pytest \
  -o addopts='' --collect-only -q \
  tests/python_client/testcases/test_bulk_insert.py::TestBulkInsertNullableVector
# 12 tests collected
```

```bash
PYTHONPATH=tests/python_client .venv-python-client/bin/python -m pytest \
  -o addopts='' -q \
  tests/python_client/testcases/test_bulk_insert.py::TestBulkInsertNullableVector \
  --host 10.100.36.172 --port 19530 \
  --minio_host 10.104.18.236 --minio_bucket yanl-master \
  --tb=short --disable-warnings
# 12 passed in 273.69s (0:04:33)
```

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-05-11 19:06:09 +08:00
yanliang567andGitHub eea56c4eed test: Fix flaky L2 search assertions (#49633)
## What this PR does

Fixes #49542

This updates stale L2 search test assertions without changing the
original test coverage points:
- keep the Bounded consistency range-search case on Bounded, but allow
already-visible growing data to be returned
- keep the duplicate-primary-key search case focused on PK
de-duplication, without requiring de-duplicated results to still equal
the requested limit
- keep distance ordering validation, but compare floating-point ordering
with a small epsilon instead of strict list equality

## Tests

Against Milvus `10.104.18.67:19530`:

- `pytest -q --host 10.104.18.67 --port 19530 --tag L2
milvus_client/test_milvus_client_range_search.py::TestRangeSearchIndependent::test_range_search_with_consistency_bounded`
- 2 passed
- `pytest -q --host 10.104.18.67 --port 19530 --tag L2
milvus_client/test_milvus_client_search_by_pk.py::TestSearchByPkIndependent::test_search_by_pk_with_duplicate_primary_key`
- 1 passed
- `pytest -q --host 10.104.18.67 --port 19530 --tag L2
milvus_client/test_milvus_client_search_pagination.py::TestMilvusClientSearchPagination::test_search_with_pagination_topk`
- 3 passed

Flaky check with `-n 10 --count=10`:
- Bounded consistency: 20 passed
- Duplicate primary key: 10 passed
- Pagination topK: 30 passed

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-05-09 16:00:08 +08:00
yanliang567andGitHub aa45c0db57 test: Fix NGRAM multilingual test assertion (#49454)
Fixes #48917

This fixes the multilingual NGRAM test by removing the incorrect
even-distribution count assertion. The test data is inserted in two
batches of 3000 rows, and each batch resets keyword assignment with j %
16, so keywords are not distributed evenly across all 6000 rows.

The test now verifies the actual intent: NGRAM-indexed JSON LIKE results
are non-empty and exactly match the non-indexed JSON LIKE scan results
for each multilingual keyword.

Verification:

```bash
source /Users/yanliang.qiao/fork/milvus/tests/python_client/.venv/bin/activate
cd tests/python_client
python3 -m pytest testcases/indexes/test_ngram.py::TestNgramBuildParams::test_ngram_search_with_multilingual_utf8_strings -q --host 10.104.15.131
```

Result: 1 passed in 19.32s

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-04-30 15:27:50 +08:00
aac5f81d18 test: fix assert_statistic false failures for low-frequency checkers (#49349)
## Problem

`assert_statistic()` in `chaos_commons.py` evaluated the success
condition as:

```python
succ_rate >= succ_rate_threshold and total > 2
```

Low-frequency checkers (`AddFieldChecker`, `AddVectorFieldChecker`) have
~111s cycle times and complete only ~2 operations within a 10-minute
test window. This caused `total > 2` to always be `False` even when
`succ_rate = 1.0`, producing false failures in
`test_concurrent_operation`.

Root cause observed in deploy_test_cron runs where checkers reported
`succ_rate: 1.00, total: 2` but still triggered `pytest.assume(False)`.

## Fix

Split the assertion into two cases:

- `total == 0`: checker never executed any operation → always fail (real
issue: thread failed to start or service completely down)
- `total >= 1`: at least one operation completed → check `succ_rate`
only, no minimum total threshold

`succ_rate = 1.0, total = 2` is a valid passing result for a
low-frequency checker in a short test window.

## Note

`test_chaos_bulk_insert.py` contains a stale local copy of
`assert_statistic` with the same pattern (predates the 2023 refactor in
#25890) but only uses high-frequency checkers so does not trigger this
issue in practice. Left as a separate cleanup.

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 17:01:45 +08:00
yanliang567andGitHub cdafd8f0b4 test: add regression test for queries uninterrupted during replica scale-up (#49334)
## Summary

Adds a regression test
`test_milvus_client_load_replica_change_query_uninterrupted` to verify
that queries are not interrupted when changing the replica number on an
already-loaded collection (issue #49304).

The test:
1. Loads a 100k-row collection with replica=1
2. Starts a background query loop with `timeout=2` (critical to surface
gRPC-masked errors)
3. Calls `load_collection(replica_number=2)` to trigger the bug
condition
4. Asserts zero query failures occurred during the replica transition

Also updates the docstring for `test_milvus_client_load_replica_change`
to match the revised test flow (hot replica change without
release+reload).

Also fixes all pre-existing ruff lint violations (452 errors) in the
file so CI `code-check` can pass:
- F403/F405: replaced star import with explicit imports
- I001: fixed import grouping/ordering
- F541: empty f-string prefixes
- F841: unused variable assignments
- E712: `== True/False` comparisons
- W291: trailing whitespace in docstrings
- `import numpy` → `import numpy as np`

### Changes

**Modified Files:**
- `tests/python_client/milvus_client/test_milvus_client_collection.py`:
new test case + docstring update + ruff lint fixes

### Test Plan

- [x] New test
`test_milvus_client_load_replica_change_query_uninterrupted` reproduces
the bug on Milvus 2.6.15 (5/5 FAILED with `GetShardLeaders: collection
not fully loaded`)
- [x] New test passes on master build including fix PR #49305 (6/6
PASSED)
- [x] `test_milvus_client_load_replica_change` passes on both 2.6 and
master (6/6 PASSED each)
- [x] `ruff check` and `ruff format --check` pass with zero errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-04-25 10:35:45 +08:00
776e24e9d4 test: fix NullVectorQueryChecker false positive when UpsertChecker overwrites with null (#49336)
## Summary

Fix two categories of checker false failures in concurrent chaos tests.

issue: #49329

### Fix 1: NullVectorQueryChecker false positive on null rows

When `UpsertChecker` runs concurrently on the shared collection, it can
legitimately overwrite rows with null nullable vector values (20% null
probability in `gen_row_data_by_schema`). After `_non_null_pk_samples`
is
refreshed, the newly sampled PKs may include rows inserted by
`UpsertChecker`
which are then overwritten with null on the next upsert cycle.

**Fix**: treat `null_rows` (like empty results) as a stale sample event
— refresh
the sample and return `True`. The all-null fallback path still detects
systematic
data corruption when no non-null rows can be found at all.

### Fix 2: PartialUpdateChecker false failures on
SchemaMismatchRetryableException

`PartialUpdateChecker` calls `milvus_client.upsert(...,
partial_update=True)` which
hits the same schema_timestamp version check as
InsertChecker/UpsertChecker (already
fixed in #49330). When `AddVectorFieldChecker` adds a nullable vector
field, the
server increments the schema version and rejects stale-timestamp
requests.

`PartialUpdateChecker` is used by `test_single_request_operation.py`.

**Fix**: same pattern as the already-fixed checkers — catch
`SchemaMismatchRetryableException`, call `_invalidate_schema()`, retry
once.

### Not fixed (don't need it)

- `InsertFreshnessChecker` / `UpsertFreshnessChecker`: no test uses them
(legacy)
- `InsertFlushChecker`: no test uses it (legacy)
- `EntityTTLChecker`: uses its own collection with a fixed schema,
unaffected by `AddVectorFieldChecker`
- `SnapshotRestoreChecker._do_dml_operations()`: `SchemaMismatch`
already caught as `log.warning`, not counted in succ_rate

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 19:19:45 +08:00
6d0006b119 test: fix InsertChecker/UpsertChecker false failures on SchemaMismatchRetryableException (#49330)
## Summary

Fix false failures in `InsertChecker` and `UpsertChecker` when
`AddVectorFieldChecker` runs concurrently during chaos tests.

issue: #49329

### Root Cause

When `AddVectorFieldChecker` adds a nullable vector field, the server
increments the collection's schema version (`schema_timestamp`). The
pymilvus SDK embeds the cached `schema_timestamp` in each insert/upsert
gRPC request. If the cached value is stale, the server rejects the
request with `SchemaMismatch` (error code 62), which pymilvus raises as
`SchemaMismatchRetryableException`.

The data itself is always valid — new fields are always nullable, so
omitting them is fine. The rejection is purely a schema version check.

### Fix

Catch `SchemaMismatchRetryableException` in both
`InsertChecker.insert_entities()` and `UpsertChecker.upsert_entities()`.
On catch:
1. Call `_invalidate_schema()` to flush the stale cache entry (same
mechanism as pymilvus's internal `retry_on_schema_mismatch` decorator
used by `upsert_rows`)
2. Regenerate row data with the refreshed schema
3. Retry the operation once

Note: `insert_rows` has no `@retry_on_schema_mismatch` decorator (unlike
`upsert_rows`), so the exception always propagates and must be handled
at the checker level.

### Changes

- `tests/python_client/chaos/checker.py`: add
`SchemaMismatchRetryableException` import and
retry-with-cache-invalidation handlers in `InsertChecker` and
`UpsertChecker`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 17:55:45 +08:00
1a1f4043e3 test: handle stale PKs in NullVectorQueryChecker when rows deleted concurrently (#49322)
## Summary

`NullVectorQueryChecker` pre-samples non-null PKs at init time and
stores them in `_non_null_pk_samples`. During concurrent testing,
`DeleteChecker` shares the same collection and continuously deletes rows
(3000 at a time). When all pre-sampled PKs are deleted, querying them
returns 0 rows, causing a false-positive failure: "no rows found for N
known non-null PKs of 'float_vector'".

**Root cause**: Pre-sampled PKs become stale under concurrent deletes.
Empty query result does not indicate data corruption — it means the rows
were deleted.

**Fix**: When query returns 0 rows for sampled PKs, treat as non-failure
(rows deleted, not corrupted), refresh the sample so subsequent calls
use valid PKs.

The existing `null_rows` check (lines 3154–3159) still correctly detects
genuine data corruption (non-null values becoming null), unaffected by
this change.

**Observed symptom in deploy_test_cron build #3984**:
- `Op.null_vector_query` succ rate ~0.35% (285/286 failures)
- All failures: `[no rows found for known non null PKs of float vector]`
- Concurrent `DeleteChecker` deleting PKs from shared collection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:09:45 +08:00
4a1712adbd test: add L2 coverage for add nullable vector field with non-float types and index/insert orderings (#49287)
## Summary

### 1. L2 parametrized coverage for `add_collection_field` with nullable
vector fields

The existing L0 tests only cover `FLOAT_VECTOR`. This adds L2 coverage
for the remaining vector types and operation orderings.

**New tests:**

- `test_milvus_client_add_vector_field_all_types` (10 cases): covers
`BINARY_VECTOR`, `SPARSE_FLOAT_VECTOR`, `FLOAT16_VECTOR`,
`BFLOAT16_VECTOR`, `INT8_VECTOR` × their valid index types (`BIN_FLAT`,
`BIN_IVF_FLAT`, `SPARSE_INVERTED_INDEX`, `SPARSE_WAND`, `HNSW`,
`IVF_FLAT`). Validates: mixed null/non-null insert → load-without-index
rejection → create_index → reload → search → search-by-id null check.

- `test_milvus_client_add_vector_field_index_insert_order` (10 cases):
covers the two valid orderings of `add_field` / `create_index` /
`insert` for the 5 non-float vector types. `FLOAT_VECTOR` orderings are
already covered by the L0 tests.

### 2. Fix `NullVectorQueryChecker` false negatives (chaos checker)

`NullVectorQueryChecker.query()` previously used `vec_field is not null`
as a server-side filter, which fails with:

```
MilvusException: IsNull/IsNotNull operations are not supported on vector fields
```

This caused 100% failure rate for `Op.null_vector_query` in all chaos
test instances (CI run #3979).

**Fix**: replace the unsupported server-side filter with a PK-based
approach:
- At init time, sample PKs that have non-null vector data for each
nullable field (80% insert ratio guarantees a sufficient sample from the
original schema fields).
- Each `query()` call fetches those specific rows by `pk in [...]` and
verifies server-returned values are still non-null.
- Fallback to a Python-side null check when no PKs were sampled.
- Dynamically-added `new_vec_*` fields are still excluded (pre-existing
segments have all-null by design).

## Test Plan

- [x] All 20 new L2 cases pass against Milvus master-20260422
- [x] Existing L0/L1 tests unaffected
- [x] `NullVectorQueryChecker` no longer uses unsupported `is not null`
vector filter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 10:31:45 +08:00
d73aa77618 test: fix NullVectorQueryChecker false positive for dynamically-added nullable vector fields (#49263)
## Summary

`NullVectorQueryChecker` was producing spurious failures during chaos
tests because it incorrectly treated all-null query results as "possible
data corruption".

**Root cause**: The checker collects nullable vector fields from
`describe_collection` at init time. When a persistent collection is
reused across test runs, it already contains `new_vec_XXX` fields added
by `AddVectorFieldChecker` in previous runs. Segments sealed *before*
those fields were added have all-null values for them by design — this
is correct behavior. A `limit=50` query with no filter can return 50
rows all from pre-existing segments → all null → false alarm. During
s3-pod-failure chaos, fewer new non-null rows were being flushed
successfully, making the all-null result more frequent and pushing the
succ rate below the pass threshold.

**Fix (two changes):**
1. Exclude `new_vec_*` fields from `nullable_vector_fields` at init —
dynamically-added fields are already verified by `AddVectorFieldChecker`
immediately after each insertion
2. Use a `{field} is not null` filter in the query — makes the check
semantically correct: verify that rows with non-null vector values
remain queryable under chaos, and that Milvus applies the filter
correctly

issue: #49262

## Test plan

- [ ] Chaos test `test_concurrent_operation.py` with s3-pod-failure —
`null_vector_query` succ rate should no longer drop below threshold
- [ ] `NullVectorQueryChecker` still catches genuine filter failures:
rows returned by `is not null` filter that contain null values are
correctly reported as failure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:01:44 +08:00
yanliang567andGitHub bc80f179ff test: add large topk boundary and index-after-insert tests (#49242)
## Summary

Add two new tests for the `query_mode=large_topk` collection property:

- **`test_create_index_after_insert_with_large_topk`** (L1): Verifies
`create_index` succeeds on a populated collection with
`query_mode=large_topk`, and that large topk search (limit > 16384)
works correctly after index build. This isolates
data-at-index-build-time behavior from the alter/drop property flow.

- **`test_large_topk_boundary_2m_rows`** (L3): Verifies topk boundary
enforcement with 2M rows:
  - `limit = 999,999` → succeeds
  - `limit = 1,000,000` (max) → succeeds, returns 1M results
  - `limit = 1,000,001` → fails with expected error

Also adds `large_topk_max = 1_000_000` constant documenting the maximum
supported topk.

### Test Plan

- [x] `test_create_index_after_insert_with_large_topk` (L1) — verified
passing on a standalone Milvus instance
- [x] `test_large_topk_boundary_2m_rows` (L3) — boundary searches
verified manually: limit=1,000,000 passed in 33.8s, limit=1,000,001
returned expected error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-04-23 11:03:44 +08:00
b7e67e4b74 test: update search iterator mul-db test to reflect SearchIteratorV2 behavior (#49113)
## What

Update `test_milvus_client_search_iterator_using_mul_db` to reflect the
behavior of `SearchIteratorV2`.

## Root Cause

The test was written for `SearchIteratorV1`, which reads `db_name` from
the connection context on each `next()` call. This meant calling
`using_database()` after iterator creation would redirect subsequent
`next()` calls to the new db, causing a collection-ID mismatch and the
error `"alias or database may have been changed"`.

`SearchIteratorV2` (default since pymilvus 2.7.0rc185) captures
`db_name` at creation time via
`_generate_call_context(db_name=self._config.db_name)`. The captured
context is baked into the iterator — `using_database()` called after
creation has no effect on it. The iterator continues to return results
from the original db, so the expected error never triggers.

This caused a pre-existing CI flake observed in build
[#25680](https://jenkins-milvus-ci.milvus.io/job/MILVUS-CI-V2-PR-PIPELINES/job/milvus-e2e-pipeline-gcp/25680/).

## Fix

- Update the expected outcome from error to success
- Update `check_items` to verify the iterator returns results in the
correct batch size
- Update docstring and inline comments to describe V2 semantics

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 10:51:43 +08:00
0bc85c0cac fix: prevent nil pointer panic in go_client teardown when Milvus is unreachable (#49112)
## Summary

- `teardown()` in `tests/go_client/testcases/helper/test_setup.go` did
not return early on connection error, causing a SIGSEGV when subsequent
calls hit a nil `Client`
- `MilvusClient.Close()` in `tests/go_client/base/milvus_client.go` now
has a nil guard as a defensive measure

issue: #49111

## Changes

- `test_setup.go`: add `return` after logging connection error in
`teardown()`
- `milvus_client.go`: add nil check in `MilvusClient.Close()` before
calling inner client

## Test plan

- [ ] CI go-sdk pipeline passes without SIGSEGV when Milvus pod is slow
to start
- [ ] No regression in normal teardown flow when Milvus is available

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 16:37:46 +08:00
32cc35982d test: fix flaky bfloat16 pagination test by pinning DISKANN search_list_size (#49033)
## Summary

Fixes a flaky test in `test_search_bfloat16_with_pagination_default`
that failed at ~40% rate (2/5 runs locally), with overlaps of 76–79%
against the 80% threshold.

issue: #49030

### Root Cause

When `offset` is set, Milvus proxy computes `queryTopK = limit + offset`
and passes it directly to DISKANN as the search depth. Without an
explicit `search_list_size`, DISKANN scales its graph traversal
proportionally to `queryTopK`:

| Call | Internal topk | Graph depth |
|------|--------------|-------------|
| Page 1 (offset=100, limit=100) | 200 | shallow (5× less than full) |
| Page 3 (offset=300, limit=100) | 400 | medium (2.5× less than full) |
| Full search (limit=1000) | 1000 | deep |

Boundary candidates at the edge of each page differ between the
paginated and full searches, producing ~76–79% overlap and flaky
failures.

### Fix

Pin `search_list_size=1200` on **both** paginated and full searches.
DISKANN uses this as a fixed exploration budget regardless of `topk`, so
both calls examine the same candidate pool and agree on boundary
positions.

Additional improvements:
- Per-page overlap threshold: 80% → 90% (reflects actual overlap with
matched search depth)
- Added overall recall assertion (≥95%) to validate cross-page coverage
- Expanded docstring explaining the DISKANN pagination consistency model

### Test Plan

- [x] Reproduced original failure: 2/5 runs failed (40% rate), overlap
76–79%
- [x] Verified fix: 5/5 runs passed after pinning `search_list_size`
- [x] Tested against Milvus `master-20260413` on standalone instance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 10:59:54 +08:00
e34dc70db0 fix: reject range_filter without radius in search params (#48934)
## Summary

When a user provides only `range_filter` without `radius` in search
params, the request silently degrades to a regular top-K ANN search —
the `range_filter` constraint is completely ignored and results violate
the specified bound.

This fix adds early validation in the proxy layer to reject such
requests with a clear `ErrParameterInvalid` error.

**Root cause**: The C++ core (`CheckAndUpdateKnowhereRangeSearchParam`
in `Utils.cpp`) uses `radius` as the gate to enter range search mode.
Without `radius`, it returns `false` and the caller falls back to top-K
search, silently discarding `range_filter`. The Go proxy layer had no
validation to catch this before it reached the core.

**Affected metric types**: COSINE, IP, L2 — all three ignore
`range_filter` when `radius` is absent.

issue: #48915

## Changes

- `internal/proxy/search_util.go`: reject `range_filter` without
`radius` with `ErrParameterInvalid`
- `internal/proxy/task_search_test.go`: add unit test
`range_filter_without_radius` covering the new validation

## Test Plan

- [x] New unit test
`TestSearchTask_parseSearchInfo/parseSearchInfo_error/range_filter_without_radius`
verifies the error is returned
- [x] gofumpt and gci checks pass on changed files
- [x] Manually reproduced the bug on a live Milvus instance (COSINE, IP,
L2 all affected)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 17:37:42 +08:00
6571ec7772 test: add query/hybrid_search coverage for query_mode=large_topk (#48896)
## What does this PR do?

Supplements #48736 with missing interface coverage for
`query_mode=large_topk` collection property.

### New test cases (4)

**`TestLargeTopkShared`** (shared collection, read-only):
- `test_query_large_limit` (L1): `query()` with `limit=16385` succeeds
when property is set
- `test_query_without_property_fails` (L2): `query()` with `limit=16385`
is rejected without property

**`TestLargeTopkIndependent`** (per-test collection):
- `test_hybrid_search_large_topk` (L1): `hybrid_search()` with
`limit=16385` succeeds when property is set
- `test_hybrid_search_without_property_fails` (L2): `hybrid_search()`
with `limit=16385` is rejected without property

### Why not iterator interfaces?

`search_iterator` and `query_iterator` are **not affected** by
`query_mode=large_topk`:
- `batch_size > 16384` is rejected client-side by the SDK (ParamError,
independent of the property)
- Iterator `limit` (total result count) uses internal pagination with
`batch_size <= 16384` per request, so per-request topk never exceeds
16384

### Error message note

`query()` and `hybrid_search()` return a different error message than
`search()` for the same restriction:
- `search()` → `"topk [N] is invalid, it should be in range [1, 16384]"`
- `query()` / `hybrid_search()` → `"invalid max query result window,
(offset+limit) should be in range [1, 16384], but got N"`

All 4 tests verified against a live Milvus instance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:25:48 +08:00
07930ff01a test: relax limit assertion for HNSW_SQ params48 (M=2,efConstruction=1) to fix flaky test (#48788)
## Summary

- Add `relaxed_limit: True` marker to params48 (`M=2, efConstruction=1,
sq_type=SQ6`) in `idx_hnsw_sq.py`
- Update `test_hnsw_sq_build_params` to only assert `> 0` results for
relaxed-limit cases, keeping strict `topK` assertion for all other
combinations

## Root Cause

With `M=2` and `efConstruction=1`, the HNSW graph has extremely poor
connectivity. Depending on random data distribution across concurrent
workers, the graph may have disconnected components — making it
impossible to traverse enough neighbors to fill `topK=10`. This causes
`AssertionError` intermittently under 6-way concurrency.

This is **expected HNSW behavior** for extreme boundary parameters, not
a Milvus server bug.

**Reproduction rate**: ~33% failure under `-n 6` concurrent load (4/12
runs failed before fix, 0/12 after).

issue: #48762

## Test plan

- [x] Reproduced failure: 4/12 runs failed with `-n 6 --count 12` before
fix
- [x] Verified fix: 12/12 passed after fix
- [x] All other `test_hnsw_sq_build_params` parametrizations unaffected
(strict limit assertion unchanged)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 09:36:33 +08:00
967b72366c test: Fix none_default/ttl/range_search/alias compatibility (#48786)
## Summary

Rebase of closed PR #48348. Fixes test compatibility issues across
multiple test files for none_default, TTL, range_search, and alias
tests.

### Key Changes

- Fix TTL test to verify search/query across all consistency levels
(Eventually, Bounded, Session, Strong)
- Use parameterized field names instead of hardcoded strings
- Repair error codes and trivially-true assertions in range search/alias
tests
- Use `request.cls` to set shared_data as class attribute in fixture
- Use NullValue sentinel for SQL NULL semantics in expression filter
tests
- Update alias error messages to match current Milvus server responses

### Changes

**Modified Files:**
- `test_milvus_client_ttl.py`: Multi-consistency-level search/query
verification
- `test_milvus_client_range_search.py`: Fix error codes and assertions
- `test_milvus_client_search_none_default.py`: NullValue sentinel,
fixture fix
- `test_milvus_client_alias.py`: Updated error messages

issue: https://github.com/milvus-io/milvus/issues/48348

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 19:05:38 +08:00
3af5fe71e3 test: rewrite scalar expression filtering tests with eval ground truth and bug regression (#48450)
## Summary
- Rewrite `test_milvus_client_scalar_filtering.py` (2156→1567 lines)
with eval-based ground truth, deterministic boundary values, and
comprehensive operator/type coverage
- Add `NullValue` sentinel class in `common_func.py` for SQL NULL 3VL
semantics (reusable across test files)
- 4 focused test classes replacing 1 monolithic class: Correctness,
IndexConsistency, CornerCase (bug regression), JSON

## Why
The original test had fundamental gaps discovered while analyzing real
bugs:
- **No boundary values** (INT64_MAX/MIN, 2^53) → missed #48440
(overflow)
- **No ground truth** (only self-consistency) → couldn't detect wrong
results from all code paths
- **Hand-written validators** with incorrect NULL handling → false
passes
- **No NOT+AND+OR compound coverage** → missed #48441 (3VL bitmap)
- **No bool literal / mixed-type IN tests** → missed #48443, #48442

## What's covered now

**Type coverage**: INT8/16/32/64, FLOAT, DOUBLE, BOOL, VARCHAR, JSON,
ARRAY(INT8/16/32/64/FLOAT/DOUBLE/BOOL/VARCHAR)

**Operator coverage**: `==, !=, >, <, >=, <=, IN, NOT IN, LIKE (12
patterns), IS NULL, IS NOT NULL, +, -, *, /, %, **, array_contains,
array_contains_all, array_contains_any, array_length, json path,
json_contains`

**Compound expressions**: AND, OR, NOT, &&, ||, NOT+AND, NOT+OR, triple
nesting, DeMorgan, double NOT, 3-way AND/OR, cross-field, range patterns

**Index consistency**: INVERTED, BITMAP, STL_SORT, TRIE — verified with
both cross-index comparison AND ground truth

**Bug regression (L0)**: #48440 overflow (+,-,*), #48441 3VL
NOT+nullable (incl. all-NULL segment), #48442 JSON mixed-type IN
precision, #48443 bool literal parser

## Test results (master-20260318-3ec434d)
```
37 tests: 32 passed, 5 failed (all real Milvus bugs)
L0+L1 (19 tests, -n 4): 37 seconds
```

| Failed test | Issue |
|---|---|
| test_int64_overflow_addition | #48440 |
| test_int64_overflow_subtraction | #48440 |
| test_3vl_not_all_null_segment | #48441 |
| test_bool_literal_in_logical_expr | #48443 |
| test_json_mixed_type_in_precision | #48442 |

## Tag distribution
- **L0 (7)**: Bug regression — every PR must run
- **L1 (12)**: Core type correctness + compound + index consistency
- **L2 (18)**: Extended types + all arrays + JSON path/contains

issue: #48048

## Test plan
- [x] L0+L1 pass (minus known Milvus bugs)
- [x] L2 pass
- [x] Eval engine verified: SQL NULL 3VL, NOT propagation, NOT IN, IS
NULL/IS NOT NULL
- [x] No false passes: parser errors → pytest.fail, skip rate tracking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:17:38 +08:00
c5c84d5cfe test: add e2e tests for query_mode=large_topk collection property (#48736)
## Summary

- Add `tests/python_client/testcases/test_large_topk.py` covering the
`query_mode: large_topk` collection-level property
- 23 test cases across `TestLargeTopkShared` (read-only, shared
collection) and `TestLargeTopkIndependent` (per-test collection)
- Covers: create/alter/drop property CRUD, topk boundary (16385, up to
`large_topk_total - default_nb`), persistence after reload, growing
segments, case sensitivity of key vs value, negative paths

## Test coverage

| Priority | Cases |
|----------|-------|
| L0 | smoke (property set + search), topk > 16384 allowed |
| L1 | various topk values, alter/drop property workflow, persistence
after reload, growing segment, negative (alter/drop with index present)
|
| L2 | empty collection, round-trip add→drop, invalid value, case
sensitivity (key case-sensitive, value case-insensitive), contrast
without property |

## Notes

- `query_mode=large_topk` forces IVF RBQ2 internally; FLAT index is used
in test setup to maintain 100% recall for exact count assertions
- `col_large_topk` contains `large_topk_total=21000` rows (>
`large_topk_first=16385` with `default_nb=3000` headroom)
- Key/value case sensitivity inconsistency tracked in
https://github.com/milvus-io/milvus/issues/48725

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:13:38 +08:00
35881c7dcb fix: filter git tags with --match 'v*' to avoid pkg/ submodule tags in MILVUS_VERSION (#48418)
## Summary

- Add `--match 'v*'` to `git describe --exact-match --tags` in
`MILVUS_VERSION` calculation
- Prevents `pkg/v2.6.13` (Go submodule tag) from being picked instead of
`v2.6.13` on release builds
- Without this fix, `GetVersion` returns `pkg/v2.6.13` instead of
`2.6.13` because `sed 's/^v//'` doesn't strip the `pkg/` prefix

### Root Cause

The milvus repo uses Go multi-module: `pkg/` has its own `go.mod` with
tags like `pkg/v2.6.13`. When both `v2.6.13` and `pkg/v2.6.13` exist on
the same commit, `git describe --exact-match --tags` may return the
`pkg/` prefixed tag.

issue: #47823

## Test plan

- [ ] Verify on a tagged commit with both `v*` and `pkg/v*` tags: `git
describe --exact-match --tags --match 'v*'` returns only the root tag
- [ ] Dev builds unaffected (no exact tag match, falls through to
branch-date-commit format)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 16:33:29 +08:00
d748a8b8b5 fix: update expected error for test_search_no_connection after pymilvus rc162 (#48504)
## Summary
- Update `test_search_no_connection` expected error to match pymilvus
2.7.0rc162 behavior

## Root Cause
After pymilvus upgrade to rc162 (#48424), `MilvusClient.close()` sets
the internal gRPC handler to `None`. When `search()` is called after
`close()`:
- **Before rc162**: `MilvusException(code=1, "should create connection
first")`
- **After rc162**: `AttributeError("'NoneType' object has no attribute
'search'")` → wrapped as `err_code=-1`

This was not caught by PR #48424's CI because:
1. The test was refactored from ORM to MilvusClient v2 style in PR
#48347 (merged after #48424's CI ran)
2. PR #48424's CI ran the old ORM version which uses
`remove_connection()` (different code path, still returns err_code=1)
3. Only after both PRs merged to master did the combination break in
hourly CI

## Test plan
- [x] `test_search_no_connection` passes locally against Milvus
10.104.14.152 with pymilvus 2.7.0rc162

issue: #48048

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 15:43:35 +08:00
17532517c6 test: Fix sparse/group_by/text_match/diskann/invalid/by_pk (#48347)
## Summary
- GPU→L1, zip() for positional index, add metric_type, fix spelling
- IVF_SQ8→DISKANN, skip DISKANN mmap, fix INT8 metric, filter assertions
- Fix false-pass bypass in check_search_results for empty hits

## Code Review Fix (0e4ad86c13)

### check_search_results: remove empty-hits bypass

`check_search_results` in `func_check.py` had a `if len(hits) == 0:
continue` guard that silently skipped all verification (including limit
check) when search returned no results. This caused tests with filters
matching zero rows to false-pass instead of failing.

Removed the 2-line guard entirely. The existing `assert len(hits) ==
check_items["limit"]` already handles this correctly — when limit is
specified and hits is empty, the assertion properly fails.

**Impact:** `test_search_with_scalar_field` in
`test_milvus_client_search_diskann.py` filters `int64 in [1, 2, 3, 4]`
on randomly-generated INT64 data (non-PK field uses full-range random
values). This matches 0 rows, and previously false-passed due to the
bypass. After the fix, it correctly fails. The filter in the test should
also be updated to use values that exist in the data.

Verified: ran all 6 PR test files (L0+L1, `-n 4`) — 88 passed, 1
expected failure (`test_search_with_scalar_field`), 9 skipped.

issue: #48048
🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:51:30 +08:00
61e929c2cf test: Fix json/string/iterator/pagination verification (#48346)
## Summary
- Add check_task/filter assertions, fix hardcoded COSINE, add pk_range
to func_check
- Reduce L0 iterator combos, fix bare field names, increase
overlap_ratio

issue: #48048
🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:47:29 +08:00
cccd4b7259 test: Refactor search_array (1→7 tests) and e2e (23→loop) (#48344)
## Summary
- search_array: 1 test → 7 tests with Shared+Independent pattern
- e2e: 23 repetitive query blocks → data-driven loop (708→411 lines)

issue: #48048
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:45:28 +08:00
519719f7f8 test: Fix search_v2 series verification and add index constant (#48345)
## Summary
- Add `ct.all_dense_float_index_types` constant (replaces fragile `[:8]`
slices)
- Fix metric, duplicate keys, GPU→L1, IVF_FLAT→FLAT, spelling

issue: #48048
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:17:27 +08:00
78ca412942 test: Refactor search_load from 33 tests to parametrize-driven (#48343)
## Summary
Collapse 33 near-identical load/release/delete permutation tests into
parametrize-driven design (1479→612 lines, -59%).

issue: #48048
🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:13:27 +08:00
4467d61296 test: Fix hybrid_search critical bugs and verification gaps (#48342)
## Summary
- Fix `fitler` typo → `filter` (2 locations, filters were silently
ignored)
- Add `metric` and `enable_milvus_client_api` to 33 check_items
- Fix loop variable bug, remove stub test, single-value parametrize,
spelling

issue: #48048
🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:57:27 +08:00
6cc4d9a9d0 test: Remove hardcoded metric_type from chaos test search params (#48255)
## Summary
- Remove `metric_type` from `DEFAULT_SEARCH_PARAM` and
`DEFAULT_INT8_SEARCH_PARAM` in chaos test constants, letting the server
auto-infer metric type from the index
- Fixes chaos test failures (broken since build #24014) where
`AddVectorFieldChecker` creates COSINE-indexed vector fields but all
search checkers hardcode `metric_type: L2`

## Root Cause
In chaos tests, `AddVectorFieldChecker` dynamically adds nullable
FLOAT_VECTOR fields with **COSINE** HNSW index. After etcd pod-failure
recovery, `SearchChecker`, `HybridSearchChecker`, and
`NullVectorSearchChecker` re-initialize and discover these new fields.
When they search on them using hardcoded `metric_type: L2`, the server
returns:
- `metric type not match: invalid parameter[expected=COSINE][actual=L2]`
- `hybrid_search` 0% success rate (iterates ALL vector fields)
- `search`/`null_vector_search` ~28% success rate

Reference failure: [chaos-test-cron
#24056](https://qa-jenkins.milvus.io/blue/organizations/jenkins/chaos-test-cron/detail/chaos-test-cron/24056/pipeline/)

## Test plan
- [x] Verified on Milvus master (`master-20260313-f163e94`): search
without `metric_type` correctly auto-detects L2 and COSINE from index
- [x] Verified hybrid search across mixed metric types (L2 + COSINE)
works without specifying `metric_type`
- [x] Backwards compatible: explicit `metric_type` in search params
still works

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 15:33:25 +08:00
5fcb3334d1 test: Fix chaos checker dimension mismatch and vector field limit handling (#48105)
## Summary

Fix two bugs in chaos test checkers that cause
`test_concurrent_operation.py` to fail consistently (broken since build
#24014 in chaos-test-cron):

- **Op.hybrid_search 0% success rate**:
`HybridSearchChecker.gen_hybrid_search_request()` used a single cached
`self.dim` for all vector fields. When `AddVectorFieldChecker` adds
fields with different dimensions to the same collection, hybrid search
sends vectors with wrong dimensions, causing `vector dimension mismatch`
errors.
- **Op.add_vector_field 0% success rate**: Hardcoded `dim=32` created
dimension inconsistency with the collection schema (default `dim=128`).
The pre-check via `describe_collection` field counting was unreliable —
replaced with server-side error handling that catches `maximum vector
field` error and gracefully falls back to insert-only.

### Changes

**`tests/python_client/chaos/checker.py`:**
- `HybridSearchChecker.gen_hybrid_search_request()`: Query each vector
field's actual dimension from schema via `get_schema()` instead of using
a single cached dim
- `AddVectorFieldChecker.add_vector_field()`: Use `self.dim` instead of
hardcoded `dim=32`; catch server-side "maximum vector field" error and
fallback to insert

### Jenkins failure reference

https://qa-jenkins.milvus.io/blue/organizations/jenkins/chaos-test-cron/detail/chaos-test-cron/24056/pipeline

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:13:24 +08:00
4322a8cae1 test: Add null vector checkers to chaos test pipeline (#47979)
## Summary

Wire three null-vector checkers into the chaos test concurrent operation
pipeline (`test_concurrent_operation.py`):

- **NullVectorSearchChecker** — detects NaN distances from null vector
leaks in search index
- **NullVectorQueryChecker** — validates null/non-null ratio consistency
in queries
- **AddVectorFieldChecker** — dynamically adds nullable FLOAT_VECTOR
fields, creates index, inserts data, and verifies

These checkers are already implemented in `checker.py` but were not
registered in `init_health_checkers()`. The default collection schema
already has nullable vector fields (`float_vector` and `image_emb` both
`nullable=True`), so the checkers use the shared collection name.

issue: #47867

### Changes

**Modified:**
- `tests/python_client/chaos/testcases/test_concurrent_operation.py`:
Added imports and registered 3 checkers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 20:15:20 +08:00
8cffd8e892 enhance: use effective version in banner and metrics BuildInfo label (#47953)
## Summary
- Use `getEffectiveVersion()` instead of hardcoded `common.Version` for
startup banner and `milvus_build_info` Prometheus metric
- Dev builds now correctly display `master-20260228-add6e4c6d4` instead
of always showing `2.6.6`
- Release builds are unaffected (git tag matches semver, so
`getEffectiveVersion()` returns the same value)

## Motivation

The startup banner (`Version:` line) and
`milvus_build_info{version="..."}` metric currently always show the
hardcoded semver from `common.Version` (e.g. `2.6.6`), regardless of
whether the binary is a release build or a dev build. This makes it
impossible to identify the actual build version from logs or monitoring
dashboards.

`getEffectiveVersion()` already exists and is used by the `GetVersion`
RPC and `Connect` RPC (via `MILVUS_GIT_BUILD_TAGS` env var, introduced
in PR #47822). This PR makes the banner and metrics consistent with
those APIs.

### What changes

| Component | Before | After (release) | After (dev) |
|-----------|--------|-----------------|-------------|
| Banner `Version:` | `2.6.6` | `2.6.6` | `master-20260228-add6e4c6d4` |
| Metric `milvus_build_info{version=}` | `2.6.6` | `2.6.6` |
`master-20260228-add6e4c6d4` |
| Session etcd version | `2.6.6` | `2.6.6` (unchanged) | `2.6.6`
(unchanged) |
| `GetVersion` RPC | `master-20260228-...` | `2.6.6` (unchanged) |
`master-20260228-...` (unchanged) |

### What is NOT affected

- `common.Version` itself (still hardcoded semver, used for session
compatibility)
- Session registration in etcd (still uses `common.Version` for cluster
version negotiation)
- Coordinator version range checks (still uses `common.Version`)

## Test plan
- [x] `go vet ./cmd/milvus/...` passes
- [x] Verified `getEffectiveVersion()` fallback: when `MilvusVersion` is
empty or "unknown", returns `common.Version.String()`
- [x] Verified no Grafana dashboard on internal 4am Grafana queries
`milvus_build_info` — zero PromQL impact

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:21:18 +08:00
yanliang567andGitHub 0748e46bed test: Add scipy.sparse insert tests and hybrid search coverage for add_field (#47885)
## Summary

- Add E2E test coverage for **scipy.sparse** sparse vector input (insert
+ search)
- Add **hybrid search** step to existing add_vector_field test for issue
#47873 coverage

**Related issue**: #47884

### Changes

**test_milvus_client_insert.py** (+118 lines):
- `test_milvus_client_insert_sparse_vector_scipy` [L1]: direct CSR
format (`csr_matrix`, `csr_array`) insert + search
- `test_milvus_client_insert_sparse_vector_scipy_to_csr` [L2]: non-CSR
formats (`csc_matrix`, `coo_matrix`, `dok_matrix`, `lil_matrix`,
`coo_array`) converted via `.tocsr()` then insert + search

**test_add_field_feature.py** (+19 lines):
- Added hybrid search step (original + new nullable vector fields) to
existing `test_milvus_client_add_vector_field`
- Regression coverage for issue #47873 (HybridSearch on newly added
nullable vector fields after release+load)

### Test Plan

- [x] All 7 scipy.sparse format tests passed on standalone
(10.104.17.152), ~5s each
- [x] Hybrid search test passed on standalone (10.104.17.152) and
distributed (10.104.21.212)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-02-28 10:57:23 +08:00
yanliang567andGitHub c047c20eaf test: Add null vector coverage to chaos tests (#47868)
## Summary

Add nullable vector field validation to the chaos test framework via
three independent checkers, following the existing
one-operation-per-checker pattern.

**Related issue**: #47867

### Changes (v2, addressing review feedback)

**Removed** (per review):
- Reverted all modifications to existing `SearchChecker`,
`QueryChecker`, `AddFieldChecker`
- Removed `TestNullVectorDataPersistence` from
`test_data_persistence.py` — persistence verification is covered by
checkers

**New independent checkers (`chaos/checker.py`)**:

| Checker | Op Enum | Responsibility | Frequency |
|---|---|---|---|
| `NullVectorSearchChecker` | `null_vector_search` | Search on nullable
vector fields, NaN distance detection with accumulation threshold (3
consecutive) | `WAIT_PER_OP / 10` |
| `NullVectorQueryChecker` | `null_vector_query` | Query nullable vector
fields, validate null/non-null ratio, fail on all-null (data corruption)
| `WAIT_PER_OP / 10` |
| `AddVectorFieldChecker` | `add_vector_field` | Add nullable
FLOAT_VECTOR + HNSW index + insert + query verification, with vector
field limit guard | `WAIT_PER_OP * 6` |

**Review feedback addressed**:
- Each checker has independent stats and frequency (no sampling bias)
- NaN detection uses accumulation threshold (`NAN_THRESHOLD=3`) to avoid
false positives from transient errors or zero-norm vectors
- `AddVectorFieldChecker` checks vector field limit dynamically via
`describe_collection` (no hardcoded `MAX_FIELD_NUM`)
- Query results are properly validated (no `result = True` hardcode)

**pytest.ini**: disable locust plugin (`-p no:locust`) to fix `--host`
option conflict

### Test Plan

- [x] `checker.py` syntax verified
- [x] New checkers follow existing patterns (TensorSearchChecker,
JsonQueryChecker, GeoQueryChecker)
- [x] No modifications to existing checkers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-02-28 10:33:23 +08:00
dc36bad36d fix: use per-command safe.directory for git in Makefile (#47916)
## Summary
- Fix `GetVersion` returning `unknown-YYYYMMDD-` instead of
`master-YYYYMMDD-<commit>` when building inside containers (e.g. via
`builder.sh`)
- Replace `git config --global --add safe.directory '*'` with a
per-command `-c safe.directory='*'` approach that doesn't pollute
`~/.gitconfig`
- Remove stale `safe.directory` setup from `print-build-info` and
`print-gpu-build-info` targets

## Root Cause
PR #47822 introduced `MILVUS_VERSION` using `:=` (immediate evaluation).
The `safe.directory` config was set in `print-build-info` target (line
253), but `MILVUS_VERSION` on line 250 is evaluated first during
Makefile parsing. So all git commands (`GIT_BRANCH`, `GIT_COMMIT`) fail
silently inside the builder container where `.git` is owned by a
different user.

## Fix
Define `GIT := git -c safe.directory='*'` and use `$(GIT)` for all git
shell calls. This:
1. Ensures `safe.directory` is effective for every git command at parse
time
2. Never modifies `~/.gitconfig` (no `--global --add` accumulation)
3. Scopes the security bypass to this Makefile only, not all repos on
the machine

issue: #47822

## Test plan
- [ ] Build milvus inside builder container via `builder.sh`, verify
`GetVersion` returns `master-YYYYMMDD-<commit>`
- [ ] Verify `~/.gitconfig` is not modified after `make build-go`
- [ ] Run `make print-build-info` and confirm correct output

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:09:20 +08:00
d81ede1818 enhance: make GetVersion return docker-image-tag style version string (#47822)
## Summary

- Make `GetVersion` API return version strings consistent with Docker
image tags, replacing the hardcoded semver
- Assemble `MilvusVersion` in Makefile via `git describe --exact-match
--tags` (release) or `branch-date-commit` (dev), inject via ldflags
- Both `detail=False` (`GetVersion` RPC) and `detail=True` (`Connect`
RPC `server_info.build_tags`) return the new format

| Scenario | Before | After |
|----------|--------|-------|
| Release (tag v2.6.11) | `2.6.11` | `2.6.11` |
| Dev (master branch) | `2.6.11` | `master-20260224-2d14975d18` |
| Feature branch | `2.6.11` | `feature-xxx-20260224-2d14975d18` |

Banner still displays semver via `common.Version.String()` — unchanged.

issue: #47823

## Test plan

- [x] Makefile dry-run verified: `MilvusVersion` correctly injected in
all 4 ldflags targets
- [x] Tag scenario verified: `v2.6.11` → `2.6.11` (v prefix stripped)
- [x] Dev scenario verified:
`feature/getversion-docker-tag-format-20260224-2d14975d18`
- [x] Go syntax verified: `gofmt` and `go vet` pass
- [ ] Full `make build-go` (requires C++ env)
- [ ] E2E: `client.get_server_version()` and
`client.get_server_version(detail=True)`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:20:47 +08:00
yanliang567andGitHub 7d22e53c99 test: Add GROUP BY on nullable field tests to verify fix for issue #47350 (#47856)
## Summary

Add 4 test cases to `TestQueryAggregationSharedV2` covering GROUP BY on
nullable fields, verifying the fix for #47350 (PR #47445).

**Related issue**: #47350

### Changes

**Schema additions** to the shared collection:
- `c10_nullable_varchar`: VARCHAR (nullable, 7 unique values + ~15%
NULL)
- `c11_nullable_int16`: INT16 (nullable, 5 unique values + ~15% NULL)

**New tests:**

| Test | What it verifies |
|------|-----------------|
| `test_group_by_nullable_varchar_field` | GROUP BY nullable VARCHAR
returns actual values (not all NULL) + aggregation correctness |
| `test_group_by_nullable_int16_field` | GROUP BY nullable INT16 returns
actual values + aggregation correctness |
| `test_multi_column_group_by_with_nullable_field` | Multi-column GROUP
BY with one nullable column |
| `test_search_group_by_nullable_field` | Search with GROUP BY on
nullable field returns actual group values |

### Test Plan

- [x] All 4 new tests passed against Milvus 2.6.6
- [x] All 28 existing tests still pass (0 regressions)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-02-25 19:12:46 +08:00
yanliang567andGitHub 4bbc01324b fix: handle NaN vs None comparison in output field value check for nullable fields (#47841)
## Summary

- Fix `output_field_value_check` in `param_check.py` to handle NaN vs
None comparison for nullable fields
- When nullable fields contain `None` values, `pandas.DataFrame`
converts them to `NaN`. The check function then fails comparing `NaN`
(from DataFrame) with `None` (from Milvus search results). This fix
treats both as equivalent null values.
- Remove resolved issue reference comments (`#47065`)

**Related issue**: #47065

### Changes

**Modified Files:**
- `tests/python_client/check/param_check.py`: Add NaN/None equivalence
check before asserting output field values
- `tests/python_client/milvus_client/test_add_field_feature.py`: Remove
resolved `#47065` comment
- `tests/python_client/milvus_client/test_milvus_client_collection.py`:
Remove resolved `#47065` comment

### Test Plan

- [x]
`test_search_by_pk_with_output_fields_and_consistency_level[Strong/Session/Bounded/Eventually]`
- 4 previously failing tests now PASS
- [x] All 98 search_by_pk tests: 93 passed + 4 fixed + 1 skipped
- [x] 13 null/nullable vector related tests all PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-02-25 16:14:46 +08:00
yanliang567andGitHub 3a11ebcc88 test: Add comprehensive test coverage for nullable vector field functionality (#47847)
## Summary

Add 6 new test cases to `test_milvus_client_collection.py` covering gaps
in nullable vector field test coverage, identified after verifying fixes
for #47065 and #47197.

**Related issue**: #47846

### New Test Cases

| Test | Level | Coverage |
|------|-------|----------|
| `test_milvus_client_search_all_null_vectors` | L1 | Search on 100%
null vectors (sealed + growing) |
| `test_milvus_client_search_iterator_null_vector` | L1 | Search
iterator with all-null and mixed data |
| `test_milvus_client_query_iterator_null_vector` | L1 | Query iterator
returns all rows including null vectors |
| `test_milvus_client_upsert_null_vector_transitions` | L1 |
Non-null↔null transitions via upsert |
| `test_milvus_client_multi_vector_output_null` | L1 | Multi-vector
output with nullable field |
| `test_milvus_client_compact_with_null_vector` | L2 | Data integrity
after compaction with null vectors |

### Test Plan

- [x] All 6 tests passed against Milvus 2.6.6 (10.104.17.170)
- [x] No regressions in existing null vector tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <82361606+yanliang567@users.noreply.github.com>
2026-02-25 15:46:46 +08:00
3659ac483c feat: [Go SDK] Support search by primary key IDs (#47633)
issue: https://github.com/milvus-io/milvus/issues/46879
design doc:
https://github.com/milvus-io/milvus-design-docs/blob/main/design_docs/20230403-search_by_pk.md

## Summary
- Add `NewSearchByIDsOption` constructor for searching by primary key
IDs, bringing Go SDK feature parity with Python SDK (PR #46993)
- Add `AnnRequest.WithIDs()` method and `column2IDs` helper for ID-based
search
- Add comprehensive E2E tests covering float/binary/sparse vectors,
nullable fields, duplicate IDs, invalid IDs, range search, hybrid
search, and search iterator compatibility

## API Design
```go
// Vector search (existing)
opt := client.NewSearchOption(collName, 10, vectors)

// Search by IDs (new)
idColumn := column.NewColumnInt64("id", []int64{1, 2, 3})
opt := client.NewSearchByIDsOption(collName, 10, idColumn)
```

## Test plan
- [x] Unit tests for `NewSearchByIDsOption`, `column2IDs`,
`AnnRequest.WithIDs`
- [x] E2E: float vector search by PK with self-match verification (FLAT
index + COSINE)
- [x] E2E: binary vector search by PK (VarChar PK)
- [x] E2E: sparse vector search by PK (non-nullable)
- [x] E2E: nullable sparse vector field with mixed null/non-null IDs
- [x] E2E: empty IDs error handling
- [x] E2E: duplicate IDs error handling
- [x] E2E: non-existent IDs error handling
- [x] E2E: search by IDs with filter expression
- [x] E2E: search by IDs with group by
- [x] E2E: search by IDs with output fields
- [x] E2E: search by IDs with range search parameters
- [x] E2E: hybrid search does not support search by IDs (negative test)
- [x] E2E: search iterator does not support search by IDs (documented)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <yanliang.qly@gmail.com>
Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 10:52:54 +08:00
d4b1957f03 enhance: [skip e2e]add agentic bug report issue template (#47615)
## Summary
Add a new issue template (`agentic_bug_report.md`) optimized for AI
Agent to analyze, reproduce, and fix Milvus bugs autonomously.

### Why
The existing `bug_report.yaml` is designed for human users with
free-text fields. For an AI agent workflow (auto-analyze → locate code →
write fix → submit PR), we need more structured, machine-actionable
information.

### Template Structure
| Section | Purpose |
|---------|---------|
| **Environment** | Version (image tag / commit), deployment mode, SDK —
for agent to checkout matching code and set up environment |
| **Reproduction Script** | Self-contained, runnable Python/Go script
ending with assertion — agent can execute directly |
| **Reproduction Steps** | Alternative for systemic/stability/timing
issues that can't be scripted |
| **Trigger Conditions** | Frequency, timing, boundary conditions —
helps agent narrow down code paths |
| **Expected / Actual Behavior** | Structured comparison — defines
"fixed" criteria for agent verification |
| **Error Logs** | Key stack traces with file:line — agent can jump
directly to suspect code |
| **Non-default Configuration** | Config diff only — agent knows
defaults, only needs deltas |
| **Analysis Hints** | Optional clues: suspect code location, related
PRs, ruled-out directions |

### Design Principles
- Every field directly serves a step in the agent's workflow: understand
→ reproduce → locate → fix → verify
- Reproduction script is preferred (functional bugs) but structured
steps are accepted (stability/timing bugs)
- Minimal required fields to reduce filing friction while maximizing
agent effectiveness

🤖 Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 01:45:50 +08:00
88cd109afc test: add e2e tests for three-valued logic with nullable fields (#47582)
## Summary
Add comprehensive e2e test cases for PR #47333 which fixed three-valued
logic issues in expression evaluation with NULL values.

### Test Coverage (19 cases)

**TestMilvusClientThreeValuedLogic (17 tests)**
- **Basic IS NULL / IS NOT NULL** (2 tests)
- **NOT operator equivalences** - `NOT (IS NOT NULL) == IS NULL` (2
tests)
- **Multiple NOT operations** - double/triple NOT (2 tests)
- **Multi-field NULL combinations** - AND/OR with two nullable fields (2
tests)
- **De Morgan's law** - `NOT (A AND B)`, `NOT (A OR B)` (2 tests)
- **NULL with value comparisons** - combined NULL check and value filter
(3 tests)
- **Mixed filters** - id filter + NULL check (2 tests)
- **Search API** - search with NULL filter expressions (2 tests)

**TestMilvusClientThreeValuedLogicIssue46972 (2 tests)**
- Complex JSON expressions that triggered "False OR False = True" bug
- Uses exact reproduction case from issue #46972

### Test Design
- Uses shared collection pattern for efficiency
- Expected values calculated dynamically from stored data (not
hardcoded)
- Easy to extend with new test cases

### Verification
| Server | Result |
|--------|--------|
| With fix (master) | **19 passed** |
| Without fix (pre-PR#47333) | Multiple failures reproducing the bug |

issue: #46820, #46972

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 10:55:51 +08:00
7b78c09e98 enhance: distinguish xfail and xpass in test report plugin (#47588)
## Summary

This PR enhances the Python test log filter plugin to properly
distinguish between xfail and xpass test outcomes, which were previously
not categorized separately.

- **xfail**: Tests marked with `@pytest.mark.xfail` that failed as
expected
- **xpass**: Tests marked with `@pytest.mark.xfail` that passed
unexpectedly (needs attention)

Related to #47253

## Changes

- Detect xfail/xpass using pytest's `wasxfail` attribute
- Add `xfail` and `xpass` categories to `test_stats` tracking
- Update JSON report with xfail/xpass in summary and tests sections
- Update HTML report with:
  - New summary cards for xfail (purple) and xpass (pink)
- XPass section with full logs (since unexpected passes need
investigation)
  - XFail section with reason only (expected behavior, just tracking)
- Support parallel test runs with worker data merging for xfail/xpass

## Test plan

- [x] Python syntax validation passes
- [ ] Run tests with xfail markers to verify correct categorization
- [ ] Verify JSON report contains xfail/xpass sections
- [ ] Verify HTML report displays xfail/xpass with correct styling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 20:17:51 +08:00
9ef7e25778 test: enable search by ids on null vectors tests for #47065 (#47559)
## Summary
- Enable search by ids tests that were commented out pending fix of
#47065
- Fix syntax error in test: `for i in len()` → `for i in range(len())`
- Update test expectations to match the fixed behavior:
  - Search on null vectors now returns empty results instead of error
- Fix assertion to use correct `num_entities_with_not_null_vector` count

## Test plan
- [x] `test_milvus_client_add_nullable_vector_field_search` - verified
passing
- [x] `test_milvus_client_collection_null_vector_field_search` -
verified passing

issue: #47065

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Signed-off-by: Yan Liang <yanliang@zilliz.com>
Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 14:17:49 +08:00
0ce6d11d9c fix: prevent crash in GROUP BY aggregation with empty result set (#47319)
# Fix: Prevent crash in GROUP BY aggregation with empty result set

**Related issue**: #47316

## Problem

When executing a GROUP BY aggregation query where the filter matches
zero rows, Milvus crashes with **SIGSEGV (exit code 139)**.

**Example query that triggers the crash:**
```python
client.query(
    collection_name="test_collection",
    filter="c2 > 10000",  # Matches 0 rows
    group_by_fields=["c1"],
    output_fields=["c1", "count(c2)"]
)
```

**Crash location:**
`internal/core/src/exec/operator/query-agg/GroupingSet.cpp:131`

## Root Cause

The bug is in `GroupingSet::getOutput()`:

```cpp
bool GroupingSet::getOutput(milvus::RowVectorPtr& result) {
    if (isGlobal_) {
        return getGlobalAggregationOutput(result);
    }
    AssertInfo(hash_table_ != nullptr, ...);
    const auto& all_rows = hash_table_->rows()->allRows();  // ← Crashes: nullptr dereference
    // ...
}
```

**Why it crashes:**
1. `hash_table_` is only initialized in `addInputForActiveRows()` when
data arrives
2. When filter matches 0 rows, no data flows to AggregationNode
3. `addInputForActiveRows()` is never called
4. `hash_table_` remains `nullptr`
5. `getOutput()` directly accesses `hash_table_->rows()` → **SIGSEGV**

**Inconsistency:** Global aggregation (no GROUP BY) has lazy
initialization via `initializeGlobalAggregation()`, but non-global
aggregation (with GROUP BY) lacks this fallback mechanism.

## Solution

Add lazy initialization in `getOutput()` to ensure `hash_table_` is
always initialized before access, even when there's no input data:

```cpp
bool GroupingSet::getOutput(milvus::RowVectorPtr& result) {
    if (isGlobal_) {
        return getGlobalAggregationOutput(result);
    }
    // Ensure hash_table_ is initialized even when there's no input data
    // This handles the case where filter matches zero rows
    if (!hash_table_) {
        createHashTable();
    }
    AssertInfo(hash_table_ != nullptr,
               "hash_table_ should not be nullptr after initialization");
    const auto& all_rows = hash_table_->rows()->allRows();  // Now safe
    if (!all_rows.empty()) {
        extractGroups(result);
        return true;
    }
    return false;  // Empty result
}
```

This approach:
-  Matches the lazy initialization pattern used by global aggregation
-  Minimal code change (4 lines added)
-  No performance impact on normal queries
-  Handles the empty result edge case safely

## Testing

### Verification
-  Successfully reproduced the crash with query filter that matches 0
rows
-  Applied fix and verified crash is resolved
-  Tested with various empty result scenarios (single/multiple
aggregations, single/multi-column GROUP BY)
-  All existing aggregation tests continue to pass

**Note:** Comprehensive E2E test cases for this fix will be submitted in
a separate PR after this fix is merged and validated in the testing
environment.

## Impact

**Severity:** Critical (P0) - Process crash
**Affected:** All GROUP BY + aggregation queries that return empty
results
**Risk:** Low - Minimal code change, follows existing pattern

## Checklist

- [x] I have read the [Contributing
Guidelines](https://github.com/milvus-io/milvus/blob/master/CONTRIBUTING.md)
- [x] I have signed my commits (`git commit -s`)
- [x] The commit message follows the [conventional
commits](https://www.conventionalcommits.org/) format
- [x] The code follows the [coding style
guidelines](https://github.com/milvus-io/milvus/blob/master/CONTRIBUTING.md#coding-style)
- [x] Fix has been manually verified in test environment
- [ ] E2E test cases will be added in a follow-up PR
- [ ] CI checks pass (will be verified by PR checks)

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 07:27:32 +08:00
yanliang567andGitHub d81e6d3996 test: Optimize query aggregation tests and add count(*) validation (#47355)
## Summary

Optimized query aggregation test structure by consolidating negative
tests into shared collection, adding count(*) validation, and
eliminating test redundancy.

**Related issue**: #47353

## Key Improvements

### 1. Test Structure Optimization
- **Moved 7 negative tests** to TestQueryAggregationSharedV2 (uses
shared collection)
  - test_group_by_field_not_in_output_fields
  - test_unsupported_vector_field
  - test_unsupported_aggregation_function_varchar
  - test_mixed_aggregation_and_non_aggregation_fields
  - test_invalid_aggregation_function_syntax
  - test_unsupported_float_type_for_groupby
  - test_unsupported_double_type_for_groupby
- **Deleted redundant test** (test_nullable_field_aggregation - covered
by shared collection)
- **Deleted entire class** TestQueryAggregationNegativeV2

### 2. count(*) Functionality Validation
Added 3 new L1 tests to validate compatibility between original count(*)
feature and new aggregation:
- `test_count_star_without_group_by` - Validates original count(*)
global counting feature
- `test_count_star_vs_count_field` - Validates difference on nullable
fields
  - count(*) = 3000 (includes NULL rows)
  - count(c2) = 2568 (excludes NULL values)
- `test_count_star_with_group_by_error` - Validates proper error when
count(*) used with GROUP BY

### 3. Test Deduplication
- **Deleted** `test_filter_and_limit_with_aggregation` (L2/xfail,
redundant)
- **Enhanced** `test_group_by_with_limit` to cover both scenarios:
  - Scenario 1: limit without filter
- Scenario 2: limit with filter (validates aggregation from filtered
data)
- Eliminated redundant independent collection creation

### 4. Performance Benefits
- **~10-15 seconds faster** per test run (eliminated 8 collection
create/drop cycles)
- **~420 lines removed** (duplicate code: ~350 + ~73)
- **Simplified structure** from 3 test classes to 2

## Changes

**Modified Files:**
- `tests/python_client/testcases/test_query_aggregation.py`
  - TestQueryAggregationSharedV2: 26 tests (+9: 17 → 26)
- TestQueryAggregationIndependentV2: 2 tests (-1: only JSON/Array
remain)
  - Total: 28 tests (29 → 28, -1 due to deduplication)

## Test Plan

- [x] All L0 tests passing: 3 passed in 6.78s
- [x] All L1 tests passing: 20 passed, 2 skipped, 1 xfailed
- [x] New count(*) tests validate:
  - count(*) returns total entity count (3000)
- count(*) vs count(field) difference on nullable fields (3000 vs 2568)
  - count(*) + GROUP BY properly returns error
- [x] Enhanced test_group_by_with_limit covers both limit scenarios
- [x] All moved negative tests still validate error messages correctly
- [x] Shared collection tests remain isolated via xdist_group marker

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-01-28 13:25:32 +08:00
yanliang567andGitHub bdb56f6053 enhance: Optimize Python test logging from 60MB to 3-5MB per run (#47253)
## Summary

This PR optimizes Python test logging to reduce log file size from 60MB+
to 3-5MB per test run (90%+ reduction) while preserving full debugging
information for failed tests.

related issue:  #47256

### Key Improvements

- **Conditional Logging**: PASSED tests save only metadata, FAILED tests
preserve complete logs
- **Memory Buffering**: Eliminates runtime disk I/O (no file writes
during test execution)
- **Unified Reports**: Generates 2 formats
  - `test_report.json`: AI-friendly structured data
  - `test_report.html`: Human-readable with color-coded logs
- **Worker Parallelism**: Full support for `pytest -n` with data merging

### Performance Impact

| Metric | Before | After | Improvement |
|--------|--------|-------|-------------|
| **Log Size** (15K tests) | 60 MB | 3-5 MB | **-90%+** |
| **Memory Usage** (6 workers) | ~50 MB | ~450 MB | +400 MB |
| **CPU Overhead** | N/A | 0.0004% | Negligible |
| **Runtime I/O** | 75 seconds | 75 ms | **-99.9%** |

### Changes

**New Files:**
- `plugin/log_filter.py`: Conditional log handler with per-test memory
buffers
- `plugin/__init__.py`: Plugin package initialization

**Modified Files:**
- `config/log_config.py`: Simplified config (only JSON/HTML paths)
- `conftest.py`: Register log filter plugin
- `utils/util_log.py`: Removed redundant file handlers
- `utils/api_request.py`: Optimized API request logging
- `check/param_check.py`: Truncate long lists in error messages
- `common/common_func.py`: Removed verbose logging
- `pytest.ini`: Added log filter plugin

**Cleanup:**
- `milvus_client/test_add_field_feature.py`: Removed unused variable

### Test Plan

- [x] Syntax validation: All Python files pass `py_compile`
- [x] Module imports: All modules load successfully
- [x] Data structures: Verified serialization without report/buffer
objects
- [x] Log configuration: Confirmed only necessary attributes present
- [x] Small-scale test (17 tests):  Generated correct JSON + HTML
reports
- [x] Performance analysis: Memory/CPU profiling for 15K test scenario

### Example Output

**test_report.html** (human-readable):
- Beautiful color-coded UI
- Failed tests with full error traceback
- Expandable log sections by level (debug/info/warning/error)

**test_report.json** (AI-friendly):
```json
{
  "metadata": { "total_tests": 15000, ... },
  "summary": { "passed": 13500, "failed": 1500, ... },
  "tests": {
    "failed": [
      {
        "id": "test.py::test_func",
        "error": { "type": "AssertionError", ... },
        "logs": { "debug": [...], "error": [...] }
      }
    ]
  }
}
```

### Memory Safety

For the standard scenario (15K tests, 10% failure, 6 workers):
- Worker memory: ~53 MB each (318 MB total)
- Main process peak: ~112 MB
- Total system: **< 450 MB**  Safe

High-risk scenarios (>30% failure or >50K tests) may require optional
streaming optimizations (documented in performance analysis).

### Backward Compatibility

-  No breaking changes to external APIs
-  Existing test commands work unchanged
-  Compatible with all pytest plugins

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-01-27 16:37:33 +08:00
b8938e4e82 test: add alter_collection_field description tests for PR #47057 (#47120)
## Summary
- Add E2E test cases for `alter_collection_field()` to change field
description
- Covers PR #47057 and Issue #46896
- 12 positive tests: basic functionality, pk/vector/scalar fields,
multiple alterations, empty description, special characters (unicode,
emoji, newlines, tabs)
- 4 negative tests: non-existent collection/field, empty
collection/field names

## Test plan
- [x] All 16 tests pass against Milvus server with PR #47057 merged
- [x] Verified correct `field_params` format: `{"field.description":
"..."}`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:05:30 +08:00
yanliang567andGitHub 6b2076e00d test: Fix issue when searching with empty sparse vector (#46940)
related issue: #46755

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-01-09 14:09:25 +08:00
yanliang567andGitHub 9996e8d1ce test: Update error msg for search by ids tests (#46792)
related issue: #46789

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-01-05 20:09:24 +08:00
yanliang567andGitHub 7018151c7d test: Add tests for search by ids (#46756)
related issue: #46755

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2026-01-05 13:25:23 +08:00
yanliang567andGitHub 15ce8aedd8 test: Add some tests for group by search support json and dynamic field (#46630)
related issue: #46616


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
- Core invariant: these tests assume the v2 group-by search
implementation (TestMilvusClientV2Base and pymilvus v2 APIs such as
AnnSearchRequest/WeightedRanker) is functionally correct; the PR extends
coverage to validate group-by semantics when using JSON fields and
dynamic fields (see
tests/python_client/milvus_client_v2/test_milvus_client_search_group_by.py
— TestGroupSearch.setup_class and parametrized group_by_field cases).
- Logic removed/simplified: legacy v1 test scaffolding and duplicated
parametrized fixtures/test permutations were consolidated into
v2-focused suites (TestGroupSearch now inherits TestMilvusClientV2Base;
old TestGroupSearch/TestcaseBase patterns and large blocks in
test_mix_scenes were removed) to avoid redundant fixture permutations
and duplicate assertions while reusing shared helpers in common_func
(e.g., gen_scalar_field, gen_row_data_by_schema) and common_type
constants.
- Why this does NOT introduce data loss or behavior regression: only
test code, test helpers, and test imports were changed — no
production/server code altered. Test helper changes are
backward-compatible (gen_scalar_field forces primary key nullable=False
and only affects test data generation paths in
tests/python_client/common/common_func.py; get_field_dtype_by_field_name
now accepts schema dicts/ORM schemas and is used only by tests to choose
vector generation) and collection creation/insertion in tests use the
same CollectionSchema/FieldSchema paths, so production
storage/serialization logic is untouched.
- New capability (test addition): adds v2 test coverage for group-by
search over JSON and dynamic fields plus related scenarios — pagination,
strict/non-strict group_size, min/max group constraints, multi-field
group-bys and binary vector cases — implemented in
tests/python_client/milvus_client_v2/test_milvus_client_search_group_by.py
to address issue #46616.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-12-31 11:03:21 +08:00
yanliang567andGitHub 13a52016ac test: Update hybrid search tests with milvus client (#46003)
related issue: https://github.com/milvus-io/milvus/issues/45326

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-12-02 18:11:10 +08:00
yanliang567andGitHub 1da75c0ee2 test: Update hybrid search tests to milvus client style (#45772)
related issue: #45326

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-11-24 17:55:07 +08:00
yanliang567andGitHub a2282d61cb test: Add more async tests (#45327)
related issue: #45326

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-11-06 15:43:33 +08:00
yanliang567andGitHub 9e5f9277c0 test: Split insert file and add test for allow insert auto id (#44801)
related issue: #44425
1. split insert.py into a few files: upsert.py, insert.py,
partial_upsert.py ...
2. add test for allow insert auto id

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-10-14 14:28:00 +08:00
yanliang567andGitHub c9f01a73cc test:Skip unstable test (#44649)
related issue: #44620

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-09-30 16:47:52 +08:00
yanliang567andGitHub 7438b00108 test:Fix a space issue for config update (#44630)
related issue: https://github.com/milvus-io/milvus/issues/44623

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-09-29 20:51:06 +08:00
yanliang567andGitHub 424075d26f test: Update querynode.segcore.exprEvalBatchSize to 512 to cover multiple batches in segcore (#44624)
related issue: #44623

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-09-29 18:01:05 +08:00
yanliang567andGitHub a7087b0023 test: Add more ngram tests, including mmap and utf8 characters (#44169)
related issue: #43989

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-09-02 14:17:52 +08:00
yanliang567andGitHub f301692900 test: Add ngram tests and expression tests (#44029)
related issue: https://github.com/milvus-io/milvus/issues/43989

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-08-26 14:51:51 +08:00
yanliang567andGitHub ec6681b018 test: add tests for ngram and fix invalid collection name mag (#43990)
related issue: #43989

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-08-21 18:45:47 +08:00
yanliang567andGitHub d45274512c test: Refactor search tests and remove useless common functions (#43608)
related issue: #40698

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-08-05 11:15:39 +08:00
yanliang567andGitHub 10ec3ce2bf test: Upgrade pymilvus to 2.6.0rc166 (#43543)
related issue: #40698

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-07-28 10:30:55 +08:00
yanliang567andGitHub abb3aeacdf test: Refactor diskann and hsnw index, and update gen data functions (#43452)
related issue #40698
1. add diskann and hnsw index test
2. update gen_row_data and gen_column_data functions

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-07-23 22:04:54 +08:00
yanliang567andGitHub 0017fa8acc test: Enable storage v2 in ci and nightly runs (#43086)
related issue: #43020

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-07-04 18:38:44 +08:00
yanliang567andGitHub e8011908ac test: Add tests for partition key filter issue and ttl eventually search (#43052)
related issue: #42918
1. add tests for ttl eventually search
2. add tests for partition key filter 
3. improve check query results for output fields 
4. verify some fix for rabitq index and update the test accordingly
5. update gen random float vector in (-1, 1) instead of (0,1)

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-07-02 11:02:43 +08:00
yanliang567andGitHub 7d41284cfe test: [skip e2e]Fix Int8_vector support list issues (#42722)
1. add assertion for those index not support int8_vector
2. remove dup testcase
3. skip e2e for L2 updates

related issue: #40698

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-06-13 15:52:35 +08:00
yanliang567andGitHub fb7f19dfa1 test: update ttl test comments and update for expressions tests (#42611)
related issue: #42604

1. update the test expression for all to L3 for now as it takes too many
hours to complete running. Will improve the performance in next pr.

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-06-11 16:52:38 +08:00
yanliang567andGitHub c40ea7403d test:Add TTL read test (#42189)
related issue: #42182

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-06-09 12:06:32 +08:00
yanliang567andGitHub f20e085b22 test: Update ivf_rabitq error msg and groupby support nullable field (#41997)
related issue: #41898

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-05-21 22:20:25 +08:00
yanliang567andGitHub d475d93a3d test: Add ivf_rabitq index tests (#41914)
related issue: #41760

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-05-20 19:28:24 +08:00
yanliang567andGitHub 83cdd6b121 test: set specific mq for standalone e2e (#41859)
related issue: https://github.com/milvus-io/milvus/issues/41819
1. remove useless distributed config
2. set specific mq for standalone e2e

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-05-16 10:30:23 +08:00
yanliang567andGitHub b59a2d669f test: Add resource limit for e2e and nightly tests (#41820)
related issue: #41819
1. set resource limit for ci and nightly e2e tests
2. combine nightly standalone and standalone+auth
3. enable mmap for distributed-pulsar

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-05-15 14:22:22 +08:00
yanliang567andGitHub ee659d50db test: [E2e Refactor] update search basic tests and add a pk_name instead of hard code (#41669)
related issue: https://github.com/milvus-io/milvus/issues/40698

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-05-09 21:58:54 +08:00
yanliang567andGitHub 70b311735b test: [E2e Refactor] use vector datatype instead of hard code dataype names (#41497)
related issue: #40698 
1. use vector datat types instead of hard code datatpe names
2. update search pagination tests
3. remove checking distances in search results checking, for knowhere
customize the distances for different metrics and indexes. Now only
assert the distances are sorted correct.

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-04-25 10:46:38 +08:00
yanliang567andGitHub 6a9ecb760f test: Update binary pagination search assertion for more stable (#41370)
related issue: #41362

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-04-17 14:16:32 +08:00
yanliang567andGitHub bbaa3c71f4 test: [E2e Refactor]gen collection name by testcase name and update search pagination test (#41170)
1.  gen collection name by testcase name
2. update search pagination test with milvus client v2
3. use collection shared mode for some tests
related issue: #40698

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-04-09 17:44:28 +08:00
yanliang567andGitHub cf223bae7b test: Split test_search and refactor on test class to share collections (#40677)
issue: #40698

---------

Signed-off-by: yanliang567 <yanliang.qiao@zilliz.com>
2025-03-19 14:20:15 +08:00