@@ -861,3 +861,398 @@ parity_test!(
861861 }
862862 }
863863) ;
864+
865+ // Integer conversion tests - fix2long
866+ parity_test ! (
867+ name: test_fix2long_zero,
868+ func: fix2long,
869+ data_factory: { ruby_eval!( "0" ) } ,
870+ expected: 0 as std:: os:: raw:: c_long
871+ ) ;
872+
873+ parity_test ! (
874+ name: test_fix2long_one,
875+ func: fix2long,
876+ data_factory: { ruby_eval!( "1" ) } ,
877+ expected: 1 as std:: os:: raw:: c_long
878+ ) ;
879+
880+ parity_test ! (
881+ name: test_fix2long_negative_one,
882+ func: fix2long,
883+ data_factory: { ruby_eval!( "-1" ) } ,
884+ expected: -1 as std:: os:: raw:: c_long
885+ ) ;
886+
887+ parity_test ! (
888+ name: test_fix2long_positive_small,
889+ func: fix2long,
890+ data_factory: { ruby_eval!( "42" ) } ,
891+ expected: 42 as std:: os:: raw:: c_long
892+ ) ;
893+
894+ parity_test ! (
895+ name: test_fix2long_negative_small,
896+ func: fix2long,
897+ data_factory: { ruby_eval!( "-123" ) } ,
898+ expected: -123 as std:: os:: raw:: c_long
899+ ) ;
900+
901+ parity_test ! (
902+ name: test_fix2long_large_positive,
903+ func: fix2long,
904+ data_factory: { ruby_eval!( "1073741823" ) } , // 2^30 - 1
905+ expected: 1073741823 as std:: os:: raw:: c_long
906+ ) ;
907+
908+ parity_test ! (
909+ name: test_fix2long_large_negative,
910+ func: fix2long,
911+ data_factory: { ruby_eval!( "-1073741824" ) } , // -2^30
912+ expected: -1073741824 as std:: os:: raw:: c_long
913+ ) ;
914+
915+ // 64-bit specific tests (c_long is i64 on Unix)
916+ #[ cfg( not( windows) ) ]
917+ parity_test ! (
918+ name: test_fix2long_max_fixnum,
919+ func: fix2long,
920+ data_factory: { ruby_eval!( "(2 ** 62) - 1" ) } , // FIXNUM_MAX on 64-bit
921+ expected: ( ( 1i64 << 62 ) - 1 ) as std:: os:: raw:: c_long
922+ ) ;
923+
924+ #[ cfg( not( windows) ) ]
925+ parity_test ! (
926+ name: test_fix2long_min_fixnum,
927+ func: fix2long,
928+ data_factory: { ruby_eval!( "-(2 ** 62)" ) } , // FIXNUM_MIN on 64-bit
929+ expected: ( -( 1i64 << 62 ) ) as std:: os:: raw:: c_long
930+ ) ;
931+
932+ // Windows-specific tests (c_long is i32 on Windows)
933+ #[ cfg( windows) ]
934+ parity_test ! (
935+ name: test_fix2long_max_fixnum,
936+ func: fix2long,
937+ data_factory: { ruby_eval!( "(2 ** 30) - 1" ) } , // FIXNUM_MAX on 32-bit
938+ expected: ( ( 1i32 << 30 ) - 1 ) as std:: os:: raw:: c_long
939+ ) ;
940+
941+ #[ cfg( windows) ]
942+ parity_test ! (
943+ name: test_fix2long_min_fixnum,
944+ func: fix2long,
945+ data_factory: { ruby_eval!( "-(2 ** 30)" ) } , // FIXNUM_MIN on 32-bit
946+ expected: ( -( 1i32 << 30 ) ) as std:: os:: raw:: c_long
947+ ) ;
948+
949+ // Integer conversion tests - fix2ulong
950+ parity_test ! (
951+ name: test_fix2ulong_zero,
952+ func: fix2ulong,
953+ data_factory: { ruby_eval!( "0" ) } ,
954+ expected: 0 as std:: os:: raw:: c_ulong
955+ ) ;
956+
957+ parity_test ! (
958+ name: test_fix2ulong_one,
959+ func: fix2ulong,
960+ data_factory: { ruby_eval!( "1" ) } ,
961+ expected: 1 as std:: os:: raw:: c_ulong
962+ ) ;
963+
964+ parity_test ! (
965+ name: test_fix2ulong_small,
966+ func: fix2ulong,
967+ data_factory: { ruby_eval!( "42" ) } ,
968+ expected: 42 as std:: os:: raw:: c_ulong
969+ ) ;
970+
971+ parity_test ! (
972+ name: test_fix2ulong_medium,
973+ func: fix2ulong,
974+ data_factory: { ruby_eval!( "1000" ) } ,
975+ expected: 1000 as std:: os:: raw:: c_ulong
976+ ) ;
977+
978+ parity_test ! (
979+ name: test_fix2ulong_large,
980+ func: fix2ulong,
981+ data_factory: { ruby_eval!( "1073741823" ) } , // 2^30 - 1
982+ expected: 1073741823 as std:: os:: raw:: c_ulong
983+ ) ;
984+
985+ // 64-bit specific test
986+ #[ cfg( not( windows) ) ]
987+ parity_test ! (
988+ name: test_fix2ulong_max_fixnum,
989+ func: fix2ulong,
990+ data_factory: { ruby_eval!( "(2 ** 62) - 1" ) } , // FIXNUM_MAX on 64-bit
991+ expected: ( ( 1u64 << 62 ) - 1 ) as std:: os:: raw:: c_ulong
992+ ) ;
993+
994+ // Windows-specific test
995+ #[ cfg( windows) ]
996+ parity_test ! (
997+ name: test_fix2ulong_max_fixnum,
998+ func: fix2ulong,
999+ data_factory: { ruby_eval!( "(2 ** 30) - 1" ) } , // FIXNUM_MAX on 32-bit
1000+ expected: ( ( 1u32 << 30 ) - 1 ) as std:: os:: raw:: c_ulong
1001+ ) ;
1002+
1003+ // Integer conversion tests - num2long (handles both fixnum and bignum)
1004+ parity_test ! (
1005+ name: test_num2long_zero,
1006+ func: num2long,
1007+ data_factory: { ruby_eval!( "0" ) } ,
1008+ expected: 0 as std:: os:: raw:: c_long
1009+ ) ;
1010+
1011+ parity_test ! (
1012+ name: test_num2long_one,
1013+ func: num2long,
1014+ data_factory: { ruby_eval!( "1" ) } ,
1015+ expected: 1 as std:: os:: raw:: c_long
1016+ ) ;
1017+
1018+ parity_test ! (
1019+ name: test_num2long_negative_one,
1020+ func: num2long,
1021+ data_factory: { ruby_eval!( "-1" ) } ,
1022+ expected: -1 as std:: os:: raw:: c_long
1023+ ) ;
1024+
1025+ parity_test ! (
1026+ name: test_num2long_positive_small,
1027+ func: num2long,
1028+ data_factory: { ruby_eval!( "999" ) } ,
1029+ expected: 999 as std:: os:: raw:: c_long
1030+ ) ;
1031+
1032+ parity_test ! (
1033+ name: test_num2long_negative_small,
1034+ func: num2long,
1035+ data_factory: { ruby_eval!( "-999" ) } ,
1036+ expected: -999 as std:: os:: raw:: c_long
1037+ ) ;
1038+
1039+ parity_test ! (
1040+ name: test_num2long_large_positive,
1041+ func: num2long,
1042+ data_factory: { ruby_eval!( "2147483647" ) } , // 2^31 - 1 (i32 max)
1043+ expected: 2147483647 as std:: os:: raw:: c_long
1044+ ) ;
1045+
1046+ parity_test ! (
1047+ name: test_num2long_large_negative,
1048+ func: num2long,
1049+ data_factory: { ruby_eval!( "-2147483648" ) } , // -2^31 (i32 min)
1050+ expected: -2147483648 as std:: os:: raw:: c_long
1051+ ) ;
1052+
1053+ // Integer conversion tests - num2ulong
1054+ parity_test ! (
1055+ name: test_num2ulong_zero,
1056+ func: num2ulong,
1057+ data_factory: { ruby_eval!( "0" ) } ,
1058+ expected: 0 as std:: os:: raw:: c_ulong
1059+ ) ;
1060+
1061+ parity_test ! (
1062+ name: test_num2ulong_one,
1063+ func: num2ulong,
1064+ data_factory: { ruby_eval!( "1" ) } ,
1065+ expected: 1 as std:: os:: raw:: c_ulong
1066+ ) ;
1067+
1068+ parity_test ! (
1069+ name: test_num2ulong_small,
1070+ func: num2ulong,
1071+ data_factory: { ruby_eval!( "888" ) } ,
1072+ expected: 888 as std:: os:: raw:: c_ulong
1073+ ) ;
1074+
1075+ parity_test ! (
1076+ name: test_num2ulong_large,
1077+ func: num2ulong,
1078+ data_factory: { ruby_eval!( "4294967295" ) } , // 2^32 - 1 (u32 max)
1079+ expected: 4294967295 as std:: os:: raw:: c_ulong
1080+ ) ;
1081+
1082+ // long2num/ulong2num parity tests
1083+ // These functions take a primitive and return VALUE, so we need a different pattern
1084+ macro_rules! parity_test_long2num {
1085+ ( name: $name: ident, value: $value: expr) => {
1086+ #[ rb_sys_test_helpers:: ruby_test]
1087+ fn $name( ) {
1088+ use rb_sys:: stable_api;
1089+ let val: std:: os:: raw:: c_long = $value;
1090+
1091+ let rust_result = stable_api:: get_default( ) . long2num( val) ;
1092+ let compiled_c_result = stable_api:: get_compiled( ) . long2num( val) ;
1093+
1094+ // Compare by converting back to long
1095+ let rust_roundtrip = unsafe { stable_api:: get_default( ) . num2long( rust_result) } ;
1096+ let compiled_roundtrip =
1097+ unsafe { stable_api:: get_compiled( ) . num2long( compiled_c_result) } ;
1098+
1099+ assert_eq!(
1100+ rust_roundtrip, compiled_roundtrip,
1101+ "long2num parity failed for {}: rust={}, compiled={}" ,
1102+ val, rust_roundtrip, compiled_roundtrip
1103+ ) ;
1104+ assert_eq!( rust_roundtrip, val, "roundtrip failed for {}" , val) ;
1105+ }
1106+ } ;
1107+ }
1108+
1109+ macro_rules! parity_test_ulong2num {
1110+ ( name: $name: ident, value: $value: expr) => {
1111+ #[ rb_sys_test_helpers:: ruby_test]
1112+ fn $name( ) {
1113+ use rb_sys:: stable_api;
1114+ let val: std:: os:: raw:: c_ulong = $value;
1115+
1116+ let rust_result = stable_api:: get_default( ) . ulong2num( val) ;
1117+ let compiled_c_result = stable_api:: get_compiled( ) . ulong2num( val) ;
1118+
1119+ // Compare by converting back to ulong
1120+ let rust_roundtrip = unsafe { stable_api:: get_default( ) . num2ulong( rust_result) } ;
1121+ let compiled_roundtrip =
1122+ unsafe { stable_api:: get_compiled( ) . num2ulong( compiled_c_result) } ;
1123+
1124+ assert_eq!(
1125+ rust_roundtrip, compiled_roundtrip,
1126+ "ulong2num parity failed for {}: rust={}, compiled={}" ,
1127+ val, rust_roundtrip, compiled_roundtrip
1128+ ) ;
1129+ assert_eq!( rust_roundtrip, val, "roundtrip failed for {}" , val) ;
1130+ }
1131+ } ;
1132+ }
1133+
1134+ // long2num parity tests
1135+ parity_test_long2num ! ( name: test_long2num_zero, value: 0 ) ;
1136+ parity_test_long2num ! ( name: test_long2num_one, value: 1 ) ;
1137+ parity_test_long2num ! ( name: test_long2num_negative_one, value: -1 ) ;
1138+ parity_test_long2num ! ( name: test_long2num_small_positive, value: 12345 ) ;
1139+ parity_test_long2num ! ( name: test_long2num_small_negative, value: -12345 ) ;
1140+ parity_test_long2num ! ( name: test_long2num_large_positive, value: 2147483647 ) ; // i32 max
1141+ parity_test_long2num ! ( name: test_long2num_large_negative, value: -2147483648 ) ; // i32 min
1142+
1143+ // 64-bit specific long2num tests
1144+ #[ cfg( not( windows) ) ]
1145+ parity_test_long2num ! ( name: test_long2num_very_large_positive, value: 4611686018427387903 ) ; // 2^62 - 1 (near FIXNUM_MAX)
1146+ #[ cfg( not( windows) ) ]
1147+ parity_test_long2num ! ( name: test_long2num_very_large_negative, value: -4611686018427387904 ) ; // -2^62 (near FIXNUM_MIN)
1148+
1149+ // Windows-specific long2num tests
1150+ #[ cfg( windows) ]
1151+ parity_test_long2num ! ( name: test_long2num_very_large_positive, value: 1073741823 ) ; // 2^30 - 1 (near FIXNUM_MAX on 32-bit)
1152+ #[ cfg( windows) ]
1153+ parity_test_long2num ! ( name: test_long2num_very_large_negative, value: -1073741824 ) ; // -2^30 (near FIXNUM_MIN on 32-bit)
1154+
1155+ // ulong2num parity tests
1156+ parity_test_ulong2num ! ( name: test_ulong2num_zero, value: 0 ) ;
1157+ parity_test_ulong2num ! ( name: test_ulong2num_one, value: 1 ) ;
1158+ parity_test_ulong2num ! ( name: test_ulong2num_small, value: 54321 ) ;
1159+ parity_test_ulong2num ! ( name: test_ulong2num_large, value: 4294967295 ) ; // u32 max
1160+
1161+ // 64-bit specific ulong2num test
1162+ #[ cfg( not( windows) ) ]
1163+ parity_test_ulong2num ! ( name: test_ulong2num_very_large, value: 4611686018427387903 ) ; // 2^62 - 1 (near FIXNUM_MAX)
1164+
1165+ // Windows-specific ulong2num test
1166+ #[ cfg( windows) ]
1167+ parity_test_ulong2num ! ( name: test_ulong2num_very_large, value: 1073741823 ) ; // 2^30 - 1 (near FIXNUM_MAX on 32-bit)
1168+
1169+ // fixable/posfixable parity tests
1170+ #[ rb_sys_test_helpers:: ruby_test]
1171+ fn test_fixable_parity ( ) {
1172+ use rb_sys:: stable_api;
1173+ let rust_api = stable_api:: get_default ( ) ;
1174+ let compiled_api = stable_api:: get_compiled ( ) ;
1175+
1176+ #[ cfg( not( windows) ) ]
1177+ const TEST_VALUES : & [ std:: os:: raw:: c_long ] = & [
1178+ 0 ,
1179+ 1 ,
1180+ -1 ,
1181+ 100 ,
1182+ -100 ,
1183+ 1000 ,
1184+ -1000 ,
1185+ 2147483647 , // i32 max
1186+ -2147483648 , // i32 min
1187+ 4611686018427387903 , // 2^62 - 1 (FIXNUM_MAX on 64-bit)
1188+ -4611686018427387904 , // -2^62 (FIXNUM_MIN on 64-bit)
1189+ 4611686018427387904 , // 2^62 (just above FIXNUM_MAX, not fixable)
1190+ -4611686018427387905 , // just below FIXNUM_MIN (not fixable)
1191+ ] ;
1192+
1193+ #[ cfg( windows) ]
1194+ const TEST_VALUES : & [ std:: os:: raw:: c_long ] = & [
1195+ 0 ,
1196+ 1 ,
1197+ -1 ,
1198+ 100 ,
1199+ -100 ,
1200+ 1000 ,
1201+ -1000 ,
1202+ 1073741823 , // 2^30 - 1 (FIXNUM_MAX on 32-bit)
1203+ -1073741824 , // -2^30 (FIXNUM_MIN on 32-bit)
1204+ 1073741824 , // 2^30 (just above FIXNUM_MAX, not fixable)
1205+ -1073741825 , // just below FIXNUM_MIN (not fixable)
1206+ 2147483647 , // i32 max (not fixable)
1207+ -2147483648 , // i32 min (not fixable)
1208+ ] ;
1209+
1210+ for & val in TEST_VALUES {
1211+ let rust_result = rust_api. fixable ( val) ;
1212+ let compiled_result = compiled_api. fixable ( val) ;
1213+ assert_eq ! (
1214+ rust_result, compiled_result,
1215+ "fixable parity failed for {}: rust={}, compiled={}" ,
1216+ val, rust_result, compiled_result
1217+ ) ;
1218+ }
1219+ }
1220+
1221+ #[ rb_sys_test_helpers:: ruby_test]
1222+ fn test_posfixable_parity ( ) {
1223+ use rb_sys:: stable_api;
1224+ let rust_api = stable_api:: get_default ( ) ;
1225+ let compiled_api = stable_api:: get_compiled ( ) ;
1226+
1227+ #[ cfg( not( windows) ) ]
1228+ const TEST_VALUES : & [ std:: os:: raw:: c_ulong ] = & [
1229+ 0 ,
1230+ 1 ,
1231+ 100 ,
1232+ 1000 ,
1233+ 2147483647 , // i32 max
1234+ 4294967295 , // u32 max
1235+ 4611686018427387903 , // 2^62 - 1 (FIXNUM_MAX on 64-bit)
1236+ 4611686018427387904 , // 2^62 (just above FIXNUM_MAX)
1237+ 9223372036854775807 , // i64 max as u64
1238+ 18446744073709551615 , // u64 max
1239+ ] ;
1240+
1241+ #[ cfg( windows) ]
1242+ const TEST_VALUES : & [ std:: os:: raw:: c_ulong ] = & [
1243+ 0 , 1 , 100 , 1000 , 1073741823 , // 2^30 - 1 (FIXNUM_MAX on 32-bit)
1244+ 1073741824 , // 2^30 (just above FIXNUM_MAX)
1245+ 2147483647 , // i32 max
1246+ 4294967295 , // u32 max
1247+ ] ;
1248+
1249+ for & val in TEST_VALUES {
1250+ let rust_result = rust_api. posfixable ( val) ;
1251+ let compiled_result = compiled_api. posfixable ( val) ;
1252+ assert_eq ! (
1253+ rust_result, compiled_result,
1254+ "posfixable parity failed for {}: rust={}, compiled={}" ,
1255+ val, rust_result, compiled_result
1256+ ) ;
1257+ }
1258+ }
0 commit comments