diff options
Diffstat (limited to 'tests/core/encoding')
| -rw-r--r-- | tests/core/encoding/base32/base32.odin | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/tests/core/encoding/base32/base32.odin b/tests/core/encoding/base32/base32.odin new file mode 100644 index 000000000..f757e99e5 --- /dev/null +++ b/tests/core/encoding/base32/base32.odin @@ -0,0 +1,231 @@ +#+test +package test_encoding_base32 + +import "core:testing" +import "core:bytes" +import "core:encoding/base32" + +Error :: base32.Error + +@(test) +test_base32_decode_valid :: proc(t: ^testing.T) { + // RFC 4648 Section 10 - Test vectors + cases := [?]struct { + input, expected: string, + }{ + {"", ""}, + {"MY======", "f"}, + {"MZXQ====", "fo"}, + {"MZXW6===", "foo"}, + {"MZXW6YQ=", "foob"}, + {"MZXW6YTB", "fooba"}, + {"MZXW6YTBOI======", "foobar"}, + } + + for c in cases { + output, err := base32.decode(c.input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.None) + expected := transmute([]u8)c.expected + if output != nil { + testing.expect(t, bytes.equal(output, expected)) + } else { + testing.expect(t, len(c.expected) == 0) + } + } +} + +@(test) +test_base32_encode :: proc(t: ^testing.T) { + // RFC 4648 Section 10 - Test vectors + cases := [?]struct { + input, expected: string, + }{ + {"", ""}, + {"f", "MY======"}, + {"fo", "MZXQ===="}, + {"foo", "MZXW6==="}, + {"foob", "MZXW6YQ="}, + {"fooba", "MZXW6YTB"}, + {"foobar", "MZXW6YTBOI======"}, + } + + for c in cases { + output := base32.encode(transmute([]byte)c.input) + defer delete(output) + testing.expect(t, output == c.expected) + } +} + +@(test) +test_base32_decode_invalid :: proc(t: ^testing.T) { + // Section 3.3 - Non-alphabet characters + { + // Characters outside alphabet + input := "MZ1W6YTB" // '1' not in alphabet (A-Z, 2-7) + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Invalid_Character) + } + { + // Lowercase not allowed + input := "mzxq====" + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Invalid_Character) + } + + // Section 3.2 - Padding requirements + { + // Padding must only be at end + input := "MZ=Q====" + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Malformed_Input) + } + { + // Missing padding + input := "MZXQ" // Should be MZXQ==== + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Malformed_Input) + } + { + // Incorrect padding length + input := "MZXQ=" // Needs 4 padding chars + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Malformed_Input) + } + { + // Too much padding + input := "MY=========" // Extra padding chars + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Malformed_Input) + } + + // Section 6 - Base32 block size requirements + { + // Single character (invalid block) + input := "M" + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Invalid_Length) + } +} + +@(test) +test_base32_roundtrip :: proc(t: ^testing.T) { + cases := [?]string{ + "", + "f", + "fo", + "foo", + "foob", + "fooba", + "foobar", + } + + for input in cases { + encoded := base32.encode(transmute([]byte)input) + defer delete(encoded) + decoded, err := base32.decode(encoded) + if decoded != nil { + defer delete(decoded) + } + testing.expect_value(t, err, Error.None) + testing.expect(t, bytes.equal(decoded, transmute([]byte)input)) + } +} + +@(test) +test_base32_custom_alphabet :: proc(t: ^testing.T) { + custom_enc_table := [32]byte{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + } + + custom_dec_table: [256]u8 + for i := 0; i < len(custom_enc_table); i += 1 { + custom_dec_table[custom_enc_table[i]] = u8(i) + } + + /* + custom_dec_table := [256]u8{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00-0x0f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10-0x1f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20-0x2f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // 0x30-0x3f ('0'-'9') + 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f ('A'-'O') + 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50-0x5f ('P'-'V') + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60-0x6f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70-0x7f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80-0x8f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90-0x9f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0-0xaf + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0-0xbf + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0-0xcf + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0-0xdf + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0-0xef + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0-0xff + } + */ + + custom_validate :: proc(c: byte) -> bool { + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'V') || c == byte(base32.PADDING) + } + + cases := [?]struct { + input: string, + enc_expected: string, + }{ + {"f", "CO======"}, + {"fo", "CPNG===="}, + {"foo", "CPNMU==="}, + } + + for c in cases { + // Test encoding + encoded := base32.encode(transmute([]byte)c.input, custom_enc_table) + defer delete(encoded) + testing.expect(t, encoded == c.enc_expected) + + // Test decoding + decoded, err := base32.decode(encoded, custom_dec_table, custom_validate) + defer if decoded != nil { + delete(decoded) + } + + testing.expect_value(t, err, Error.None) + testing.expect(t, bytes.equal(decoded, transmute([]byte)c.input)) + } + + // Test invalid character detection + { + input := "WXY=====" // Contains chars not in our alphabet + output, err := base32.decode(input, custom_dec_table, custom_validate) + if output != nil { + delete(output) + } + testing.expect_value(t, err, Error.Invalid_Character) + } +}
\ No newline at end of file |