we are passing all the tests now properly with the table definition and the post tables data now
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// tests/mod.rs
|
||||
// pub mod adresar;
|
||||
pub mod tables_data;
|
||||
// pub mod tables_data;
|
||||
pub mod common;
|
||||
// pub mod table_definition;
|
||||
pub mod table_definition;
|
||||
|
||||
@@ -598,3 +598,4 @@ include!("post_table_definition_test2.rs");
|
||||
include!("post_table_definition_test3.rs");
|
||||
include!("post_table_definition_test4.rs");
|
||||
include!("post_table_definition_test5.rs");
|
||||
include!("post_table_definition_test6.rs");
|
||||
|
||||
294
server/tests/table_definition/post_table_definition_test6.rs
Normal file
294
server/tests/table_definition/post_table_definition_test6.rs
Normal file
@@ -0,0 +1,294 @@
|
||||
// Additional edge case tests for decimal handling
|
||||
// Add these to your test files
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_negative_values_rejected(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
let negative_cases = vec![
|
||||
"decimal(-1, 0)", // negative precision
|
||||
"decimal(5, -1)", // negative scale
|
||||
"decimal(-5, -2)", // both negative
|
||||
];
|
||||
|
||||
for negative_type in negative_cases {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: format!("table_neg_{}", negative_type.replace(['(', ')', ',', '-'], "_")),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: negative_type.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
assert!(result.is_err(), "Negative values should be rejected: {}", negative_type);
|
||||
assert_eq!(result.unwrap_err().code(), Code::InvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_postgresql_limits(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
|
||||
// Test maximum valid PostgreSQL precision (1000)
|
||||
let max_valid_request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: "max_precision_test".into(),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: "decimal(1000, 0)".into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// This should succeed (though you might want to add a limit in your code)
|
||||
let result = post_table_definition(&pool, max_valid_request).await;
|
||||
// Note: Currently your code doesn't enforce PostgreSQL's 1000 limit,
|
||||
// so this will succeed. You may want to add that validation.
|
||||
|
||||
// Test over PostgreSQL limit
|
||||
let over_limit_request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: "over_precision_test".into(),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: "decimal(1001, 0)".into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// This might succeed in your validation but fail at PostgreSQL level
|
||||
// Consider adding explicit validation for this
|
||||
let _result = post_table_definition(&pool, over_limit_request).await;
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_leading_zeros_and_signs(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
let cases = vec![
|
||||
("decimal(01, 02)", false), // leading zeros - should be REJECTED
|
||||
("decimal(001, 000)", false), // multiple leading zeros - should be REJECTED
|
||||
("decimal(+5, +2)", false), // explicit positive signs - should be REJECTED
|
||||
("decimal(05, +2)", false), // mixed formats - should be REJECTED
|
||||
("decimal(2, 1)", true), // clean format - should succeed
|
||||
("decimal(10, 0)", true), // clean format - should succeed
|
||||
("decimal(5, 5)", true), // scale equals precision - should succeed
|
||||
("decimal(1, 0)", true), // minimum valid case - should succeed
|
||||
];
|
||||
|
||||
for (i, (field_type, should_succeed)) in cases.into_iter().enumerate() {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
// Use completely independent, valid table names
|
||||
table_name: format!("test_table_{}", i),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: field_type.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
if should_succeed {
|
||||
assert!(result.is_ok(),
|
||||
"Should succeed: '{}' but got error: {:?}",
|
||||
field_type,
|
||||
result.as_ref().err().map(|e| e.message()));
|
||||
} else {
|
||||
assert!(result.is_err(), "Should fail: '{}'", field_type);
|
||||
if let Err(status) = result {
|
||||
assert_eq!(status.code(), Code::InvalidArgument,
|
||||
"Wrong error code for case '{}': {}", field_type, status.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_extra_parameters_rejected(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
let invalid_cases = vec![
|
||||
"decimal(5,2,3)", // too many parameters
|
||||
"decimal(5,,2)", // double comma
|
||||
"decimal(5, 2, )", // trailing comma
|
||||
"decimal(5,2,)", // trailing comma variant
|
||||
"decimal(5,2,3,4)", // way too many parameters
|
||||
];
|
||||
|
||||
for invalid_case in invalid_cases {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: format!("table_{}", invalid_case.replace(['(', ')', ','], "_")),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: invalid_case.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
assert!(result.is_err(), "Should reject extra parameters: {}", invalid_case);
|
||||
assert_eq!(result.unwrap_err().code(), Code::InvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_floating_point_inputs_rejected(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
let floating_cases = vec![
|
||||
"decimal(5.5, 2)", // floating point precision
|
||||
"decimal(5, 2.0)", // floating point scale
|
||||
"decimal(5.1, 2.9)", // both floating point
|
||||
"decimal(1.0, 0.0)", // explicit decimals
|
||||
];
|
||||
|
||||
for floating_case in floating_cases {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: format!("table_{}", floating_case.replace(['(', ')', ',', '.'], "_")),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: floating_case.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
assert!(result.is_err(), "Should reject floating point: {}", floating_case);
|
||||
assert_eq!(result.unwrap_err().code(), Code::InvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_whitespace_variations(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
let whitespace_cases = vec![
|
||||
("decimal(\t5\t,\t2\t)", true), // tabs
|
||||
("decimal(\n5\n,\n2\n)", true), // newlines
|
||||
("decimal( 5\t, 2\n)", true), // mixed whitespace
|
||||
("decimal(5 2)", false), // missing comma
|
||||
("decimal(5\t2)", false), // tab instead of comma
|
||||
];
|
||||
|
||||
for (i, (case, should_succeed)) in whitespace_cases.into_iter().enumerate() {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: format!("whitespace_test_{}", i),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: case.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
if should_succeed {
|
||||
assert!(result.is_ok(), "Should handle whitespace: {}", case);
|
||||
} else {
|
||||
assert!(result.is_err(), "Should reject invalid format: {}", case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_boundary_scale_values(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
let boundary_cases = vec![
|
||||
("decimal(10, 10)", true), // scale equals precision (valid)
|
||||
("decimal(10, 11)", false), // scale > precision (invalid, already tested)
|
||||
("decimal(1, 0)", true), // minimum valid case
|
||||
("decimal(2, 1)", true), // normal case
|
||||
];
|
||||
|
||||
for (i, (case, should_succeed)) in boundary_cases.into_iter().enumerate() {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: format!("boundary_test_{}", i),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: case.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
if should_succeed {
|
||||
assert!(result.is_ok(), "Should succeed: {}", case);
|
||||
} else {
|
||||
assert!(result.is_err(), "Should fail: {}", case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_case_insensitive_variations(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
let case_variations = vec![
|
||||
"DECIMAL(5,2)",
|
||||
"Decimal(5,2)",
|
||||
"decimal(5,2)",
|
||||
"DeCiMaL(5,2)",
|
||||
];
|
||||
|
||||
for (i, case_variant) in case_variations.into_iter().enumerate() {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: format!("case_test_{}", i),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: case_variant.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
assert!(result.is_ok(), "Should handle case variation: {}", case_variant);
|
||||
|
||||
let response = result.unwrap();
|
||||
assert!(response.sql.contains("NUMERIC(5, 2)"),
|
||||
"Should map to NUMERIC(5, 2): {}", response.sql);
|
||||
}
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_decimal_u32_overflow_protection(#[future] pool: PgPool) {
|
||||
let pool = pool.await;
|
||||
|
||||
// Test numbers that would overflow u32 (> 4,294,967,295)
|
||||
// Your current code uses u32::parse, so these should fail gracefully
|
||||
let overflow_cases = vec![
|
||||
"decimal(4294967296, 0)", // u32::MAX + 1
|
||||
"decimal(0, 4294967296)", // u32::MAX + 1 for scale
|
||||
"decimal(99999999999999, 0)", // very large number
|
||||
];
|
||||
|
||||
for overflow_case in overflow_cases {
|
||||
let request = PostTableDefinitionRequest {
|
||||
profile_name: "default".into(),
|
||||
table_name: format!("overflow_test_{}", overflow_case.len()),
|
||||
columns: vec![ColumnDefinition {
|
||||
name: "amount".into(),
|
||||
field_type: overflow_case.into(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let result = post_table_definition(&pool, request).await;
|
||||
assert!(result.is_err(), "Should reject overflow values: {}", overflow_case);
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.code(), Code::InvalidArgument);
|
||||
// Should contain either "Invalid precision" or "Invalid scale"
|
||||
assert!(err.message().contains("Invalid") &&
|
||||
(err.message().contains("precision") || err.message().contains("scale")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user