Files
wifi-densepose/vendor/ruvector/npm/tests/integration/cross-package.test.js

286 lines
9.3 KiB
JavaScript

/**
* Integration tests for cross-package compatibility
* Tests that all packages work together correctly
*/
const test = require('node:test');
const assert = require('node:assert');
// Test that main package correctly loads backends
test('Integration - Backend Loading', async (t) => {
const ruvector = require('ruvector');
await t.test('should load a working backend', () => {
const info = ruvector.getBackendInfo();
assert.ok(info, 'Should get backend info');
assert.ok(['native', 'wasm'].includes(info.type), 'Should have valid backend type');
});
await t.test('should create VectorIndex with loaded backend', () => {
const index = new ruvector.VectorIndex({ dimension: 128 });
assert.ok(index, 'Should create index with backend');
});
await t.test('backend type should match availability', () => {
const info = ruvector.getBackendInfo();
const hasNative = ruvector.isNativeAvailable();
if (hasNative) {
assert.strictEqual(info.type, 'native', 'Should use native when available');
} else {
assert.strictEqual(info.type, 'wasm', 'Should use WASM as fallback');
}
});
});
// Test API compatibility between backends
test('Integration - API Compatibility', async (t) => {
const ruvector = require('ruvector');
const dimension = 128;
await t.test('insert and search should work consistently', async () => {
const index = new ruvector.VectorIndex({ dimension, metric: 'cosine' });
// Insert test data
const vectors = Array.from({ length: 20 }, (_, i) => ({
id: `api-test-${i}`,
values: Array.from({ length: dimension }, () => Math.random())
}));
await index.insertBatch(vectors);
// Search
const query = Array.from({ length: dimension }, () => Math.random());
const results = await index.search(query, { k: 5 });
assert.ok(Array.isArray(results), 'Search should return array');
assert.ok(results.length > 0, 'Should find results');
assert.ok(results.length <= 5, 'Should respect k parameter');
// Verify result structure
results.forEach(result => {
assert.ok(result.id, 'Result should have ID');
assert.strictEqual(typeof result.score, 'number', 'Score should be number');
});
});
await t.test('delete and get should work consistently', async () => {
const index = new ruvector.VectorIndex({ dimension });
const testId = 'delete-get-test';
const vector = {
id: testId,
values: Array.from({ length: dimension }, () => Math.random())
};
await index.insert(vector);
// Get
const retrieved = await index.get(testId);
assert.ok(retrieved, 'Should get inserted vector');
assert.strictEqual(retrieved.id, testId, 'ID should match');
// Delete
const deleted = await index.delete(testId);
assert.strictEqual(deleted, true, 'Should delete successfully');
// Verify deletion
const afterDelete = await index.get(testId);
assert.strictEqual(afterDelete, null, 'Vector should be deleted');
});
await t.test('stats should work consistently', async () => {
const index = new ruvector.VectorIndex({ dimension });
await index.insert({
id: 'stats-test',
values: Array.from({ length: dimension }, () => Math.random())
});
const stats = await index.stats();
assert.ok(stats, 'Should return stats');
assert.ok(typeof stats.vectorCount === 'number', 'vectorCount should be number');
assert.strictEqual(stats.dimension, dimension, 'Dimension should match');
});
});
// Test data consistency across operations
test('Integration - Data Consistency', async (t) => {
const ruvector = require('ruvector');
const dimension = 256;
await t.test('inserted vectors should be searchable', async () => {
const index = new ruvector.VectorIndex({ dimension, metric: 'cosine' });
const testVector = {
id: 'consistency-test',
values: Array.from({ length: dimension }, () => Math.random())
};
await index.insert(testVector);
// Search with the exact same vector
const results = await index.search(testVector.values, { k: 1 });
assert.strictEqual(results.length, 1, 'Should find the vector');
assert.strictEqual(results[0].id, testVector.id, 'Should find the correct vector');
assert.ok(results[0].score < 0.01, 'Score should be very close to 0 (exact match)');
});
await t.test('batch insert should maintain order and IDs', async () => {
const index = new ruvector.VectorIndex({ dimension });
const vectors = Array.from({ length: 10 }, (_, i) => ({
id: `order-${i}`,
values: Array.from({ length: dimension }, () => Math.random())
}));
await index.insertBatch(vectors);
// Verify all vectors were inserted
for (const vector of vectors) {
const retrieved = await index.get(vector.id);
assert.ok(retrieved, `Vector ${vector.id} should be retrievable`);
assert.strictEqual(retrieved.id, vector.id, 'ID should match');
}
});
await t.test('search results should be deterministic', async () => {
const index = new ruvector.VectorIndex({ dimension, metric: 'cosine' });
// Insert fixed vectors
const vectors = Array.from({ length: 20 }, (_, i) => ({
id: `det-${i}`,
values: Array.from({ length: dimension }, (_, j) => (i + j) / 100)
}));
await index.insertBatch(vectors);
// Search with fixed query
const query = Array.from({ length: dimension }, (_, i) => i / 100);
const results1 = await index.search(query, { k: 5 });
const results2 = await index.search(query, { k: 5 });
assert.strictEqual(results1.length, results2.length, 'Should return same number of results');
for (let i = 0; i < results1.length; i++) {
assert.strictEqual(results1[i].id, results2[i].id, 'IDs should match');
assert.strictEqual(results1[i].score, results2[i].score, 'Scores should match');
}
});
});
// Test performance across backends
test('Integration - Performance Comparison', async (t) => {
const ruvector = require('ruvector');
const dimension = 128;
const numVectors = 100;
await t.test('insert performance should be reasonable', async () => {
const index = new ruvector.VectorIndex({ dimension });
const vectors = Array.from({ length: numVectors }, (_, i) => ({
id: `perf-${i}`,
values: Array.from({ length: dimension }, () => Math.random())
}));
const start = Date.now();
await index.insertBatch(vectors);
const duration = Date.now() - start;
const throughput = numVectors / (duration / 1000);
console.log(` Insert throughput: ${throughput.toFixed(0)} vectors/sec`);
assert.ok(throughput > 10, 'Should insert at least 10 vectors/sec');
});
await t.test('search performance should be reasonable', async () => {
const index = new ruvector.VectorIndex({ dimension });
// Insert test data
const vectors = Array.from({ length: numVectors }, (_, i) => ({
id: `search-perf-${i}`,
values: Array.from({ length: dimension }, () => Math.random())
}));
await index.insertBatch(vectors);
// Run searches
const numQueries = 50;
const queries = Array.from(
{ length: numQueries },
() => Array.from({ length: dimension }, () => Math.random())
);
const start = Date.now();
for (const query of queries) {
await index.search(query, { k: 10 });
}
const duration = Date.now() - start;
const throughput = numQueries / (duration / 1000);
console.log(` Search throughput: ${throughput.toFixed(0)} queries/sec`);
assert.ok(throughput > 5, 'Should search at least 5 queries/sec');
});
});
// Test error handling consistency
test('Integration - Error Handling', async (t) => {
const ruvector = require('ruvector');
await t.test('should handle invalid dimensions', () => {
assert.throws(
() => new ruvector.VectorIndex({ dimension: -1 }),
'Should reject negative dimensions'
);
});
await t.test('should handle dimension mismatch', async () => {
const index = new ruvector.VectorIndex({ dimension: 128 });
const wrongVector = {
id: 'wrong-dim',
values: Array.from({ length: 64 }, () => Math.random())
};
try {
await index.insert(wrongVector);
// Some backends might auto-handle this, others might throw
assert.ok(true);
} catch (error) {
assert.ok(error.message.includes('dimension'), 'Error should mention dimension');
}
});
await t.test('should handle empty search', async () => {
const index = new ruvector.VectorIndex({ dimension: 128 });
const query = Array.from({ length: 128 }, () => Math.random());
const results = await index.search(query, { k: 10 });
assert.ok(Array.isArray(results), 'Should return empty array');
assert.strictEqual(results.length, 0, 'Should have no results');
});
});
// Test TypeScript types compatibility
test('Integration - TypeScript Types', async (t) => {
await t.test('should have type definitions available', () => {
const fs = require('fs');
const path = require('path');
const ruvectorTypesPath = path.join(__dirname, '../../ruvector/dist/index.d.ts');
const coreTypesPath = path.join(__dirname, '../../core/dist/index.d.ts');
// At least one should exist
const hasRuvectorTypes = fs.existsSync(ruvectorTypesPath);
const hasCoreTypes = fs.existsSync(coreTypesPath);
assert.ok(
hasRuvectorTypes || hasCoreTypes,
'Should have TypeScript definitions'
);
});
});