Skip to content

Commit 7c40333

Browse files
committed
Create integration tests for CrcParams compatibility
- Add tests to verify `CrcParams::new()` behavior is unchanged - Test that all existing CRC parameter combinations work correctly - Verify that cached and uncached results are identical - Test multiple `CrcParams` instances with same parameters use cached keys
1 parent 5be2e91 commit 7c40333

File tree

2 files changed

+380
-1
lines changed

2 files changed

+380
-1
lines changed

.kiro/specs/crc-params-caching/tasks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
- Test lock poisoning recovery behavior
5050
- _Requirements: 1.3_
5151

52-
- [ ] 8. Create integration tests for CrcParams compatibility
52+
- [x] 8. Create integration tests for CrcParams compatibility
5353
- Add tests to verify `CrcParams::new()` behavior is unchanged
5454
- Test that all existing CRC parameter combinations work correctly
5555
- Verify that cached and uncached results are identical

src/cache.rs

Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,385 @@ mod tests {
668668
"Cache should still work correctly after concurrent operations");
669669
}
670670

671+
// Integration tests for CrcParams compatibility
672+
#[test]
673+
fn test_crc_params_new_behavior_unchanged() {
674+
use crate::CrcParams;
675+
676+
clear_cache();
677+
678+
// Test that CrcParams::new() creates identical instances regardless of caching
679+
let params1 = CrcParams::new("TEST_CRC32", 32, 0x04C11DB7, 0xFFFFFFFF, true, 0xFFFFFFFF, 0xCBF43926);
680+
let params2 = CrcParams::new("TEST_CRC32", 32, 0x04C11DB7, 0xFFFFFFFF, true, 0xFFFFFFFF, 0xCBF43926);
681+
682+
// All fields should be identical
683+
assert_eq!(params1.name, params2.name);
684+
assert_eq!(params1.width, params2.width);
685+
assert_eq!(params1.poly, params2.poly);
686+
assert_eq!(params1.init, params2.init);
687+
assert_eq!(params1.refin, params2.refin);
688+
assert_eq!(params1.refout, params2.refout);
689+
assert_eq!(params1.xorout, params2.xorout);
690+
assert_eq!(params1.check, params2.check);
691+
assert_eq!(params1.keys, params2.keys);
692+
693+
// Test CRC64 parameters as well
694+
let params64_1 = CrcParams::new("TEST_CRC64", 64, 0x42F0E1EBA9EA3693, 0xFFFFFFFFFFFFFFFF, false, 0x0, 0x6C40DF5F0B497347);
695+
let params64_2 = CrcParams::new("TEST_CRC64", 64, 0x42F0E1EBA9EA3693, 0xFFFFFFFFFFFFFFFF, false, 0x0, 0x6C40DF5F0B497347);
696+
697+
assert_eq!(params64_1.name, params64_2.name);
698+
assert_eq!(params64_1.width, params64_2.width);
699+
assert_eq!(params64_1.poly, params64_2.poly);
700+
assert_eq!(params64_1.init, params64_2.init);
701+
assert_eq!(params64_1.refin, params64_2.refin);
702+
assert_eq!(params64_1.refout, params64_2.refout);
703+
assert_eq!(params64_1.xorout, params64_2.xorout);
704+
assert_eq!(params64_1.check, params64_2.check);
705+
assert_eq!(params64_1.keys, params64_2.keys);
706+
}
707+
708+
#[test]
709+
fn test_existing_crc_parameter_combinations() {
710+
use crate::test::consts::TEST_ALL_CONFIGS;
711+
712+
clear_cache();
713+
714+
// Test all existing CRC parameter combinations work correctly with caching
715+
for config in TEST_ALL_CONFIGS {
716+
let params = crate::CrcParams::new(
717+
config.get_name(),
718+
config.get_width(),
719+
config.get_poly(),
720+
config.get_init(),
721+
config.get_refin(),
722+
config.get_xorout(),
723+
config.get_check(),
724+
);
725+
726+
// Verify the parameters are set correctly
727+
assert_eq!(params.name, config.get_name());
728+
assert_eq!(params.width, config.get_width());
729+
assert_eq!(params.poly, config.get_poly());
730+
assert_eq!(params.init, config.get_init());
731+
assert_eq!(params.refin, config.get_refin());
732+
assert_eq!(params.refout, config.get_refin());
733+
assert_eq!(params.xorout, config.get_xorout());
734+
assert_eq!(params.check, config.get_check());
735+
736+
// Verify keys are correct by comparing with expected keys
737+
let expected_keys = config.get_keys();
738+
assert_eq!(params.keys, expected_keys,
739+
"Keys mismatch for {}: expected {:?}, got {:?}",
740+
config.get_name(), expected_keys, params.keys);
741+
}
742+
}
743+
744+
#[test]
745+
fn test_cached_vs_uncached_results_identical() {
746+
clear_cache();
747+
748+
// Test parameters that affect key generation
749+
let test_cases = [
750+
(32, 0x04C11DB7, true), // CRC32 reflected
751+
(32, 0x04C11DB7, false), // CRC32 non-reflected
752+
(32, 0x1EDC6F41, true), // CRC32C
753+
(64, 0x42F0E1EBA9EA3693, true), // CRC64 ISO reflected
754+
(64, 0x42F0E1EBA9EA3693, false), // CRC64 ISO non-reflected
755+
(64, 0xD800000000000000, true), // CRC64 ECMA
756+
];
757+
758+
for &(width, poly, reflected) in &test_cases {
759+
// Generate keys directly (uncached)
760+
let uncached_keys = generate::keys(width, poly, reflected);
761+
762+
// Clear cache to ensure first call is cache miss
763+
clear_cache();
764+
765+
// Create CrcParams instance (first call - cache miss)
766+
let params1 = crate::CrcParams::new(
767+
"TEST", width, poly, 0xFFFFFFFFFFFFFFFF, reflected, 0x0, 0x0
768+
);
769+
770+
// Create another CrcParams instance with same parameters (cache hit)
771+
let params2 = crate::CrcParams::new(
772+
"TEST", width, poly, 0xFFFFFFFFFFFFFFFF, reflected, 0x0, 0x0
773+
);
774+
775+
// All should be identical
776+
assert_eq!(uncached_keys, params1.keys,
777+
"Uncached keys should match CrcParams keys for width={}, poly={:#x}, reflected={}",
778+
width, poly, reflected);
779+
assert_eq!(params1.keys, params2.keys,
780+
"Cached and uncached CrcParams should have identical keys for width={}, poly={:#x}, reflected={}",
781+
width, poly, reflected);
782+
assert_eq!(uncached_keys, params2.keys,
783+
"All key generation methods should produce identical results for width={}, poly={:#x}, reflected={}",
784+
width, poly, reflected);
785+
}
786+
}
787+
788+
#[test]
789+
fn test_multiple_crc_params_instances_use_cached_keys() {
790+
clear_cache();
791+
792+
// Create multiple CrcParams instances with the same parameters
793+
let width = 32;
794+
let poly = 0x04C11DB7;
795+
let reflected = true;
796+
let init = 0xFFFFFFFF;
797+
let xorout = 0xFFFFFFFF;
798+
let check = 0xCBF43926;
799+
800+
// First instance - should generate and cache keys
801+
let params1 = crate::CrcParams::new("TEST1", width, poly, init, reflected, xorout, check);
802+
803+
// Subsequent instances - should use cached keys
804+
let params2 = crate::CrcParams::new("TEST2", width, poly, init, reflected, xorout, check);
805+
let params3 = crate::CrcParams::new("TEST3", width, poly, init, reflected, xorout, check);
806+
let params4 = crate::CrcParams::new("TEST4", width, poly, init, reflected, xorout, check);
807+
808+
// All should have identical keys (proving cache is working)
809+
assert_eq!(params1.keys, params2.keys, "Instance 1 and 2 should have identical keys");
810+
assert_eq!(params1.keys, params3.keys, "Instance 1 and 3 should have identical keys");
811+
assert_eq!(params1.keys, params4.keys, "Instance 1 and 4 should have identical keys");
812+
assert_eq!(params2.keys, params3.keys, "Instance 2 and 3 should have identical keys");
813+
assert_eq!(params2.keys, params4.keys, "Instance 2 and 4 should have identical keys");
814+
assert_eq!(params3.keys, params4.keys, "Instance 3 and 4 should have identical keys");
815+
816+
// Verify keys are mathematically correct
817+
let expected_keys = generate::keys(width, poly, reflected);
818+
assert_eq!(params1.keys, expected_keys, "Cached keys should be mathematically correct");
819+
820+
// Test with different parameters that don't affect key generation
821+
let params5 = crate::CrcParams::new("DIFFERENT_NAME", width, poly, 0x12345678, reflected, 0x87654321, 0xABCDEF);
822+
assert_eq!(params1.keys, params5.keys,
823+
"Different init/xorout/check/name should not affect cached keys");
824+
825+
// Test with CRC64 parameters
826+
let width64 = 64;
827+
let poly64 = 0x42F0E1EBA9EA3693;
828+
let reflected64 = false;
829+
830+
let params64_1 = crate::CrcParams::new("CRC64_1", width64, poly64, 0xFFFFFFFFFFFFFFFF, reflected64, 0x0, 0x0);
831+
let params64_2 = crate::CrcParams::new("CRC64_2", width64, poly64, 0x0, reflected64, 0xFFFFFFFFFFFFFFFF, 0x12345);
832+
let params64_3 = crate::CrcParams::new("CRC64_3", width64, poly64, 0x123456789ABCDEF0, reflected64, 0x0FEDCBA987654321, 0x999);
833+
834+
assert_eq!(params64_1.keys, params64_2.keys, "CRC64 instances should have identical keys");
835+
assert_eq!(params64_1.keys, params64_3.keys, "CRC64 instances should have identical keys");
836+
837+
let expected_keys64 = generate::keys(width64, poly64, reflected64);
838+
assert_eq!(params64_1.keys, expected_keys64, "CRC64 cached keys should be mathematically correct");
839+
}
840+
841+
#[test]
842+
fn test_crc_params_api_compatibility() {
843+
use crate::{CrcParams, CrcAlgorithm};
844+
845+
clear_cache();
846+
847+
// Test that the CrcParams API remains unchanged
848+
let params = CrcParams::new(
849+
"API_TEST",
850+
32,
851+
0x04C11DB7,
852+
0xFFFFFFFF,
853+
true,
854+
0xFFFFFFFF,
855+
0xCBF43926
856+
);
857+
858+
// Verify all public fields are accessible and have expected types
859+
let _algorithm: CrcAlgorithm = params.algorithm;
860+
let _name: &'static str = params.name;
861+
let _width: u8 = params.width;
862+
let _poly: u64 = params.poly;
863+
let _init: u64 = params.init;
864+
let _refin: bool = params.refin;
865+
let _refout: bool = params.refout;
866+
let _xorout: u64 = params.xorout;
867+
let _check: u64 = params.check;
868+
let _keys: [u64; 23] = params.keys;
869+
870+
// Verify the algorithm is set correctly based on width
871+
match params.width {
872+
32 => assert!(matches!(params.algorithm, CrcAlgorithm::Crc32Custom)),
873+
64 => assert!(matches!(params.algorithm, CrcAlgorithm::Crc64Custom)),
874+
_ => panic!("Unexpected width: {}", params.width),
875+
}
876+
877+
// Test that CrcParams can be copied and cloned
878+
let params_copy = params;
879+
let params_clone = params.clone();
880+
881+
assert_eq!(params.keys, params_copy.keys);
882+
assert_eq!(params.keys, params_clone.keys);
883+
884+
// Test Debug formatting works
885+
let debug_str = format!("{:?}", params);
886+
assert!(debug_str.contains("CrcParams"));
887+
assert!(debug_str.contains("API_TEST"));
888+
}
889+
890+
#[test]
891+
fn test_crc_params_with_all_standard_algorithms() {
892+
use crate::test::consts::TEST_ALL_CONFIGS;
893+
894+
clear_cache();
895+
896+
// Test creating CrcParams for all standard CRC algorithms
897+
for config in TEST_ALL_CONFIGS {
898+
// Create CrcParams using the same parameters as the standard algorithm
899+
let params = crate::CrcParams::new(
900+
config.get_name(),
901+
config.get_width(),
902+
config.get_poly(),
903+
config.get_init(),
904+
config.get_refin(),
905+
config.get_xorout(),
906+
config.get_check(),
907+
);
908+
909+
// Verify the created params match the expected configuration
910+
assert_eq!(params.name, config.get_name());
911+
assert_eq!(params.width, config.get_width());
912+
assert_eq!(params.poly, config.get_poly());
913+
assert_eq!(params.init, config.get_init());
914+
assert_eq!(params.refin, config.get_refin());
915+
assert_eq!(params.refout, config.get_refin());
916+
assert_eq!(params.xorout, config.get_xorout());
917+
assert_eq!(params.check, config.get_check());
918+
919+
// Most importantly, verify the keys are correct
920+
assert_eq!(params.keys, config.get_keys(),
921+
"Keys should match expected values for {}", config.get_name());
922+
923+
// Create a second instance to test caching
924+
let params2 = crate::CrcParams::new(
925+
"CACHED_VERSION", // Different name shouldn't affect caching
926+
config.get_width(),
927+
config.get_poly(),
928+
0x12345678, // Different init shouldn't affect caching
929+
config.get_refin(),
930+
0x87654321, // Different xorout shouldn't affect caching
931+
0xABCDEF, // Different check shouldn't affect caching
932+
);
933+
934+
// Keys should be identical (proving cache hit)
935+
assert_eq!(params.keys, params2.keys,
936+
"Cached keys should be identical for {}", config.get_name());
937+
}
938+
}
939+
940+
#[test]
941+
fn test_crc_params_edge_cases() {
942+
clear_cache();
943+
944+
// Test edge cases for CrcParams creation
945+
946+
// Test minimum and maximum polynomial values
947+
let params_min_poly = crate::CrcParams::new("MIN_POLY", 32, 0x1, 0x0, false, 0x0, 0x0);
948+
let params_max_poly = crate::CrcParams::new("MAX_POLY", 32, 0xFFFFFFFF, 0x0, false, 0x0, 0x0);
949+
950+
// Both should create valid instances
951+
assert_eq!(params_min_poly.width, 32);
952+
assert_eq!(params_min_poly.poly, 0x1);
953+
assert_eq!(params_max_poly.width, 32);
954+
assert_eq!(params_max_poly.poly, 0xFFFFFFFF);
955+
956+
// Test both reflection modes
957+
let params_reflected = crate::CrcParams::new("REFLECTED", 32, 0x04C11DB7, 0x0, true, 0x0, 0x0);
958+
let params_normal = crate::CrcParams::new("NORMAL", 32, 0x04C11DB7, 0x0, false, 0x0, 0x0);
959+
960+
// Should have different keys due to different reflection
961+
assert_ne!(params_reflected.keys, params_normal.keys);
962+
assert_eq!(params_reflected.refin, true);
963+
assert_eq!(params_reflected.refout, true);
964+
assert_eq!(params_normal.refin, false);
965+
assert_eq!(params_normal.refout, false);
966+
967+
// Test 64-bit edge cases
968+
let params64_min = crate::CrcParams::new("CRC64_MIN", 64, 0x1, 0x0, false, 0x0, 0x0);
969+
let params64_max = crate::CrcParams::new("CRC64_MAX", 64, 0xFFFFFFFFFFFFFFFF, 0x0, false, 0x0, 0x0);
970+
971+
assert_eq!(params64_min.width, 64);
972+
assert_eq!(params64_min.poly, 0x1);
973+
assert_eq!(params64_max.width, 64);
974+
assert_eq!(params64_max.poly, 0xFFFFFFFFFFFFFFFF);
975+
976+
// Verify all instances have valid 23-element key arrays
977+
assert_eq!(params_min_poly.keys.len(), 23);
978+
assert_eq!(params_max_poly.keys.len(), 23);
979+
assert_eq!(params_reflected.keys.len(), 23);
980+
assert_eq!(params_normal.keys.len(), 23);
981+
assert_eq!(params64_min.keys.len(), 23);
982+
assert_eq!(params64_max.keys.len(), 23);
983+
}
984+
985+
#[test]
986+
fn test_crc_params_concurrent_creation() {
987+
use std::sync::{Arc, Barrier};
988+
use std::thread;
989+
990+
clear_cache();
991+
992+
let num_threads = 8;
993+
let barrier = Arc::new(Barrier::new(num_threads));
994+
let mut handles = Vec::new();
995+
996+
// All threads create CrcParams with the same parameters simultaneously
997+
for i in 0..num_threads {
998+
let barrier_clone = Arc::clone(&barrier);
999+
let handle = thread::spawn(move || {
1000+
barrier_clone.wait();
1001+
1002+
// All threads create the same CrcParams
1003+
let params = crate::CrcParams::new(
1004+
"CONCURRENT_TEST",
1005+
32,
1006+
0x04C11DB7,
1007+
0xFFFFFFFF,
1008+
true,
1009+
0xFFFFFFFF,
1010+
0xCBF43926
1011+
);
1012+
1013+
(i, params)
1014+
});
1015+
handles.push(handle);
1016+
}
1017+
1018+
// Collect results from all threads
1019+
let mut results = Vec::new();
1020+
for handle in handles {
1021+
results.push(handle.join().expect("Thread should not panic"));
1022+
}
1023+
1024+
// Verify all threads completed successfully
1025+
assert_eq!(results.len(), num_threads);
1026+
1027+
// Verify all CrcParams instances have identical keys
1028+
let first_keys = results[0].1.keys;
1029+
for (thread_id, params) in results {
1030+
assert_eq!(params.keys, first_keys,
1031+
"Thread {} should have identical keys to other threads", thread_id);
1032+
1033+
// Verify other fields are also correct
1034+
assert_eq!(params.name, "CONCURRENT_TEST");
1035+
assert_eq!(params.width, 32);
1036+
assert_eq!(params.poly, 0x04C11DB7);
1037+
assert_eq!(params.init, 0xFFFFFFFF);
1038+
assert_eq!(params.refin, true);
1039+
assert_eq!(params.refout, true);
1040+
assert_eq!(params.xorout, 0xFFFFFFFF);
1041+
assert_eq!(params.check, 0xCBF43926);
1042+
}
1043+
1044+
// Verify the keys are mathematically correct
1045+
let expected_keys = generate::keys(32, 0x04C11DB7, true);
1046+
assert_eq!(first_keys, expected_keys,
1047+
"All concurrent CrcParams should have correct keys");
1048+
}
1049+
6711050
#[test]
6721051
fn test_lock_poisoning_recovery() {
6731052
use std::sync::{Arc, Barrier};

0 commit comments

Comments
 (0)