get adresar by position unit test

This commit is contained in:
filipriec
2025-02-25 11:17:02 +01:00
parent 6f5e548200
commit 684f238d1c
2 changed files with 304 additions and 0 deletions

View File

@@ -0,0 +1,303 @@
// tests/adresar/get_adresar_by_position_test.rs
use rstest::{fixture, rstest};
use server::adresar::handlers::get_adresar_by_position;
use common::proto::multieko2::common::PositionRequest;
use crate::common::setup_test_db;
use sqlx::PgPool;
use tonic;
use std::sync::Arc;
use tokio::sync::Mutex;
// Use a global mutex to synchronize test execution
// This prevents tests from interfering with each other
lazy_static::lazy_static! {
static ref TEST_MUTEX: Arc<Mutex<()>> = Arc::new(Mutex::new(()));
}
#[fixture]
async fn pool() -> PgPool {
setup_test_db().await
}
#[fixture]
async fn closed_pool(#[future] pool: PgPool) -> PgPool {
let pool = pool.await;
pool.close().await;
pool
}
// Create a test record with specific data and delete status
async fn create_test_record(pool: &PgPool, firma: &str, deleted: bool) -> i64 {
sqlx::query_scalar!(
"INSERT INTO adresar (firma, deleted) VALUES ($1, $2) RETURNING id",
firma,
deleted
)
.fetch_one(pool)
.await
.unwrap()
}
// Clean up test records after tests
async fn cleanup_test_records(pool: &PgPool, prefix: &str) {
sqlx::query!(
"DELETE FROM adresar WHERE firma LIKE $1",
format!("{}%", prefix)
)
.execute(pool)
.await
.unwrap();
}
// Find the position of a record in the database
async fn find_position_of_record(pool: &PgPool, id: i64) -> Option<i64> {
// Get all non-deleted records ordered by ID
let records = sqlx::query_scalar!(
"SELECT id FROM adresar WHERE deleted = FALSE ORDER BY id ASC"
)
.fetch_all(pool)
.await
.unwrap();
// Find the position of our record (1-based)
for (index, record_id) in records.iter().enumerate() {
if *record_id == id {
return Some((index + 1) as i64);
}
}
None
}
// Test position validation
#[rstest]
#[tokio::test]
async fn test_position_zero(#[future] pool: PgPool) {
let pool = pool.await;
// Request position 0 (invalid)
let request = PositionRequest { position: 0 };
let result = get_adresar_by_position(&pool, request).await;
// Verify it returns an error
assert!(result.is_err());
assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument);
}
#[rstest]
#[tokio::test]
async fn test_position_negative(#[future] pool: PgPool) {
let pool = pool.await;
// Request negative position (invalid)
let request = PositionRequest { position: -1 };
let result = get_adresar_by_position(&pool, request).await;
// Verify it returns an error
assert!(result.is_err());
assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument);
}
#[rstest]
#[tokio::test]
async fn test_basic_position_retrieval(#[future] pool: PgPool) {
let pool = pool.await;
// Take a lock to prevent concurrent test execution
let _guard = TEST_MUTEX.lock().await;
// Use a unique prefix for test data to prevent conflicts
let prefix = "PosBasicTest";
// Clean up any existing test data
cleanup_test_records(&pool, prefix).await;
// Create test records
let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await;
let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await;
let id3 = create_test_record(&pool, &format!("{}_3", prefix), false).await;
// Find the positions of these records in the database
let pos1 = find_position_of_record(&pool, id1).await.unwrap();
let pos2 = find_position_of_record(&pool, id2).await.unwrap();
let pos3 = find_position_of_record(&pool, id3).await.unwrap();
// Test retrieving each position
let response1 = get_adresar_by_position(&pool, PositionRequest { position: pos1 }).await.unwrap();
assert_eq!(response1.id, id1);
let response2 = get_adresar_by_position(&pool, PositionRequest { position: pos2 }).await.unwrap();
assert_eq!(response2.id, id2);
let response3 = get_adresar_by_position(&pool, PositionRequest { position: pos3 }).await.unwrap();
assert_eq!(response3.id, id3);
// Clean up test data
cleanup_test_records(&pool, prefix).await;
}
#[rstest]
#[tokio::test]
async fn test_deleted_records_excluded(#[future] pool: PgPool) {
let pool = pool.await;
// Take a lock to prevent concurrent test execution
let _guard = TEST_MUTEX.lock().await;
// Use a unique prefix for test data
let prefix = "PosDeletedTest";
// Clean up any existing test data
cleanup_test_records(&pool, prefix).await;
// Create a mix of active and deleted records
let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await;
let _id_deleted = create_test_record(&pool, &format!("{}_del", prefix), true).await;
let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await;
// Find positions
let pos1 = find_position_of_record(&pool, id1).await.unwrap();
let pos2 = find_position_of_record(&pool, id2).await.unwrap();
// Verify positions are consecutive, which means the deleted record is excluded
assert_eq!(pos2, pos1 + 1);
// Retrieve by position and verify
let response1 = get_adresar_by_position(&pool, PositionRequest { position: pos1 }).await.unwrap();
assert_eq!(response1.id, id1);
let response2 = get_adresar_by_position(&pool, PositionRequest { position: pos2 }).await.unwrap();
assert_eq!(response2.id, id2);
// Clean up test data
cleanup_test_records(&pool, prefix).await;
}
#[rstest]
#[tokio::test]
async fn test_position_changes_after_deletion(#[future] pool: PgPool) {
let pool = pool.await;
// Take a lock to prevent concurrent test execution
let _guard = TEST_MUTEX.lock().await;
// Use a unique prefix for test data
let prefix = "PosChangeTest";
// Clean up any existing test data
cleanup_test_records(&pool, prefix).await;
// Create records
let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await;
let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await;
let id3 = create_test_record(&pool, &format!("{}_3", prefix), false).await;
// Find initial positions
let pos1 = find_position_of_record(&pool, id1).await.unwrap();
let pos2 = find_position_of_record(&pool, id2).await.unwrap();
let pos3 = find_position_of_record(&pool, id3).await.unwrap();
// Mark the first record as deleted
sqlx::query!("UPDATE adresar SET deleted = TRUE WHERE id = $1", id1)
.execute(&pool)
.await
.unwrap();
// Find new positions
let pos2_after = find_position_of_record(&pool, id2).await.unwrap();
let pos3_after = find_position_of_record(&pool, id3).await.unwrap();
// Verify positions shifted
assert!(pos2_after < pos2);
assert!(pos3_after < pos3);
// Verify by retrieving records at new positions
let response_at_first = get_adresar_by_position(&pool, PositionRequest { position: pos2_after }).await.unwrap();
assert_eq!(response_at_first.id, id2);
// Clean up test data
cleanup_test_records(&pool, prefix).await;
}
#[rstest]
#[tokio::test]
async fn test_position_out_of_bounds(#[future] pool: PgPool) {
let pool = pool.await;
// Take a lock to prevent concurrent test execution
let _guard = TEST_MUTEX.lock().await;
// Get the total count of non-deleted records
let count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM adresar WHERE deleted = FALSE"
)
.fetch_one(&pool)
.await
.unwrap()
.unwrap_or(0);
// Request a position beyond the count
let request = PositionRequest { position: count + 1 };
let result = get_adresar_by_position(&pool, request).await;
// Verify it returns an error
assert!(result.is_err());
assert_eq!(result.unwrap_err().code(), tonic::Code::NotFound);
}
#[rstest]
#[tokio::test]
async fn test_database_error(#[future] closed_pool: PgPool) {
let closed_pool = closed_pool.await;
// Attempt to query with a closed pool
let request = PositionRequest { position: 1 };
let result = get_adresar_by_position(&closed_pool, request).await;
// Verify it returns an internal error
assert!(result.is_err());
assert_eq!(result.unwrap_err().code(), tonic::Code::Internal);
}
#[rstest]
#[tokio::test]
async fn test_position_after_adding_record(#[future] pool: PgPool) {
let pool = pool.await;
// Take a lock to prevent concurrent test execution
let _guard = TEST_MUTEX.lock().await;
// Use a unique prefix for test data
let prefix = "PosAddTest";
// Clean up any existing test data
cleanup_test_records(&pool, prefix).await;
// Create records
let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await;
let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await;
// Find positions
let pos1 = find_position_of_record(&pool, id1).await.unwrap();
let pos2 = find_position_of_record(&pool, id2).await.unwrap();
// Add a new record
let id3 = create_test_record(&pool, &format!("{}_3", prefix), false).await;
// Find its position
let pos3 = find_position_of_record(&pool, id3).await.unwrap();
// Verify retrieval by position
let response3 = get_adresar_by_position(&pool, PositionRequest { position: pos3 }).await.unwrap();
assert_eq!(response3.id, id3);
// Verify original positions still work
let response1 = get_adresar_by_position(&pool, PositionRequest { position: pos1 }).await.unwrap();
assert_eq!(response1.id, id1);
let response2 = get_adresar_by_position(&pool, PositionRequest { position: pos2 }).await.unwrap();
assert_eq!(response2.id, id2);
// Clean up test data
cleanup_test_records(&pool, prefix).await;
}

View File

@@ -4,3 +4,4 @@ pub mod post_adresar_test;
pub mod put_adresar_test;
pub mod get_adresar_test;
pub mod get_adresar_count_test;
pub mod get_adresar_by_position_test;