Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/scripts/test_ci_workflow_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@


class WorkflowContractsTest(unittest.TestCase):
def test_ctest_invocations_reject_empty_selections(self):
workflow = (ROOT / ".github/workflows/test.yaml").read_text()
commands = re.findall(r"\bctest\s+[^\n]+", workflow)
self.assertTrue(commands)
for command in commands:
with self.subTest(command=command):
self.assertEqual(
re.findall(r"--no-tests(?:=|\s+)(\w+)", command), ["error"]
)

with tempfile.TemporaryDirectory() as directory:
result = subprocess.run(
["ctest", "--test-dir", directory, "--no-tests=error"],
capture_output=True,
text=True,
check=False,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("No tests were found", result.stdout + result.stderr)

def test_wheels_preserve_abi_coverage_and_release_gates(self):
workflow = (ROOT / ".github/workflows/release.yml").read_text()
config = tomllib.loads((ROOT / "pyproject.toml").read_text())
Expand Down
22 changes: 11 additions & 11 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,14 @@ jobs:
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="$PWD/rabitqlib-native-install"
cmake --build build-native-consumer
ctest --test-dir build-native-consumer --output-on-failure
ctest --test-dir build-native-consumer --output-on-failure --no-tests=error
- name: Test add_subdirectory isolation
run: |
cmake -S tests/consumer -B build-source-consumer -G Ninja \
-DCMAKE_BUILD_TYPE=Release -DRABITQ_SOURCE_DIR="$PWD" \
-DRABITQ_ENABLE_NATIVE_OPTIMIZATION=ON
cmake --build build-source-consumer
ctest --test-dir build-source-consumer --output-on-failure
ctest --test-dir build-source-consumer --output-on-failure --no-tests=error

clang:
name: Clang 23 (OpenMP ${{ matrix.openmp }})
Expand Down Expand Up @@ -256,14 +256,14 @@ jobs:
- name: Build
run: cmake --build build-windows --config Release --parallel 2
- name: Test
run: ctest --test-dir build-windows -C Release --output-on-failure
run: ctest --test-dir build-windows -C Release --output-on-failure --no-tests=error
- name: Test installed CMake package and header requirements
run: |
cmake --install build-windows --config Release --prefix "$PWD/rabitqlib-install"
cmake -S tests/consumer -B build-consumer -G "Visual Studio 18 2026" -A x64 `
"-DCMAKE_PREFIX_PATH=$PWD/rabitqlib-install"
cmake --build build-consumer --config Release --parallel 2
ctest --test-dir build-consumer -C Release --output-on-failure
ctest --test-dir build-consumer -C Release --output-on-failure --no-tests=error

sanitizers:
needs: changes
Expand Down Expand Up @@ -305,7 +305,7 @@ jobs:
-DCMAKE_PREFIX_PATH="$PWD/rabitqlib-sanitized-install" \
-DRABITQ_EXPECT_SANITIZERS=ON
cmake --build build-sanitized-consumer
ctest --test-dir build-sanitized-consumer --output-on-failure
ctest --test-dir build-sanitized-consumer --output-on-failure --no-tests=error

downstream-consumer:
needs: changes
Expand All @@ -330,7 +330,7 @@ jobs:
-DCMAKE_INSTALL_PREFIX="$PWD/rabitqlib-install"
cmake --build build-install
- name: Test portable Release build
run: ctest --test-dir build-install --output-on-failure
run: ctest --test-dir build-install --output-on-failure --no-tests=error
- name: Download pinned Intel SDE
run: |
curl --fail --location --retry 3 --max-time 120 \
Expand Down Expand Up @@ -365,7 +365,7 @@ jobs:
-DCMAKE_PREFIX_PATH="$PWD/rabitqlib-install"
cmake --build build-consumer
- name: Test downstream consumer
run: ctest --test-dir build-consumer --output-on-failure
run: ctest --test-dir build-consumer --output-on-failure --no-tests=error

core-consumer:
name: Core and FastScan consumers (${{ matrix.os }}, OpenMP ${{ matrix.openmp }}${{ matrix.component && format(', {0}', matrix.component) || '' }})
Expand Down Expand Up @@ -483,14 +483,14 @@ jobs:
- name: Build and run C++ tests
run: |
cmake --build build --parallel 2
ctest --test-dir build --output-on-failure
ctest --test-dir build --output-on-failure --no-tests=error
- name: Test installed CMake package
run: |
cmake --install build --prefix "$RUNNER_TEMP/rabitq-install"
cmake -S tests/consumer -B build-consumer -G Ninja \
-DCMAKE_PREFIX_PATH="$RUNNER_TEMP/rabitq-install"
cmake --build build-consumer --parallel 2
ctest --test-dir build-consumer --output-on-failure
ctest --test-dir build-consumer --output-on-failure --no-tests=error

macos-arm64:
name: Native Apple Silicon C++
Expand All @@ -515,12 +515,12 @@ jobs:
- name: Build and run C++ reference and index tests
run: |
cmake --build build --parallel 3
ctest --test-dir build --output-on-failure
ctest --test-dir build --output-on-failure --no-tests=error
- name: Test installed CMake package
run: |
cmake --install build --prefix "$RUNNER_TEMP/rabitq-install"
cmake -S tests/consumer -B build-consumer \
-DCMAKE_PREFIX_PATH="$RUNNER_TEMP/rabitq-install" \
-DOpenMP_ROOT="$(brew --prefix libomp)"
cmake --build build-consumer --parallel 3
ctest --test-dir build-consumer --output-on-failure
ctest --test-dir build-consumer --output-on-failure --no-tests=error
13 changes: 11 additions & 2 deletions tests/core_consumer/core_static_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,22 @@ namespace {
const bool kBeforeMain = [] {
namespace api = rabitqlib::quant::v1;
std::array<float, 64> input{}, rotated{}, query{};
double input_norm_sqr = 0;
for (size_t i = 0; i < input.size(); ++i) {
input[i] = static_cast<float>(i % 11) - 5.0F;
input_norm_sqr += static_cast<double>(input[i]) * input[i];
}
rabitqlib::rotator_impl::FhtKacRotator rotator(64, 64, 42);
rotator.rotate(input.data(), rotated.data());
query = rotated;
// A half-length collinear query gives known, nonzero results for both metrics.
for (size_t i = 0; i < query.size(); ++i) {
query[i] = rotated[i] * 0.5F;
}
for (const auto metric : {rabitqlib::METRIC_L2, rabitqlib::METRIC_IP}) {
const double expected = metric == rabitqlib::METRIC_L2 ? 0.25 * input_norm_sqr
: 1 - 0.5 * input_norm_sqr;
// Reference the original coordinates, allowing float rotation/scoring roundoff.
const double tolerance = 2e-5 * (1 + input_norm_sqr);
for (size_t bits = 1; bits <= 9; ++bits) {
const api::Parameters params{64, bits, metric};
const auto req = api::requirements(params, api::CodeLayout::SplitPacked);
Expand All @@ -46,7 +55,7 @@ const bool kBeforeMain = [] {
{extra.data(), extra.size()}},
factors
);
if (!std::isfinite(distance)) {
if (!std::isfinite(distance) || std::abs(distance - expected) > tolerance) {
return false;
}
}
Expand Down
29 changes: 28 additions & 1 deletion tests/dispatch/modules_static_init.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <array>
#include <cstddef>
#include <cstdint>

#include "rabitqlib/fastscan/fastscan.hpp"
Expand All @@ -10,18 +11,44 @@
namespace {
const bool kBeforeMain = [] {
std::array<float, 64> query{};
for (size_t i = 0; i < query.size(); ++i) {
query[i] = static_cast<float>(i % 4 + 1);
}
std::array<float, 256> lut{};
lut.fill(-1.0F);
rabitqlib::fastscan::pack_lut(64, query.data(), lut.data());
for (size_t i = 0; i < lut.size(); ++i) {
// The first coordinate occupies the high bit of each four-bit code.
float expected = 0;
for (size_t bit = 0; bit < 4; ++bit) {
if ((i % 16) & (size_t{1} << bit)) {
expected += static_cast<float>(4 - bit);
}
}
if (lut[i] != expected) {
return false;
}
}
std::array<uint16_t, 256> integer_lut{};
// Equal nonzero bytes make the packed result independent of the HACC layout.
integer_lut.fill(0x0101);
std::array<uint8_t, 512> packed_lut{};
packed_lut.fill(0xAB);
std::array<uint8_t, 256> codes{};
std::array<int32_t, 32> scores{};
scores.fill(-1);
rabitqlib::fastscan::transfer_lut_hacc(integer_lut.data(), 64, packed_lut.data());
for (const auto value : packed_lut) {
if (value != 1) {
return false;
}
}
rabitqlib::fastscan::accumulate_hacc(
codes.data(), packed_lut.data(), scores.data(), 64
);
for (const auto score : scores) {
if (score != 0) {
// Sixteen four-coordinate tables, each contributing 0x0101.
if (score != 16 * 0x0101) {
return false;
}
}
Expand Down
Loading