Files
n8n-openai-adapter/lib/elixir/test/elixir/base_test.exs
T
José Valim 5f4b38c748 Make Base encoding/decoding 100%/25% faster respectively
decode16, in particular, is 50% faster, as we don't need to
handle padding.

We also reduce the .beam size from 330kb to 80kb.

This is achieved by building look tables, as described in
https://www.erlang.org/blog/type-based-optimizations-in-the-jit/

For decoding, we build a sparse lookup table with nils in it.
The tables are still small (less than 80 elements) and we have
to check for nils, but that's more efficient than the previous
approach as well.

The code is also simpler, as we rely less on macros
and more on dynamic code generation.

Closes #11866.
2022-06-19 16:15:29 +02:00

823 lines
25 KiB
Elixir

Code.require_file("test_helper.exs", __DIR__)
defmodule BaseTest do
use ExUnit.Case, async: true
doctest Base
import Base
test "encode16/1" do
assert "" == encode16("")
assert "66" == encode16("f")
assert "666F" == encode16("fo")
assert "666F6F" == encode16("foo")
assert "666F6F62" == encode16("foob")
assert "666F6F6261" == encode16("fooba")
assert "666F6F626172" == encode16("foobar")
assert "A1B2C3D4E5F67891" == encode16(<<161, 178, 195, 212, 229, 246, 120, 145>>)
assert "a1b2c3d4e5f67891" ==
encode16(<<161, 178, 195, 212, 229, 246, 120, 145>>, case: :lower)
end
test "decode16/1" do
assert {:ok, ""} == decode16("")
assert {:ok, "f"} == decode16("66")
assert {:ok, "fo"} == decode16("666F")
assert {:ok, "foo"} == decode16("666F6F")
assert {:ok, "foob"} == decode16("666F6F62")
assert {:ok, "fooba"} == decode16("666F6F6261")
assert {:ok, "foobar"} == decode16("666F6F626172")
assert {:ok, <<161, 178, 195, 212, 229, 246, 120, 145>>} == decode16("A1B2C3D4E5F67891")
assert {:ok, <<161, 178, 195, 212, 229, 246, 120, 145>>} ==
decode16("a1b2c3d4e5f67891", case: :lower)
assert {:ok, <<161, 178, 195, 212, 229, 246, 120, 145>>} ==
decode16("a1B2c3D4e5F67891", case: :mixed)
end
test "decode16!/1" do
assert "" == decode16!("")
assert "f" == decode16!("66")
assert "fo" == decode16!("666F")
assert "foo" == decode16!("666F6F")
assert "foob" == decode16!("666F6F62")
assert "fooba" == decode16!("666F6F6261")
assert "foobar" == decode16!("666F6F626172")
assert <<161, 178, 195, 212, 229, 246, 120, 145>> == decode16!("A1B2C3D4E5F67891")
assert <<161, 178, 195, 212, 229, 246, 120, 145>> ==
decode16!("a1b2c3d4e5f67891", case: :lower)
assert <<161, 178, 195, 212, 229, 246, 120, 145>> ==
decode16!("a1B2c3D4e5F67891", case: :mixed)
end
test "decode16/1 errors on non-alphabet character" do
assert :error == decode16("66KF")
assert :error == decode16("66ff")
assert :error == decode16("66FF", case: :lower)
end
test "decode16!/1 errors on non-alphabet character" do
assert_raise ArgumentError, "non-alphabet character found: \"K\" (byte 75)", fn ->
decode16!("66KF")
end
assert_raise ArgumentError, "non-alphabet character found: \"f\" (byte 102)", fn ->
decode16!("66ff")
end
assert_raise ArgumentError, "non-alphabet character found: \"F\" (byte 70)", fn ->
decode16!("66FF", case: :lower)
end
end
test "decode16/1 errors on odd-length string" do
assert :error == decode16("666")
end
test "decode16!/1 errors odd-length string" do
assert_raise ArgumentError, ~r/string given to decode has wrong length/, fn ->
decode16!("666")
end
end
test "encode64/1 can deal with empty strings" do
assert "" == encode64("")
end
test "encode64/1 with two pads" do
assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ==" == encode64("Aladdin:open sesame")
end
test "encode64/1 with one pad" do
assert "SGVsbG8gV29ybGQ=" == encode64("Hello World")
end
test "encode64/1 with no pad" do
assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == encode64("Aladdin:open sesam")
assert "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" ==
encode64(<<"0123456789!@#0^&*();:<>,. []{}">>)
end
test "encode64/1 with one pad and ignoring padding" do
assert "SGVsbG8gV29ybGQ" == encode64("Hello World", padding: false)
end
test "encode64/1 with two pads and ignoring padding" do
assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ" == encode64("Aladdin:open sesame", padding: false)
end
test "encode64/1 with no pads and ignoring padding" do
assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == encode64("Aladdin:open sesam", padding: false)
end
test "decode64/1 can deal with empty strings" do
assert {:ok, ""} == decode64("")
end
test "decode64!/1 can deal with empty strings" do
assert "" == decode64!("")
end
test "decode64/1 with two pads" do
assert {:ok, "Aladdin:open sesame"} == decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ==")
end
test "decode64!/1 with two pads" do
assert "Aladdin:open sesame" == decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ==")
end
test "decode64/1 with one pad" do
assert {:ok, "Hello World"} == decode64("SGVsbG8gV29ybGQ=")
end
test "decode64!/1 with one pad" do
assert "Hello World" == decode64!("SGVsbG8gV29ybGQ=")
end
test "decode64/1 with no pad" do
assert {:ok, "Aladdin:open sesam"} == decode64("QWxhZGRpbjpvcGVuIHNlc2Ft")
end
test "decode64!/1 with no pad" do
assert "Aladdin:open sesam" == decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft")
end
test "decode64/1 errors on non-alphabet character" do
assert :error == decode64("Zm9)")
end
test "decode64!/1 errors on non-alphabet character" do
assert_raise ArgumentError, "non-alphabet character found: \")\" (byte 41)", fn ->
decode64!("Zm9)")
end
end
test "decode64/1 errors on whitespace unless there's ignore: :whitespace" do
assert :error == decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
assert {:ok, "Aladdin:open sesam"} ==
decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "decode64!/1 errors on whitespace unless there's ignore: :whitespace" do
assert_raise ArgumentError, "non-alphabet character found: \"\\n\" (byte 10)", fn ->
decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
end
assert "Aladdin:open sesam" ==
decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "decode64/1 errors on incorrect padding" do
assert :error == decode64("SGVsbG8gV29ybGQ")
end
test "decode64!/1 errors on incorrect padding" do
assert_raise ArgumentError, "incorrect padding", fn ->
decode64!("SGVsbG8gV29ybGQ")
end
end
test "decode64/2 with two pads and ignoring padding" do
assert {:ok, "Aladdin:open sesame"} == decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "decode64!/2 with two pads and ignoring padding" do
assert "Aladdin:open sesame" == decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "decode64/2 with one pad and ignoring padding" do
assert {:ok, "Hello World"} == decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "decode64!/2 with one pad and ignoring padding" do
assert "Hello World" == decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "decode64/2 with no pad and ignoring padding" do
assert {:ok, "Aladdin:open sesam"} == decode64("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "decode64!/2 with no pad and ignoring padding" do
assert "Aladdin:open sesam" == decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "decode64/2 with incorrect padding and ignoring padding" do
assert {:ok, "Hello World"} == decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "decode64!/2 with incorrect padding and ignoring padding" do
assert "Hello World" == decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "url_encode64/1 can deal with empty strings" do
assert "" == url_encode64("")
end
test "url_encode64/1 with two pads" do
assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ==" == url_encode64("Aladdin:open sesame")
end
test "url_encode64/1 with one pad" do
assert "SGVsbG8gV29ybGQ=" == url_encode64("Hello World")
end
test "url_encode64/1 with no pad" do
assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == url_encode64("Aladdin:open sesam")
assert "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" ==
url_encode64(<<"0123456789!@#0^&*();:<>,. []{}">>)
end
test "url_encode64/2 with two pads and ignoring padding" do
assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ" == url_encode64("Aladdin:open sesame", padding: false)
end
test "url_encode64/2 with one pad and ignoring padding" do
assert "SGVsbG8gV29ybGQ" == url_encode64("Hello World", padding: false)
end
test "url_encode64/2 with no pad and ignoring padding" do
assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == url_encode64("Aladdin:open sesam", padding: false)
end
test "url_encode64/1 doesn't produce URL-unsafe characters" do
refute "/3/+/A==" == url_encode64(<<255, 127, 254, 252>>)
assert "_3_-_A==" == url_encode64(<<255, 127, 254, 252>>)
end
test "url_decode64/1 can deal with empty strings" do
assert {:ok, ""} == url_decode64("")
end
test "url_decode64!/1 can deal with empty strings" do
assert "" == url_decode64!("")
end
test "url_decode64/1 with two pads" do
assert {:ok, "Aladdin:open sesame"} == url_decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ==")
end
test "url_decode64!/1 with two pads" do
assert "Aladdin:open sesame" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ==")
end
test "url_decode64/1 with one pad" do
assert {:ok, "Hello World"} == url_decode64("SGVsbG8gV29ybGQ=")
end
test "url_decode64!/1 with one pad" do
assert "Hello World" == url_decode64!("SGVsbG8gV29ybGQ=")
end
test "url_decode64/1 with no pad" do
assert {:ok, "Aladdin:open sesam"} == url_decode64("QWxhZGRpbjpvcGVuIHNlc2Ft")
end
test "url_decode64!/1 with no pad" do
assert "Aladdin:open sesam" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft")
end
test "url_decode64/1,2 error on whitespace unless there's ignore: :whitespace" do
assert :error == url_decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
assert {:ok, "Aladdin:open sesam"} ==
url_decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "url_decode64!/1,2 error on whitespace unless there's ignore: :whitespace" do
assert_raise ArgumentError, "non-alphabet character found: \"\\n\" (byte 10)", fn ->
url_decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
end
assert "Aladdin:open sesam" ==
url_decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "url_decode64/1 errors on non-alphabet character" do
assert :error == url_decode64("Zm9)")
end
test "url_decode64!/1 errors on non-alphabet character" do
assert_raise ArgumentError, "non-alphabet character found: \")\" (byte 41)", fn ->
url_decode64!("Zm9)")
end
end
test "url_decode64/1 errors on incorrect padding" do
assert :error == url_decode64("SGVsbG8gV29ybGQ")
end
test "url_decode64!/1 errors on incorrect padding" do
assert_raise ArgumentError, "incorrect padding", fn ->
url_decode64!("SGVsbG8gV29ybGQ")
end
end
test "url_decode64/2 with two pads and ignoring padding" do
assert {:ok, "Aladdin:open sesame"} ==
url_decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "url_decode64!/2 with two pads and ignoring padding" do
assert "Aladdin:open sesame" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "url_decode64/2 with one pad and ignoring padding" do
assert {:ok, "Hello World"} == url_decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "url_decode64!/2 with one pad and ignoring padding" do
assert "Hello World" == url_decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "url_decode64/2 with no pad and ignoring padding" do
assert {:ok, "Aladdin:open sesam"} == url_decode64("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "url_decode64!/2 with no pad and ignoring padding" do
assert "Aladdin:open sesam" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "url_decode64/2 ignores incorrect padding when :padding is false" do
assert {:ok, "Hello World"} == url_decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "url_decode64!/2 ignores incorrect padding when :padding is false" do
assert "Hello World" == url_decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "encode32/1 can deal with empty strings" do
assert "" == encode32("")
end
test "encode32/1 with one pad" do
assert "MZXW6YQ=" == encode32("foob")
end
test "encode32/1 with three pads" do
assert "MZXW6===" == encode32("foo")
end
test "encode32/1 with four pads" do
assert "MZXQ====" == encode32("fo")
end
test "encode32/1 with six pads" do
assert "MZXW6YTBOI======" == encode32("foobar")
assert "MY======" == encode32("f")
end
test "encode32/1 with no pads" do
assert "MZXW6YTB" == encode32("fooba")
end
test "encode32/2 with one pad and ignoring padding" do
assert "MZXW6YQ" == encode32("foob", padding: false)
end
test "encode32/2 with three pads and ignoring padding" do
assert "MZXW6" == encode32("foo", padding: false)
end
test "encode32/2 with four pads and ignoring padding" do
assert "MZXQ" == encode32("fo", padding: false)
end
test "encode32/2 with six pads and ignoring padding" do
assert "MZXW6YTBOI" == encode32("foobar", padding: false)
end
test "encode32/2 with no pads and ignoring padding" do
assert "MZXW6YTB" == encode32("fooba", padding: false)
end
test "encode32/2 with lowercase" do
assert "mzxw6ytb" == encode32("fooba", case: :lower)
end
test "decode32/1 can deal with empty strings" do
assert {:ok, ""} == decode32("")
end
test "decode32!/2 can deal with empty strings" do
assert "" == decode32!("")
end
test "decode32/1 with one pad" do
assert {:ok, "foob"} == decode32("MZXW6YQ=")
end
test "decode32!/1 with one pad" do
assert "foob" == decode32!("MZXW6YQ=")
end
test "decode32/1 with three pads" do
assert {:ok, "foo"} == decode32("MZXW6===")
end
test "decode32!/1 with three pads" do
assert "foo" == decode32!("MZXW6===")
end
test "decode32/1 with four pads" do
assert {:ok, "fo"} == decode32("MZXQ====")
end
test "decode32!/1 with four pads" do
assert "fo" == decode32!("MZXQ====")
end
test "decode32/2 with lowercase" do
assert {:ok, "fo"} == decode32("mzxq====", case: :lower)
end
test "decode32!/2 with lowercase" do
assert "fo" == decode32!("mzxq====", case: :lower)
end
test "decode32/2 with mixed case" do
assert {:ok, "fo"} == decode32("mZXq====", case: :mixed)
end
test "decode32!/2 with mixed case" do
assert "fo" == decode32!("mZXq====", case: :mixed)
end
test "decode32/1 with six pads" do
assert {:ok, "foobar"} == decode32("MZXW6YTBOI======")
assert {:ok, "f"} == decode32("MY======")
end
test "decode32!/1 with six pads" do
assert "foobar" == decode32!("MZXW6YTBOI======")
assert "f" == decode32!("MY======")
end
test "decode32/1 with no pads" do
assert {:ok, "fooba"} == decode32("MZXW6YTB")
end
test "decode32!/1 with no pads" do
assert "fooba" == decode32!("MZXW6YTB")
end
test "decode32/1,2 error on non-alphabet character" do
assert :error == decode32("MZX)6YTB")
assert :error == decode32("66ff")
assert :error == decode32("66FF", case: :lower)
end
test "decode32!/1,2 argument error on non-alphabet character" do
assert_raise ArgumentError, "non-alphabet character found: \")\" (byte 41)", fn ->
decode32!("MZX)6YTB")
end
assert_raise ArgumentError, "non-alphabet character found: \"m\" (byte 109)", fn ->
decode32!("mzxw6ytboi======")
end
assert_raise ArgumentError, "non-alphabet character found: \"M\" (byte 77)", fn ->
decode32!("MZXW6YTBOI======", case: :lower)
end
assert_raise ArgumentError, "non-alphabet character found: \"0\" (byte 48)", fn ->
decode32!("0ZXW6YTB0I======", case: :mixed)
end
end
test "decode32/1 errors on incorrect padding" do
assert :error == decode32("MZXW6YQ")
end
test "decode32!/1 errors on incorrect padding" do
assert_raise ArgumentError, "incorrect padding", fn ->
decode32!("MZXW6YQ")
end
end
test "decode32/2 with one pad and :padding to false" do
assert {:ok, "foob"} == decode32("MZXW6YQ", padding: false)
end
test "decode32!/2 with one pad and :padding to false" do
assert "foob" == decode32!("MZXW6YQ", padding: false)
end
test "decode32/2 with three pads and ignoring padding" do
assert {:ok, "foo"} == decode32("MZXW6", padding: false)
end
test "decode32!/2 with three pads and ignoring padding" do
assert "foo" == decode32!("MZXW6", padding: false)
end
test "decode32/2 with four pads and ignoring padding" do
assert {:ok, "fo"} == decode32("MZXQ", padding: false)
end
test "decode32!/2 with four pads and ignoring padding" do
assert "fo" == decode32!("MZXQ", padding: false)
end
test "decode32/2 with :lower case and ignoring padding" do
assert {:ok, "fo"} == decode32("mzxq", case: :lower, padding: false)
end
test "decode32!/2 with :lower case and ignoring padding" do
assert "fo" == decode32!("mzxq", case: :lower, padding: false)
end
test "decode32/2 with :mixed case and ignoring padding" do
assert {:ok, "fo"} == decode32("mZXq", case: :mixed, padding: false)
end
test "decode32!/2 with :mixed case and ignoring padding" do
assert "fo" == decode32!("mZXq", case: :mixed, padding: false)
end
test "decode32/2 with six pads and ignoring padding" do
assert {:ok, "foobar"} == decode32("MZXW6YTBOI", padding: false)
end
test "decode32!/2 with six pads and ignoring padding" do
assert "foobar" == decode32!("MZXW6YTBOI", padding: false)
end
test "decode32/2 with no pads and ignoring padding" do
assert {:ok, "fooba"} == decode32("MZXW6YTB", padding: false)
end
test "decode32!/2 with no pads and ignoring padding" do
assert "fooba" == decode32!("MZXW6YTB", padding: false)
end
test "decode32/2 ignores incorrect padding when :padding is false" do
assert {:ok, "foob"} == decode32("MZXW6YQ", padding: false)
end
test "decode32!/2 ignores incorrect padding when :padding is false" do
"foob" = decode32!("MZXW6YQ", padding: false)
end
test "hex_encode32/1 can deal with empty strings" do
assert "" == hex_encode32("")
end
test "hex_encode32/1 with one pad" do
assert "CPNMUOG=" == hex_encode32("foob")
end
test "hex_encode32/1 with three pads" do
assert "CPNMU===" == hex_encode32("foo")
end
test "hex_encode32/1 with four pads" do
assert "CPNG====" == hex_encode32("fo")
end
test "hex_encode32/1 with six pads" do
assert "CPNMUOJ1E8======" == hex_encode32("foobar")
assert "CO======" == hex_encode32("f")
end
test "hex_encode32/1 with no pads" do
assert "CPNMUOJ1" == hex_encode32("fooba")
end
test "hex_encode32/2 with one pad and ignoring padding" do
assert "CPNMUOG" == hex_encode32("foob", padding: false)
end
test "hex_encode32/2 with three pads and ignoring padding" do
assert "CPNMU" == hex_encode32("foo", padding: false)
end
test "hex_encode32/2 with four pads and ignoring padding" do
assert "CPNG" == hex_encode32("fo", padding: false)
end
test "hex_encode32/2 with six pads and ignoring padding" do
assert "CPNMUOJ1E8" == hex_encode32("foobar", padding: false)
end
test "hex_encode32/2 with no pads and ignoring padding" do
assert "CPNMUOJ1" == hex_encode32("fooba", padding: false)
end
test "hex_encode32/2 with lowercase" do
assert "cpnmuoj1" == hex_encode32("fooba", case: :lower)
end
test "hex_decode32/1 can deal with empty strings" do
assert {:ok, ""} == hex_decode32("")
end
test "hex_decode32!/1 can deal with empty strings" do
assert "" == hex_decode32!("")
end
test "hex_decode32/1 with one pad" do
assert {:ok, "foob"} == hex_decode32("CPNMUOG=")
end
test "hex_decode32!/1 with one pad" do
assert "foob" == hex_decode32!("CPNMUOG=")
end
test "hex_decode32/1 with three pads" do
assert {:ok, "foo"} == hex_decode32("CPNMU===")
end
test "hex_decode32!/1 with three pads" do
assert "foo" == hex_decode32!("CPNMU===")
end
test "hex_decode32/1 with four pads" do
assert {:ok, "fo"} == hex_decode32("CPNG====")
end
test "hex_decode32!/1 with four pads" do
assert "fo" == hex_decode32!("CPNG====")
end
test "hex_decode32/1 with six pads" do
assert {:ok, "foobar"} == hex_decode32("CPNMUOJ1E8======")
assert {:ok, "f"} == hex_decode32("CO======")
end
test "hex_decode32!/1 with six pads" do
assert "foobar" == hex_decode32!("CPNMUOJ1E8======")
assert "f" == hex_decode32!("CO======")
end
test "hex_decode32/1 with no pads" do
assert {:ok, "fooba"} == hex_decode32("CPNMUOJ1")
end
test "hex_decode32!/1 with no pads" do
assert "fooba" == hex_decode32!("CPNMUOJ1")
end
test "hex_decode32/1,2 error on non-alphabet character" do
assert :error == hex_decode32("CPN)UOJ1")
assert :error == hex_decode32("66f")
assert :error == hex_decode32("66F", case: :lower)
end
test "hex_decode32!/1,2 error non-alphabet character" do
assert_raise ArgumentError, "non-alphabet character found: \")\" (byte 41)", fn ->
hex_decode32!("CPN)UOJ1")
end
assert_raise ArgumentError, "non-alphabet character found: \"c\" (byte 99)", fn ->
hex_decode32!("cpnmuoj1e8======")
end
assert_raise ArgumentError, "non-alphabet character found: \"C\" (byte 67)", fn ->
hex_decode32!("CPNMUOJ1E8======", case: :lower)
end
end
test "hex_decode32/1 errors on incorrect padding" do
assert :error == hex_decode32("CPNMUOG")
end
test "hex_decode32!/1 errors on incorrect padding" do
assert_raise ArgumentError, "incorrect padding", fn ->
hex_decode32!("CPNMUOG")
end
end
test "hex_decode32/2 with lowercase" do
assert {:ok, "fo"} == hex_decode32("cpng====", case: :lower)
end
test "hex_decode32!/2 with lowercase" do
assert "fo" == hex_decode32!("cpng====", case: :lower)
end
test "hex_decode32/2 with mixed case" do
assert {:ok, "fo"} == hex_decode32("cPNg====", case: :mixed)
end
test "hex_decode32!/2 with mixed case" do
assert "fo" == hex_decode32!("cPNg====", case: :mixed)
end
test "decode16!/1 errors on non-UTF-8 char" do
assert_raise ArgumentError, "non-alphabet character found: \"\\0\" (byte 0)", fn ->
decode16!("012" <> <<0>>)
end
end
test "hex_decode32/2 with one pad and ignoring padding" do
assert {:ok, "foob"} == hex_decode32("CPNMUOG", padding: false)
end
test "hex_decode32!/2 with one pad and ignoring padding" do
assert "foob" == hex_decode32!("CPNMUOG", padding: false)
end
test "hex_decode32/2 with three pads and ignoring padding" do
assert {:ok, "foo"} == hex_decode32("CPNMU", padding: false)
end
test "hex_decode32!/2 with three pads and ignoring padding" do
assert "foo" == hex_decode32!("CPNMU", padding: false)
end
test "hex_decode32/2 with four pads and ignoring padding" do
assert {:ok, "fo"} == hex_decode32("CPNG", padding: false)
end
test "hex_decode32!/2 with four pads and ignoring padding" do
assert "fo" == hex_decode32!("CPNG", padding: false)
end
test "hex_decode32/2 with six pads and ignoring padding" do
assert {:ok, "foobar"} == hex_decode32("CPNMUOJ1E8", padding: false)
end
test "hex_decode32!/2 with six pads and ignoring padding" do
assert "foobar" == hex_decode32!("CPNMUOJ1E8", padding: false)
end
test "hex_decode32/2 with no pads and ignoring padding" do
assert {:ok, "fooba"} == hex_decode32("CPNMUOJ1", padding: false)
end
test "hex_decode32!/2 with no pads and ignoring padding" do
assert "fooba" == hex_decode32!("CPNMUOJ1", padding: false)
end
test "hex_decode32/2 ignores incorrect padding when :padding is false" do
assert {:ok, "foob"} == hex_decode32("CPNMUOG", padding: false)
end
test "hex_decode32!/2 ignores incorrect padding when :padding is false" do
"foob" = hex_decode32!("CPNMUOG", padding: false)
end
test "hex_decode32/2 with :lower case and ignoring padding" do
assert {:ok, "fo"} == hex_decode32("cpng", case: :lower, padding: false)
end
test "hex_decode32!/2 with :lower case and ignoring padding" do
assert "fo" == hex_decode32!("cpng", case: :lower, padding: false)
end
test "hex_decode32/2 with :mixed case and ignoring padding" do
assert {:ok, "fo"} == hex_decode32("cPNg====", case: :mixed, padding: false)
end
test "hex_decode32!/2 with :mixed case and ignoring padding" do
assert "fo" == hex_decode32!("cPNg", case: :mixed, padding: false)
end
test "encode then decode is identity" do
for {encode, decode} <- [
{&encode16/2, &decode16!/2},
{&encode32/2, &decode32!/2},
{&hex_encode32/2, &hex_decode32!/2},
{&encode64/2, &decode64!/2},
{&url_encode64/2, &url_decode64!/2}
],
encode_case <- [:upper, :lower],
decode_case <- [:upper, :lower, :mixed],
encode_case == decode_case or decode_case == :mixed,
pad? <- [true, false],
len <- 0..256 do
data =
0
|> :lists.seq(len - 1)
|> Enum.shuffle()
|> IO.iodata_to_binary()
allowed_opts =
encode
|> Function.info()
|> Keyword.fetch!(:name)
|> case do
:encode16 -> [:case]
:encode64 -> [:padding]
:url_encode64 -> [:padding]
_ -> [:case, :padding]
end
expected =
data
|> encode.(Keyword.take([case: encode_case, padding: pad?], allowed_opts))
|> decode.(Keyword.take([case: decode_case, padding: pad?], allowed_opts))
assert data == expected,
"identity did not match for #{inspect(data)} when #{inspect(encode)} (#{encode_case})"
end
end
end