%% Copyright (c) 2000-2004, 2007 Tony Garnock-Jones %% %% Permission is hereby granted, free of charge, to any person obtaining a copy %% of this software and associated documentation files (the "Software"), to deal %% in the Software without restriction, including without limitation the rights %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell %% copies of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be included in %% all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% THE SOFTWARE. %% -module(ubf_a_tests). -export([test_all/0, quit_vm/0]). -define(UBF_MODULE, ubf_joe). -define(RUN_TEST(Fun), run_test(??Fun, fun () -> ok = Fun() end)). -define(RUN_OK_TEST(DoEncode, File, Value), run_test(File, fun () -> ok = file_ok_test(DoEncode, File, Value) end)). -define(RUN_FAIL_TEST(File), run_test(File, fun () -> ok = file_fail_test(File) end)). run_test(Name, Fun) -> io:format("Running test ~p...", [Name]), case catch Fun() of ok -> io:format("ok~n"), put(passed, [Name | get(passed)]), ok; Error -> io:format("FAILED~n~p~n", [Error]), put(failed, [Name | get(failed)]), failed end. ustr(X) -> {'#S', X}. test_all() -> put(passed, []), put(failed, []), ?RUN_OK_TEST(true, "ok:bigger-negative-integers", {-123, -234, -345}), ?RUN_OK_TEST(true, "ok:bizarre-tag-with-backquote", {'$TYPE',"a`b",[]}), ?RUN_OK_TEST(true, "ok:bizarre-tag-with-backslash", {'$TYPE',"a\\b",[]}), ?RUN_OK_TEST(true, "ok:comment-escaping", {123, 234}), ?RUN_OK_TEST(true, "ok:double-tag", {'$TYPE',"outer",{'$TYPE',"inner",[]}}), ?RUN_OK_TEST(true, "ok:empty-structure", {}), ?RUN_OK_TEST(true, "ok:ignore-comments", 123), ?RUN_OK_TEST(true, "ok:ignore-spaces", hi), ?RUN_OK_TEST(true, "ok:large-integer", 123456789123456789), ?RUN_OK_TEST(true, "ok:list", [a, b]), ?RUN_OK_TEST(true, "ok:list-of-lists", [[1], [2]]), ?RUN_OK_TEST(true, "ok:list-with-registers", [hello, hello, hello]), ?RUN_OK_TEST(true, "ok:negative-integer", -123), ?RUN_OK_TEST(true, "ok:negative-integers", {-1, -2, -3}), ?RUN_OK_TEST(true, "ok:register-allocation-sensible", {1, ustr("a"), 1, ustr("b"), 1, ustr("c"), 1, ustr("d"), 1}), ?RUN_OK_TEST(true, "ok:small-integer", 123), ?RUN_OK_TEST(true, "ok:string", ustr("a\"b")), ?RUN_OK_TEST(true, "ok:struct-of-structs", {a, {1}, b, {2}, c, {3}, d}), ?RUN_OK_TEST(true, "ok:struct-of-tagged-values", {{'$TYPE',"a",1},{'$TYPE',"b",2},{'$TYPE',"c",3}}), ?RUN_OK_TEST(true, "ok:structure-vector", {1, 2, 3}), ?RUN_OK_TEST(true, "ok:structure-with-registers", {hello, hello, hello}), ?RUN_OK_TEST(true, "ok:symbol", 'a\'b'), ?RUN_OK_TEST(true, "ok:tagged-structure", {'$TYPE',"tag",{1, 2, 3}}), ?RUN_OK_TEST(true, "ok:u8vector", <<"abc">>), ?RUN_FAIL_TEST("fail:binary-extra-data"), ?RUN_FAIL_TEST("fail:binary-missing-data"), ?RUN_FAIL_TEST("fail:early-end-of-stream"), ?RUN_FAIL_TEST("fail:early-end-of-string"), ?RUN_FAIL_TEST("fail:empty-stack-at-eom"), ?RUN_FAIL_TEST("fail:extra-close-struct"), ?RUN_FAIL_TEST("fail:non-empty-stack-at-eom"), ?RUN_FAIL_TEST("fail:non-integer-binary-data-length"), ?RUN_FAIL_TEST("fail:orphan-binary-data"), ?RUN_FAIL_TEST("fail:orphan-tag-inside-struct"), ?RUN_FAIL_TEST("fail:orphan-tag-outside-struct"), ?RUN_FAIL_TEST("fail:unhandled-ubf-a-opcode"), summarise(). quit_vm() -> receive after 250 -> ok end, halt(). summarise() -> P = get(passed), F = get(failed), Total = length(P) + length(F), io:format("~n"), io:format("===========================================================================~n"), io:format("~p tests run: ~p passed, ~p failed~n", [Total, length(P), length(F)]), case F of [] -> ok; _ -> io:format("Failures:~n"), lists:foreach(fun (Failed) -> io:format(" - ~p~n", [Failed]) end, lists:reverse(F)), ok end, io:format("===========================================================================~n"), ok. file_ok_test(DoEncode, File, Value) -> {ok, FileContentsBin} = file:read_file("../tests/encoding-tests/" ++ File), FileContents = binary_to_list(FileContentsBin), {done, Term, ""} = ?UBF_MODULE:decode(FileContents), {decoded_contents_match, Value, Value} = {decoded_contents_match, Term, Value}, case DoEncode of true -> {encoded_contents_match, FileContents} = {encoded_contents_match, ?UBF_MODULE:encode(Value)}, ok; false -> ok end. file_fail_test(File) -> {ok, FileContentsBin} = file:read_file("../tests/encoding-tests/" ++ File), FileContents = binary_to_list(FileContentsBin), case catch ?UBF_MODULE:decode(FileContents) of {'EXIT', _Reason} -> ok; Result -> % Deliberate mismatch: {unexpected_decode_return, Result} end.