feat: Add comprehensive test suite and cleanup step
- Split validation into 4 granular CI steps (Config, Timescale, Vector, Hybrid) - Added cleanup step for Docker images in CI - Created SQL test scripts in tests/ for robustness
This commit is contained in:
@@ -51,30 +51,23 @@ jobs:
|
|||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: 🧪 Test image - Verify extensions
|
- name: ⚙️ Setup Tests
|
||||||
run: |
|
run: |
|
||||||
# Wait a bit more for init scripts to complete
|
# Wait for valid startup
|
||||||
sleep 5
|
sleep 10
|
||||||
|
docker cp tests/ test-pg${{ matrix.pg_version }}:/tmp/tests/
|
||||||
# Check extensions are installed
|
|
||||||
RESULT=$(docker exec test-pg${{ matrix.pg_version }} psql -U postgres -t -c \
|
- name: 🧪 Test 1: Configuration
|
||||||
"SELECT count(*) FROM pg_extension WHERE extname IN ('timescaledb', 'vector', 'vchord');")
|
run: docker exec test-pg${{ matrix.pg_version }} psql -U postgres -f /tmp/tests/test-1-config.sql
|
||||||
|
|
||||||
EXTENSIONS=$(echo $RESULT | tr -d ' ')
|
- name: 🧪 Test 2: TimescaleDB
|
||||||
echo "Found $EXTENSIONS extensions"
|
run: docker exec test-pg${{ matrix.pg_version }} psql -U postgres -f /tmp/tests/test-2-timescale.sql
|
||||||
|
|
||||||
if [ "$EXTENSIONS" -eq "3" ]; then
|
- name: 🧪 Test 3: VectorChord
|
||||||
echo "✅ All 3 extensions are installed!"
|
run: docker exec test-pg${{ matrix.pg_version }} psql -U postgres -f /tmp/tests/test-3-vector.sql
|
||||||
else
|
|
||||||
echo "❌ Expected 3 extensions, found $EXTENSIONS"
|
- name: 🧪 Test 4: Hybrid Scenarios
|
||||||
docker exec test-pg${{ matrix.pg_version }} psql -U postgres -c \
|
run: docker exec test-pg${{ matrix.pg_version }} psql -U postgres -f /tmp/tests/test-4-hybrid.sql
|
||||||
"SELECT extname, extversion FROM pg_extension;"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Show extension versions
|
|
||||||
docker exec test-pg${{ matrix.pg_version }} psql -U postgres -c \
|
|
||||||
"SELECT extname, extversion FROM pg_extension WHERE extname IN ('timescaledb', 'vector', 'vchord');"
|
|
||||||
|
|
||||||
- name: 🧹 Cleanup test container
|
- name: 🧹 Cleanup test container
|
||||||
if: always()
|
if: always()
|
||||||
@@ -101,4 +94,10 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
gitea.killinger.fr/maxime.killinger/postgres-ts-vectors:latest
|
gitea.killinger.fr/maxime.killinger/postgres-ts-vectors:latest
|
||||||
|
|
||||||
|
- name: 🧹 Cleanup Docker images
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
docker rmi postgres-ts-vectors:pg${{ matrix.pg_version }}-test || true
|
||||||
|
docker image prune -f
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
17
tests/test-1-config.sql
Normal file
17
tests/test-1-config.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
-- Test 1: Configuration
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
|
||||||
|
SELECT version();
|
||||||
|
SELECT extname, extversion FROM pg_extension;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
preload_libs text;
|
||||||
|
BEGIN
|
||||||
|
SELECT setting INTO preload_libs FROM pg_settings WHERE name = 'shared_preload_libraries';
|
||||||
|
IF preload_libs NOT LIKE '%timescaledb%' OR preload_libs NOT LIKE '%vchord%' THEN
|
||||||
|
RAISE EXCEPTION 'Missing shared_preload_libraries config. Found: %', preload_libs;
|
||||||
|
END IF;
|
||||||
|
RAISE NOTICE 'Configuration Check: OK';
|
||||||
|
END
|
||||||
|
$$;
|
||||||
31
tests/test-2-timescale.sql
Normal file
31
tests/test-2-timescale.sql
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
-- Test 2: TimescaleDB
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS sensors CASCADE;
|
||||||
|
|
||||||
|
CREATE TABLE sensors (
|
||||||
|
time TIMESTAMPTZ NOT NULL,
|
||||||
|
sensor_id INTEGER,
|
||||||
|
temperature DOUBLE PRECISION
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Convert to hypertable
|
||||||
|
SELECT create_hypertable('sensors', 'time');
|
||||||
|
|
||||||
|
-- Insert data
|
||||||
|
INSERT INTO sensors (time, sensor_id, temperature) VALUES
|
||||||
|
(NOW(), 1, 20.0),
|
||||||
|
(NOW() + INTERVAL '1 hour', 1, 22.0);
|
||||||
|
|
||||||
|
-- Query data
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
count int;
|
||||||
|
BEGIN
|
||||||
|
SELECT count(*) INTO count FROM sensors;
|
||||||
|
IF count != 2 THEN
|
||||||
|
RAISE EXCEPTION 'Hypertable insert failed';
|
||||||
|
END IF;
|
||||||
|
RAISE NOTICE 'TimescaleDB Check: OK';
|
||||||
|
END
|
||||||
|
$$;
|
||||||
27
tests/test-3-vector.sql
Normal file
27
tests/test-3-vector.sql
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
-- Test 3: VectorChord / pgvector
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS items;
|
||||||
|
|
||||||
|
CREATE TABLE items (
|
||||||
|
id bigserial PRIMARY KEY,
|
||||||
|
embedding vector(3)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]'), ('[1.1, 2.1, 3.1]');
|
||||||
|
|
||||||
|
-- Create VectorChord Index
|
||||||
|
CREATE INDEX ON items USING vchordrq (embedding vector_l2_ops);
|
||||||
|
|
||||||
|
-- Search
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
closest_id int;
|
||||||
|
BEGIN
|
||||||
|
SELECT id INTO closest_id FROM items ORDER BY embedding <-> '[1,2,3]' LIMIT 1;
|
||||||
|
IF closest_id != 1 THEN
|
||||||
|
RAISE EXCEPTION 'Vector search failed. Expected ID 1, got %', closest_id;
|
||||||
|
END IF;
|
||||||
|
RAISE NOTICE 'Vector Check: OK';
|
||||||
|
END
|
||||||
|
$$;
|
||||||
40
tests/test-4-hybrid.sql
Normal file
40
tests/test-4-hybrid.sql
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
-- Test 4: Hybrid (Timescale + Vector)
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS hybrid_logs;
|
||||||
|
|
||||||
|
CREATE TABLE hybrid_logs (
|
||||||
|
time TIMESTAMPTZ NOT NULL,
|
||||||
|
msg TEXT,
|
||||||
|
vec vector(2)
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT create_hypertable('hybrid_logs', 'time');
|
||||||
|
|
||||||
|
INSERT INTO hybrid_logs (time, msg, vec) VALUES
|
||||||
|
(NOW(), 'log1', '[0,0]'),
|
||||||
|
(NOW() - INTERVAL '1 day', 'old_log', '[1,1]');
|
||||||
|
|
||||||
|
-- Index
|
||||||
|
CREATE INDEX ON hybrid_logs USING vchordrq (vec vector_l2_ops);
|
||||||
|
|
||||||
|
-- Hybrid Query
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
res_count int;
|
||||||
|
BEGIN
|
||||||
|
-- Recent logs similar to [0.1, 0.1]
|
||||||
|
SELECT count(*) INTO res_count
|
||||||
|
FROM (
|
||||||
|
SELECT * FROM hybrid_logs
|
||||||
|
WHERE time > NOW() - INTERVAL '1 hour'
|
||||||
|
ORDER BY vec <-> '[0.1, 0.1]'
|
||||||
|
LIMIT 1
|
||||||
|
) sub;
|
||||||
|
|
||||||
|
IF res_count != 1 THEN
|
||||||
|
RAISE EXCEPTION 'Hybrid query failed';
|
||||||
|
END IF;
|
||||||
|
RAISE NOTICE 'Hybrid Check: OK';
|
||||||
|
END
|
||||||
|
$$;
|
||||||
Reference in New Issue
Block a user