-module(logic_upload_tests). -include_lib("eunit/include/eunit.hrl"). logic_upload_test_() -> {foreach, fun setup/0, fun cleanup/1, [ {"png avatar saves and serves path", fun test_png_avatar/0}, {"jpeg ok", fun test_jpeg/0}, {"webp ok", fun test_webp/0}, {"too large", fun test_too_large/0}, {"unsupported media", fun test_bad_media/0}, {"path traversal rejected", fun test_bad_path/0}, {"cover + delete old url", fun test_cover_and_delete/0} ]}. setup() -> Dir = "/tmp/eh-upload-test-" ++ integer_to_list(erlang:unique_integer([positive])), ok = filelib:ensure_dir(filename:join(Dir, "dummy")), application:set_env(eventhub, upload_dir, Dir), application:set_env(eventhub, upload_max_bytes, 1024), Dir. cleanup(Dir) -> application:unset_env(eventhub, upload_dir), application:unset_env(eventhub, upload_max_bytes), _ = os:cmd("rm -rf " ++ Dir), ok. png() -> <<137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 0>>. jpeg() -> <<16#FF, 16#D8, 16#FF, 16#E0, 0, 0>>. webp() -> <<"RIFF", 0, 0, 0, 0, "WEBP", 0, 0>>. test_png_avatar() -> UserId = <<"user1">>, {ok, Url} = logic_upload:save_avatar(UserId, png()), ?assertMatch(<<"/v1/media/avatar/user1/", _/binary>>, Url), <<"/v1/media/", Rest/binary>> = Url, [<<"avatar">>, <<"user1">>, File] = binary:split(Rest, <<"/">>, [global]), {ok, Path} = logic_upload:media_abs_path(avatar, UserId, File), {ok, Bin} = file:read_file(Path), ?assertEqual(png(), Bin). test_jpeg() -> {ok, Url} = logic_upload:save_avatar(<<"u">>, jpeg()), ?assert(binary:match(Url, <<".jpg">>) =/= nomatch). test_webp() -> {ok, Url} = logic_upload:save_cover(<<"cal1">>, <<"owner">>, webp()), ?assert(binary:match(Url, <<".webp">>) =/= nomatch), ?assertMatch(<<"/v1/media/cover/cal1/", _/binary>>, Url). test_too_large() -> Big = list_to_binary(lists:duplicate(2000, $x)), %% not a valid image either, but size checked first ?assertEqual({error, too_large}, logic_upload:save_avatar(<<"u">>, Big)). test_bad_media() -> ?assertEqual({error, unsupported_media}, logic_upload:save_avatar(<<"u">>, <<"not-an-image">>)). test_bad_path() -> ?assertEqual({error, invalid}, logic_upload:media_abs_path(avatar, <<"../x">>, <<"a.jpg">>)), ?assertEqual({error, invalid}, logic_upload:media_abs_path(avatar, <<"u">>, <<"../a.jpg">>)). test_cover_and_delete() -> {ok, Url1} = logic_upload:save_cover(<<"c">>, <<"o">>, png()), <<"/v1/media/", Rest/binary>> = Url1, [<<"cover">>, <<"c">>, File] = binary:split(Rest, <<"/">>, [global]), {ok, Path} = logic_upload:media_abs_path(cover, <<"c">>, File), ?assert(filelib:is_regular(Path)), ok = logic_upload:maybe_delete_url(Url1), ?assertNot(filelib:is_regular(Path)).