OCaml library for Crockford's Base32
at v1.0.0 6.7 kB view raw
1(* Test suite using Alcotest - ported from crockford_test.go *) 2 3(* Encode tests *) 4let test_encode () = 5 let test_cases = [ 6 (0L, 0, 0, false, "0"); 7 (1234L, 0, 0, false, "16j"); 8 (1234L, 2, 0, false, "16-j"); 9 (1234L, 2, 4, false, "01-6j"); 10 (538751765283013L, 5, 10, false, "f9zqn-sf065"); 11 (736381604818L, 5, 10, true, "ndsw7-4yj20"); 12 (258706475165200172L, 7, 14, true, "75rw5cg-n1bsc64"); 13 (161006169L, 4, 8, true, "4shg-js75"); 14 ] in 15 List.iter (fun (input, split_every, length, checksum, expected) -> 16 let result = Crockford.encode ~split_every ~min_length:length ~checksum input in 17 let test_name = Printf.sprintf "encode %Ld (split=%d, len=%d, checksum=%b)" input split_every length checksum in 18 Alcotest.(check string) test_name expected result 19 ) test_cases 20 21(* Generate tests *) 22let test_generate () = 23 Random.self_init (); 24 25 let test_cases = [ 26 (4, 0, false); 27 (10, 5, false); 28 (10, 5, true); 29 ] in 30 List.iter (fun (length, split_every, checksum) -> 31 let result = Crockford.generate ~length ~split_every ~checksum () in 32 let expected_length = 33 if split_every > 0 then 34 length + (length / split_every) - 1 35 else 36 length 37 in 38 let test_name = Printf.sprintf "generate length=%d split=%d checksum=%b" length split_every checksum in 39 Alcotest.(check int) test_name expected_length (String.length result) 40 ) test_cases 41 42(* Decode tests *) 43let test_decode () = 44 let test_cases = [ 45 ("0", false, Some 0L); 46 ("16j", false, Some 1234L); 47 ("16-j", false, Some 1234L); 48 ("01-6j", false, Some 1234L); 49 ("f9zqn-sf065", false, Some 538751765283013L); 50 ("twwjw-1ww98", true, Some 924377286556L); 51 ("9ed5m-ytn", false, Some 324712168277L); 52 ("9ed5m-ytn30", true, Some 324712168277L); 53 ("elife.01567", false, None); (* Should fail - contains invalid character '.' *) 54 ] in 55 List.iter (fun (input, checksum, expected) -> 56 let test_name = Printf.sprintf "decode '%s' (checksum=%b)" input checksum in 57 match expected with 58 | Some want -> 59 let got = Crockford.decode ~checksum input in 60 Alcotest.(check int64) test_name want got 61 | None -> 62 (* Expected to fail *) 63 Alcotest.check_raises 64 test_name 65 (Crockford.Decode_error (Crockford.Invalid_character { 66 char = '.'; 67 message = "character '.' not in base32 alphabet" 68 })) 69 (fun () -> ignore (Crockford.decode ~checksum input)) 70 ) test_cases 71 72(* Normalize tests *) 73let test_normalize () = 74 let test_cases = [ 75 ("f9ZQNSF065", "f9zqnsf065"); 76 ("f9zqn-sf065", "f9zqnsf065"); 77 ("f9Llio", "f91110"); 78 ] in 79 List.iter (fun (input, expected) -> 80 let result = Crockford.normalize input in 81 let test_name = Printf.sprintf "normalize '%s'" input in 82 Alcotest.(check string) test_name expected result 83 ) test_cases 84 85(* GenerateChecksum tests *) 86let test_generate_checksum () = 87 let test_cases = [ 88 (450320459383L, 85L); 89 (123456789012L, 44L); 90 ] in 91 List.iter (fun (input, expected) -> 92 let result = Crockford.generate_checksum input in 93 let test_name = Printf.sprintf "generate_checksum %Ld" input in 94 Alcotest.(check int64) test_name expected result 95 ) test_cases 96 97(* Validate tests *) 98let test_validate () = 99 let test_cases = [ 100 (375301249367L, 92L, true); 101 (930412369850L, 36L, true); 102 ] in 103 List.iter (fun (input, checksum, expected) -> 104 let result = Crockford.validate input ~checksum in 105 let test_name = Printf.sprintf "validate %Ld checksum=%Ld" input checksum in 106 Alcotest.(check bool) test_name expected result 107 ) test_cases 108 109(* Additional roundtrip tests *) 110let test_roundtrip () = 111 let test_numbers = [ 112 0L; 113 1L; 114 32L; 115 1024L; 116 1234567890L; 117 Int64.max_int; 118 ] in 119 120 List.iter (fun num -> 121 let encoded = Crockford.encode num in 122 let decoded = Crockford.decode encoded in 123 Alcotest.(check int64) (Printf.sprintf "roundtrip %Ld" num) num decoded 124 ) test_numbers 125 126let test_roundtrip_with_checksum () = 127 let test_numbers = [ 128 0L; 129 1L; 130 32L; 131 1024L; 132 1234567890L; 133 ] in 134 135 List.iter (fun num -> 136 let encoded = Crockford.encode ~checksum:true num in 137 let decoded = Crockford.decode ~checksum:true encoded in 138 Alcotest.(check int64) (Printf.sprintf "roundtrip with checksum %Ld" num) num decoded 139 ) test_numbers 140 141(* Error handling tests *) 142let test_error_invalid_character () = 143 Alcotest.check_raises 144 "invalid character" 145 (Crockford.Decode_error (Crockford.Invalid_character { 146 char = '#'; 147 message = "character '#' not in base32 alphabet" 148 })) 149 (fun () -> ignore (Crockford.decode "abc#def")) 150 151let test_error_invalid_checksum () = 152 Alcotest.check_raises 153 "invalid checksum length" 154 (Crockford.Decode_error (Crockford.Invalid_checksum { 155 checksum = "ab"; 156 message = "encoded string too short for checksum" 157 })) 158 (fun () -> ignore (Crockford.decode ~checksum:true "ab")) 159 160let test_error_checksum_mismatch () = 161 let encoded = Crockford.encode ~checksum:true 1234L in 162 let corrupted = String.sub encoded 0 (String.length encoded - 2) ^ "00" in 163 164 Alcotest.check_raises 165 "checksum mismatch" 166 (Crockford.Decode_error (Crockford.Checksum_mismatch { 167 expected = Crockford.generate_checksum 1234L; 168 got = 0L; 169 identifier = corrupted 170 })) 171 (fun () -> ignore (Crockford.decode ~checksum:true corrupted)) 172 173let test_error_invalid_length () = 174 Alcotest.check_raises 175 "invalid length for generate" 176 (Crockford.Decode_error (Crockford.Invalid_length { 177 length = 2; 178 message = "length must be >= 3 if checksum is enabled" 179 })) 180 (fun () -> ignore (Crockford.generate ~length:2 ~checksum:true ())) 181 182let () = 183 let open Alcotest in 184 run "Crockford" [ 185 "encoding", [ 186 test_case "encode" `Quick test_encode; 187 ]; 188 "decoding", [ 189 test_case "decode" `Quick test_decode; 190 ]; 191 "normalization", [ 192 test_case "normalize" `Quick test_normalize; 193 ]; 194 "checksum", [ 195 test_case "generate_checksum" `Quick test_generate_checksum; 196 test_case "validate" `Quick test_validate; 197 ]; 198 "generation", [ 199 test_case "generate" `Quick test_generate; 200 ]; 201 "roundtrip", [ 202 test_case "roundtrip encoding/decoding" `Quick test_roundtrip; 203 test_case "roundtrip with checksum" `Quick test_roundtrip_with_checksum; 204 ]; 205 "errors", [ 206 test_case "invalid character" `Quick test_error_invalid_character; 207 test_case "invalid checksum" `Quick test_error_invalid_checksum; 208 test_case "checksum mismatch" `Quick test_error_checksum_mismatch; 209 test_case "invalid length" `Quick test_error_invalid_length; 210 ]; 211 ]