Files
faiss/tests/test_svs_metric.cpp
Justin Gibbs 8008ca2a70 Fix deadly signal in to_svs_metric() for unsupported metrics (#5032)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5032

Convert supported metric type assert to throw in `to_svs_metric()` to
better support tests that expect exceptions when processing invalid input.

There are two vectors that reach `to_svs_metric()` with an unsupported
metric:

1. **Deserialization** (`deserialize_impl()`):
   A invalid binary index with fourcc `"IBFf"`
   (IndexBinaryFromFloat) wrapping an SVS float index (`"ISVF"`,
   `"ILVQ"`, etc.) can carry any valid `MetricType` in the
   serialized stream. When the metric is not L2 or INNER_PRODUCT,
   `to_svs_metric()` is called with the unsupported value during
   `deserialize_impl()`.

2. **Programmatic construction** (`create_impl()`):
   Creating an SVS index (e.g., `IndexSVSFlat`) with an unsupported
   metric and calling `add()` triggers `create_impl()` which calls
   `to_svs_metric()`. This is a user-error path.

Reviewed By: mnorris11

Differential Revision: D99336458

fbshipit-source-id: ee5449b72e957a5e7eb77f651471f84c34e5c122
2026-04-03 15:08:59 -07:00

42 lines
1.5 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <faiss/impl/FaissException.h>
#include <faiss/svs/IndexSVSFaissUtils.h>
#include <faiss/svs/IndexSVSFlat.h>
#include <gtest/gtest.h>
#include <vector>
// Verify that to_svs_metric throws FaissException (not abort) for unsupported
// metric types.
// Direct call: exercises the deserialization path where metric_type is read
// from a serialized stream and passed to to_svs_metric().
TEST(SVSMetric, UnsupportedMetricThrowsDirect) {
EXPECT_THROW(faiss::to_svs_metric(faiss::METRIC_L1), faiss::FaissException);
EXPECT_THROW(
faiss::to_svs_metric(faiss::METRIC_Linf), faiss::FaissException);
EXPECT_THROW(
faiss::to_svs_metric(faiss::METRIC_Jaccard), faiss::FaissException);
}
// Supported metrics should not throw.
TEST(SVSMetric, SupportedMetricsSucceed) {
EXPECT_NO_THROW(faiss::to_svs_metric(faiss::METRIC_L2));
EXPECT_NO_THROW(faiss::to_svs_metric(faiss::METRIC_INNER_PRODUCT));
}
// Construction path: creating an IndexSVSFlat with an unsupported metric and
// calling add() triggers create_impl() -> to_svs_metric(). Verifies the throw
// propagates through the index construction API.
TEST(SVSMetric, IndexSVSFlatCreateImplUnsupportedMetricThrows) {
faiss::IndexSVSFlat idx(4, faiss::METRIC_L1);
std::vector<float> data = {1.0f, 2.0f, 3.0f, 4.0f};
EXPECT_THROW(idx.add(1, data.data()), faiss::FaissException);
}