@@ -668,6 +668,385 @@ mod tests {
668
668
"Cache should still work correctly after concurrent operations" ) ;
669
669
}
670
670
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
+
671
1050
#[ test]
672
1051
fn test_lock_poisoning_recovery ( ) {
673
1052
use std:: sync:: { Arc , Barrier } ;
0 commit comments