Skip to content

Commit fa9265b

Browse files
committed
test(sqlx): add encrypted column constraint validation tests
Add three Rust/SQLx test cases for eql_v2 encrypted column constraint functions: - add_encrypted_constraint_prevents_invalid_data: validates constraint blocks invalid JSONB - remove_encrypted_constraint_allows_invalid_data: validates constraint removal allows invalid data - version_metadata_validation_on_insert: validates v=2 version field enforcement These tests verify the constraint management functions work correctly to prevent insertion of malformed eql_v2_encrypted values.
1 parent 25be30c commit fa9265b

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

tests/sqlx/tests/constraint_tests.rs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,172 @@ async fn foreign_key_constraint_with_encrypted(pool: PgPool) -> Result<()> {
221221

222222
Ok(())
223223
}
224+
225+
// ========================================================================
226+
// EQL-Specific Constraint Tests (from src/encrypted/constraints_test.sql)
227+
// ========================================================================
228+
229+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
230+
async fn add_encrypted_constraint_prevents_invalid_data(pool: PgPool) -> Result<()> {
231+
// Test: eql_v2.add_encrypted_constraint() adds validation to encrypted column
232+
// Source: constraints_test.sql lines 3-21
233+
234+
// First, verify that insert without constraint works (even with invalid empty JSONB)
235+
sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)")
236+
.execute(&pool)
237+
.await?;
238+
239+
let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM encrypted")
240+
.fetch_one(&pool)
241+
.await?;
242+
243+
assert_eq!(
244+
count, 4,
245+
"Should have 4 records (3 from fixture + 1 invalid)"
246+
);
247+
248+
// Delete the invalid data and reset
249+
sqlx::query("DELETE FROM encrypted WHERE e = '{}'::jsonb::eql_v2_encrypted")
250+
.execute(&pool)
251+
.await?;
252+
253+
// Add the encrypted constraint
254+
sqlx::query("SELECT eql_v2.add_encrypted_constraint('encrypted', 'e')")
255+
.execute(&pool)
256+
.await?;
257+
258+
// Now attempt to insert invalid data - should fail
259+
let result = sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)")
260+
.execute(&pool)
261+
.await;
262+
263+
assert!(
264+
result.is_err(),
265+
"Constraint should prevent insert of invalid eql_v2_encrypted (empty JSONB)"
266+
);
267+
268+
// Verify count unchanged after failed insert
269+
let final_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM encrypted")
270+
.fetch_one(&pool)
271+
.await?;
272+
273+
assert_eq!(
274+
final_count, 3,
275+
"Should still have 3 records after constraint prevented invalid insert"
276+
);
277+
278+
Ok(())
279+
}
280+
281+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
282+
async fn remove_encrypted_constraint_allows_invalid_data(pool: PgPool) -> Result<()> {
283+
// Test: eql_v2.remove_encrypted_constraint() removes validation from encrypted column
284+
// Source: constraints_test.sql lines 24-43
285+
286+
// Add the encrypted constraint first
287+
sqlx::query("SELECT eql_v2.add_encrypted_constraint('encrypted', 'e')")
288+
.execute(&pool)
289+
.await?;
290+
291+
// Verify constraint is working - invalid data should be rejected
292+
let result = sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)")
293+
.execute(&pool)
294+
.await;
295+
296+
assert!(
297+
result.is_err(),
298+
"Constraint should prevent insert of invalid eql_v2_encrypted"
299+
);
300+
301+
// Remove the constraint
302+
sqlx::query("SELECT eql_v2.remove_encrypted_constraint('encrypted', 'e')")
303+
.execute(&pool)
304+
.await?;
305+
306+
// Now invalid data should be allowed
307+
sqlx::query("INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)")
308+
.execute(&pool)
309+
.await?;
310+
311+
let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM encrypted")
312+
.fetch_one(&pool)
313+
.await?;
314+
315+
assert_eq!(
316+
count, 4,
317+
"Should have 4 records (3 valid + 1 invalid after constraint removed)"
318+
);
319+
320+
Ok(())
321+
}
322+
323+
#[sqlx::test(fixtures(path = "../fixtures", scripts("encrypted_json")))]
324+
async fn version_metadata_validation_on_insert(pool: PgPool) -> Result<()> {
325+
// Test: EQL version metadata (v field) is enforced on insert
326+
// Source: constraints_test.sql lines 106-138
327+
//
328+
// Note: The SQL test doesn't explicitly add a constraint, which suggests
329+
// version validation is built into the eql_v2_encrypted type itself or
330+
// is enforced automatically. However, for this test we need to ensure
331+
// the constraint exists to validate version fields.
332+
333+
// Add encrypted constraint to enable version validation
334+
sqlx::query("SELECT eql_v2.add_encrypted_constraint('encrypted', 'e')")
335+
.execute(&pool)
336+
.await?;
337+
338+
// Create a valid encrypted value with version removed
339+
// We'll get a valid encrypted JSON and remove the 'v' field
340+
let encrypted_without_version: String =
341+
sqlx::query_scalar("SELECT (create_encrypted_json(1)::jsonb - 'v')::text")
342+
.fetch_one(&pool)
343+
.await?;
344+
345+
// Attempt to insert without version field - should fail
346+
let result = sqlx::query(&format!(
347+
"INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)",
348+
encrypted_without_version
349+
))
350+
.execute(&pool)
351+
.await;
352+
353+
assert!(
354+
result.is_err(),
355+
"Insert should fail when version field is missing"
356+
);
357+
358+
// Create encrypted value with invalid version (v=1 instead of v=2)
359+
let encrypted_invalid_version: String =
360+
sqlx::query_scalar("SELECT (create_encrypted_json(1)::jsonb || '{\"v\": 1}')::text")
361+
.fetch_one(&pool)
362+
.await?;
363+
364+
// Attempt to insert with invalid version - should fail
365+
let result = sqlx::query(&format!(
366+
"INSERT INTO encrypted (e) VALUES ('{}'::jsonb::eql_v2_encrypted)",
367+
encrypted_invalid_version
368+
))
369+
.execute(&pool)
370+
.await;
371+
372+
assert!(
373+
result.is_err(),
374+
"Insert should fail when version field is invalid (v=1)"
375+
);
376+
377+
// Insert with valid version (v=2) should succeed
378+
sqlx::query("INSERT INTO encrypted (e) VALUES (create_encrypted_json(1))")
379+
.execute(&pool)
380+
.await?;
381+
382+
let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM encrypted")
383+
.fetch_one(&pool)
384+
.await?;
385+
386+
assert_eq!(
387+
count, 4,
388+
"Should have 4 records after successful insert with valid version"
389+
);
390+
391+
Ok(())
392+
}

0 commit comments

Comments
 (0)