Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
24 changes: 23 additions & 1 deletion tests/sqlx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ This test crate provides:

## Migration Status

Framework infrastructure complete. Test migration in progress.
✅ **Like-for-Like Migration: Complete** (40/40 SQL assertions ported)

- Equality operators: 16/16 (HMAC + Blake3, operators + functions + JSONB)
- JSONB functions: 24/24 (arrays, paths, structure validation, encrypted selectors)

## Architecture

Expand Down Expand Up @@ -167,6 +170,25 @@ async fn test_name(pool: PgPool) {
- **Better errors**: Rust panic messages show exact assertion failure
- **Test isolation**: Each test runs in fresh database (SQLx handles this automatically)

## Test Organization

### Current Test Modules

**`tests/jsonb_tests.rs`** - JSONB functions and operators
- Converted from `src/jsonb/functions_test.sql`
- Tests: `jsonb_array_elements`, `jsonb_array_elements_text`, `jsonb_array_length`, `jsonb_path_query`, `jsonb_path_exists`, encrypted selector validation

**`tests/equality_tests.rs`** - Equality operators and functions
- Converted from `src/operators/=_test.sql`
- Tests: HMAC index equality, Blake3 index equality, `eq()` function

### Test Count

- **Total**: 35 tests (34 functional + 1 helper)
- **JSONB**: 19 tests
- **Equality**: 15 tests
- **Helpers**: 1 test

## Dependencies

From `Cargo.toml`:
Expand Down
293 changes: 293 additions & 0 deletions tests/sqlx/tests/equality_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
//! Equality operator tests
//!
//! Converted from src/operators/=_test.sql
//! Tests EQL equality operators with encrypted data (HMAC and Blake3 indexes)

use eql_tests::QueryAssertion;
use sqlx::{PgPool, Row};

/// Helper to execute create_encrypted_json SQL function with specific indexes
/// Uses variadic form: create_encrypted_json(id, index1, index2, ...)
async fn create_encrypted_json_with_index(pool: &PgPool, id: i32, index_type: &str) -> String {
let sql = format!(
"SELECT create_encrypted_json({}, '{}')::text",
id, index_type
);

let row = sqlx::query(&sql).fetch_one(pool).await.unwrap_or_else(|e| {
panic!(
"Failed to create encrypted JSON with id={}, index_type='{}': {}",
id, index_type, e
)
});

let result: Option<String> = row.try_get(0).unwrap_or_else(|e| {
panic!(
"Failed to get result from create_encrypted_json(id={}, index_type='{}'): {}",
id, index_type, e
)
});

result.unwrap_or_else(|| {
panic!(
"create_encrypted_json returned NULL for id={}, index_type='{}'",
id, index_type
)
})
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_finds_matching_record_hmac(pool: PgPool) {
// Test: eql_v2_encrypted = eql_v2_encrypted with HMAC index
// Original SQL line 10-32 in src/operators/=_test.sql

let encrypted = create_encrypted_json_with_index(&pool, 1, "hm").await;

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted",
encrypted
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_returns_empty_for_no_match_hmac(pool: PgPool) {
// Test: equality returns no results for non-existent record
// Original SQL line 25-29 in src/operators/=_test.sql
// Note: Using id=4 instead of 91347 to ensure ore data exists (start=40 is within ore range 1-99)
// The important part is that id=4 doesn't exist in the fixture data (only 1, 2, 3)

let encrypted = create_encrypted_json_with_index(&pool, 4, "hm").await;

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted",
encrypted
);

QueryAssertion::new(&pool, &sql).count(0).await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_finds_matching_record_blake3(pool: PgPool) {
// Test: eql_v2_encrypted = eql_v2_encrypted with Blake3 index
// Original SQL line 105-127 in src/operators/=_test.sql

let encrypted = create_encrypted_json_with_index(&pool, 1, "b3").await;

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted",
encrypted
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_returns_empty_for_no_match_blake3(pool: PgPool) {
// Test: equality returns no results for non-existent record with Blake3
// Original SQL line 120-124 in src/operators/=_test.sql
// Note: Using id=4 instead of 91347 to ensure ore data exists
// The important part is that id=4 doesn't exist in the fixture data (only 1, 2, 3)

let encrypted = create_encrypted_json_with_index(&pool, 4, "b3").await;

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::eql_v2_encrypted",
encrypted
);

QueryAssertion::new(&pool, &sql).count(0).await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn eq_function_finds_matching_record_hmac(pool: PgPool) {
// Test: eql_v2.eq() function with HMAC index
// Original SQL line 38-59 in src/operators/=_test.sql
// Uses create_encrypted_json(id)::jsonb-'ob' to get encrypted data without ORE field

// Call SQL function to create encrypted JSON and remove 'ob' field
// Cast to eql_v2_encrypted first, then to text to get tuple format
let sql_create = "SELECT ((create_encrypted_json(1)::jsonb - 'ob')::eql_v2_encrypted)::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let encrypted: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE eql_v2.eq(e, '{}'::eql_v2_encrypted)",
encrypted
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn eq_function_finds_matching_record_blake3(pool: PgPool) {
// Test: eql_v2.eq() function with Blake3 index
// Original SQL line 135-156 in src/operators/=_test.sql

// Call SQL function to create encrypted JSON with Blake3 and remove 'ob' field
let sql_create = "SELECT ((create_encrypted_json(1, 'b3')::jsonb - 'ob')::eql_v2_encrypted)::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let encrypted: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE eql_v2.eq(e, '{}'::eql_v2_encrypted)",
encrypted
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn eq_function_returns_empty_for_no_match_blake3(pool: PgPool) {
// Test: eql_v2.eq() returns no results for non-existent record with Blake3
// Original SQL line 148-153 in src/operators/=_test.sql

let sql_create = "SELECT ((create_encrypted_json(4, 'b3')::jsonb - 'ob')::eql_v2_encrypted)::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let encrypted: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE eql_v2.eq(e, '{}'::eql_v2_encrypted)",
encrypted
);

QueryAssertion::new(&pool, &sql).count(0).await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_encrypted_equals_jsonb_hmac(pool: PgPool) {
// Test: eql_v2_encrypted = jsonb with HMAC index
// Original SQL line 65-94 in src/operators/=_test.sql

// Create encrypted JSON with HMAC, remove 'ob' field for comparison
let sql_create = "SELECT (create_encrypted_json(1)::jsonb - 'ob')::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::jsonb",
json_value
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_jsonb_equals_encrypted_hmac(pool: PgPool) {
// Test: jsonb = eql_v2_encrypted with HMAC index (reverse direction)
// Original SQL line 78-81 in src/operators/=_test.sql

let sql_create = "SELECT (create_encrypted_json(1)::jsonb - 'ob')::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE '{}'::jsonb = e",
json_value
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_encrypted_equals_jsonb_no_match_hmac(pool: PgPool) {
// Test: eql_v2_encrypted = jsonb with no matching record
// Original SQL line 83-87 in src/operators/=_test.sql

let sql_create = "SELECT (create_encrypted_json(4)::jsonb - 'ob')::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::jsonb",
json_value
);

QueryAssertion::new(&pool, &sql).count(0).await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_jsonb_equals_encrypted_no_match_hmac(pool: PgPool) {
// Test: jsonb = eql_v2_encrypted with no matching record
// Original SQL line 89-91 in src/operators/=_test.sql

let sql_create = "SELECT (create_encrypted_json(4)::jsonb - 'ob')::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE '{}'::jsonb = e",
json_value
);

QueryAssertion::new(&pool, &sql).count(0).await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_encrypted_equals_jsonb_blake3(pool: PgPool) {
// Test: eql_v2_encrypted = jsonb with Blake3 index
// Original SQL line 164-193 in src/operators/=_test.sql

let sql_create = "SELECT create_encrypted_json(1, 'b3')::jsonb::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::jsonb",
json_value
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_jsonb_equals_encrypted_blake3(pool: PgPool) {
// Test: jsonb = eql_v2_encrypted with Blake3 index (reverse direction)
// Original SQL line 177-180 in src/operators/=_test.sql

let sql_create = "SELECT create_encrypted_json(1, 'b3')::jsonb::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE '{}'::jsonb = e",
json_value
);

QueryAssertion::new(&pool, &sql).returns_rows().await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_encrypted_equals_jsonb_no_match_blake3(pool: PgPool) {
// Test: eql_v2_encrypted = jsonb with no matching record (Blake3)
// Original SQL line 184-187 in src/operators/=_test.sql

let sql_create = "SELECT create_encrypted_json(4, 'b3')::jsonb::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE e = '{}'::jsonb",
json_value
);

QueryAssertion::new(&pool, &sql).count(0).await;
}

#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
async fn equality_operator_jsonb_equals_encrypted_no_match_blake3(pool: PgPool) {
// Test: jsonb = eql_v2_encrypted with no matching record (Blake3)
// Original SQL line 188-191 in src/operators/=_test.sql

let sql_create = "SELECT create_encrypted_json(4, 'b3')::jsonb::text";
let row = sqlx::query(sql_create).fetch_one(&pool).await.unwrap();
let json_value: String = row.try_get(0).unwrap();

let sql = format!(
"SELECT e FROM encrypted WHERE '{}'::jsonb = e",
json_value
);

QueryAssertion::new(&pool, &sql).count(0).await;
}
Loading