diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/mock_pkg_resource.erl | 11 | ||||
-rw-r--r-- | test/rebar_pkg_SUITE.erl | 207 | ||||
-rw-r--r-- | test/rebar_pkg_SUITE_data/badindexchk-1.0.0.tar | bin | 0 -> 10240 bytes | |||
-rw-r--r-- | test/rebar_pkg_SUITE_data/badpkg-1.0.0.tar | bin | 0 -> 10240 bytes | |||
-rw-r--r-- | test/rebar_pkg_SUITE_data/goodpkg-1.0.0.tar | bin | 0 -> 10240 bytes |
5 files changed, 215 insertions, 3 deletions
diff --git a/test/mock_pkg_resource.erl b/test/mock_pkg_resource.erl index 560caef..e94ea93 100644 --- a/test/mock_pkg_resource.erl +++ b/test/mock_pkg_resource.erl @@ -16,6 +16,7 @@ mock() -> mock([]). -spec mock(Opts) -> ok when Opts :: [Option], Option :: {update, [App]} + | {cache_dir, string()} | {default_vsn, Vsn} | {override_vsn, [{App, Vsn}]} | {not_in_index, [{App, Vsn}]} @@ -83,7 +84,8 @@ mock_download(Opts) -> [kernel, stdlib] ++ [element(1,D) || D <- AppDeps] ), rebar_test_utils:create_config(Dir, [{deps, AppDeps}]), - Tarball = filename:join([Dir, App++"-"++binary_to_list(Vsn)++".tar"]), + TarApp = App++"-"++binary_to_list(Vsn)++".tar", + Tarball = filename:join([Dir, TarApp]), Contents = filename:join([Dir, "contents.tar.gz"]), Files = all_files(rebar_app_info:dir(AppInfo)), ok = erl_tar:create(Contents, @@ -92,8 +94,11 @@ mock_download(Opts) -> ok = erl_tar:create(Tarball, [{"contents.tar.gz", Contents}], []), - [file:delete(F) || F <- Files], - {tarball, Tarball} + Cache = proplists:get_value(cache_dir, Opts, filename:join(Dir,"cache")), + Cached = filename:join([Cache, TarApp]), + filelib:ensure_dir(Cached), + rebar_file_utils:mv(Tarball, Cached), + {ok, true} end). %% @doc On top of the pkg resource mocking, we need to mock the package diff --git a/test/rebar_pkg_SUITE.erl b/test/rebar_pkg_SUITE.erl new file mode 100644 index 0000000..95eb6f6 --- /dev/null +++ b/test/rebar_pkg_SUITE.erl @@ -0,0 +1,207 @@ +%% Test suite for the rebar pkg index caching and decompression +%% mechanisms. +-module(rebar_pkg_SUITE). +-compile(export_all). +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-define(bad_etag, "abcdef"). +-define(good_etag, "22e1d7387c9085a462340088a2a8ba67"). +-define(bad_checksum, <<"D576B442A68C7B92BACDE1EFE9C6E54D8D6C74BDB71D8175B9D3C6EC8C7B62A7">>). +-define(good_checksum, <<"1C6CE379D191FBAB41B7905075E0BF87CBBE23C77CECE775C5A0B786B2244C35">>). + +all() -> [good_uncached, good_cached, badindexchk, badpkg, + bad_to_good, good_disconnect, bad_disconnect]. + +init_per_suite(Config) -> + application:start(meck), + Config. + +end_per_suite(_Config) -> + application:stop(meck). + +init_per_testcase(good_uncached=Name, Config0) -> + Config = [{good_cache, false}, + {pkg, {<<"goodpkg">>, <<"1.0.0">>}} + | Config0], + mock_config(Name, Config); +init_per_testcase(good_cached=Name, Config0) -> + Pkg = {<<"goodpkg">>, <<"1.0.0">>}, + Config1 = [{good_cache, true}, + {pkg, Pkg} + | Config0], + Config = mock_config(Name, Config1), + copy_to_cache(Pkg, Config), + Config; +init_per_testcase(badindexchk=Name, Config0) -> + Config = [{good_cache, false}, + {pkg, {<<"badindexchk">>, <<"1.0.0">>}} + | Config0], + mock_config(Name, Config); +init_per_testcase(badpkg=Name, Config0) -> + Config = [{good_cache, false}, + {pkg, {<<"badpkg">>, <<"1.0.0">>}} + | Config0], + mock_config(Name, Config); +init_per_testcase(bad_to_good=Name, Config0) -> + Config1 = [{good_cache, false}, + {pkg, {<<"goodpkg">>, <<"1.0.0">>}} + | Config0], + Config = mock_config(Name, Config1), + Source = filename:join(?config(data_dir, Config), <<"badpkg-1.0.0.tar">>), + Dest = filename:join(?config(cache_dir, Config), <<"goodpkg-1.0.0.tar">>), + ec_file:copy(Source, Dest), + Config; +init_per_testcase(good_disconnect=Name, Config0) -> + Pkg = {<<"goodpkg">>, <<"1.0.0">>}, + Config1 = [{good_cache, true}, + {pkg, Pkg} + | Config0], + Config = mock_config(Name, Config1), + copy_to_cache(Pkg, Config), + meck:unload(httpc), + meck:new(httpc, [passthrough, unsticky]), + meck:expect(httpc, request, fun(_, _, _, _) -> {error, econnrefused} end), + Config; +init_per_testcase(bad_disconnect=Name, Config0) -> + Pkg = {<<"goodpkg">>, <<"1.0.0">>}, + Config1 = [{good_cache, false}, + {pkg, Pkg} + | Config0], + Config = mock_config(Name, Config1), + meck:unload(httpc), + meck:new(httpc, [passthrough, unsticky]), + meck:expect(httpc, request, fun(_, _, _, _) -> {error, econnrefused} end), + Config. + +end_per_testcase(_, Config) -> + unmock_config(Config), + Config. + +good_uncached(Config) -> + Tmp = ?config(tmp_dir, Config), + {Pkg,Vsn} = ?config(pkg, Config), + State = ?config(state, Config), + ?assertEqual({ok, true}, + rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)), + Cache = ?config(cache_dir, Config), + ?assert(filelib:is_regular(filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>))). + +good_cached(Config) -> + Tmp = ?config(tmp_dir, Config), + {Pkg,Vsn} = ?config(pkg, Config), + State = ?config(state, Config), + Cache = ?config(cache_dir, Config), + CachedFile = filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>), + ?assert(filelib:is_regular(CachedFile)), + {ok, Content} = file:read_file(CachedFile), + ?assertEqual({ok, true}, + rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)), + {ok, Content} = file:read_file(CachedFile). + +badindexchk(Config) -> + Tmp = ?config(tmp_dir, Config), + {Pkg,Vsn} = ?config(pkg, Config), + State = ?config(state, Config), + ?assertMatch({bad_registry_checksum, _Path}, + rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)), + %% The cached file is there for forensic purposes + Cache = ?config(cache_dir, Config), + ?assert(filelib:is_regular(filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>))). + +badpkg(Config) -> + Tmp = ?config(tmp_dir, Config), + {Pkg,Vsn} = ?config(pkg, Config), + State = ?config(state, Config), + ?assertMatch({bad_download, _Path}, + rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)), + %% The cached file is there for forensic purposes + Cache = ?config(cache_dir, Config), + ?assert(filelib:is_regular(filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>))). + +bad_to_good(Config) -> + Tmp = ?config(tmp_dir, Config), + {Pkg,Vsn} = ?config(pkg, Config), + State = ?config(state, Config), + Cache = ?config(cache_dir, Config), + CachedFile = filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>), + ?assert(filelib:is_regular(CachedFile)), + {ok, Contents} = file:read_file(CachedFile), + ?assertEqual({ok, true}, + rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)), + %% Cache has refreshed + ?assert({ok, Contents} =/= file:read_file(CachedFile)). + +good_disconnect(Config) -> + Tmp = ?config(tmp_dir, Config), + {Pkg,Vsn} = ?config(pkg, Config), + State = ?config(state, Config), + Cache = ?config(cache_dir, Config), + CachedFile = filename:join(Cache, <<Pkg/binary, "-", Vsn/binary, ".tar">>), + ?assert(filelib:is_regular(CachedFile)), + {ok, Content} = file:read_file(CachedFile), + ?assertEqual({ok, true}, + rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)), + {ok, Content} = file:read_file(CachedFile). + +bad_disconnect(Config) -> + Tmp = ?config(tmp_dir, Config), + {Pkg,Vsn} = ?config(pkg, Config), + State = ?config(state, Config), + ?assertEqual(request_failed, + rebar_pkg_resource:download(Tmp, {pkg, Pkg, Vsn}, State)). + + +%%%%%%%%%%%%%%% +%%% Helpers %%% +%%%%%%%%%%%%%%% +mock_config(Name, Config) -> + Priv = ?config(priv_dir, Config), + CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]), + TmpDir = filename:join([Priv, "tmp", atom_to_list(Name)]), + T = ets:new(fake_registry, [public]), + ets:insert_new(T, [ + {{<<"badindexchk">>,<<"1.0.0">>}, [[], ?bad_checksum]}, + {{<<"goodpkg">>,<<"1.0.0">>}, [[], ?good_checksum]}, + {{<<"badpkg">>,<<"1.0.0">>}, [[], ?good_checksum]} + ]), + CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]), + filelib:ensure_dir(filename:join([CacheDir, "registry"])), + ok = ets:tab2file(T, filename:join([CacheDir, "registry"])), + %% The state returns us a fake registry + meck:new(rebar_state, [passthrough]), + meck:expect(rebar_state, registry, + fun(_State) -> {ok, fake_registry} end), + meck:expect(rebar_state, get, + fun(_State, rebar_packages_cdn, _Default) -> + "http://test.com/" + end), + meck:new(rebar_dir, [passthrough]), + meck:expect(rebar_dir, global_cache_dir, fun(_) -> CacheRoot end), + %% Cache fetches are mocked -- we assume the server and clients are + %% correctly used. + GoodCache = ?config(good_cache, Config), + {Pkg,Vsn} = ?config(pkg, Config), + PkgFile = <<Pkg/binary, "-", Vsn/binary, ".tar">>, + {ok, PkgContents} = file:read_file(filename:join(?config(data_dir, Config), PkgFile)), + meck:new(httpc, [passthrough, unsticky]), + meck:expect(httpc, request, + fun(get, {_Url, _Opts}, _, _) when GoodCache -> + {ok, {{Vsn, 304, <<"Not Modified">>}, [{"etag", ?good_etag}], <<>>}}; + (get, {_Url, _Opts}, _, _) -> + {ok, {{Vsn, 200, <<"OK">>}, [{"etag", ?good_etag}], PkgContents}} + end), + [{cache_root, CacheRoot}, + {cache_dir, CacheDir}, + {tmp_dir, TmpDir}, + {mock_table, T} | Config]. + +unmock_config(Config) -> + meck:unload(), + ets:delete(?config(mock_table, Config)). + +copy_to_cache({Pkg,Vsn}, Config) -> + Name = <<Pkg/binary, "-", Vsn/binary, ".tar">>, + Source = filename:join(?config(data_dir, Config), Name), + Dest = filename:join(?config(cache_dir, Config), Name), + ec_file:copy(Source, Dest). diff --git a/test/rebar_pkg_SUITE_data/badindexchk-1.0.0.tar b/test/rebar_pkg_SUITE_data/badindexchk-1.0.0.tar Binary files differnew file mode 100644 index 0000000..e5b963f --- /dev/null +++ b/test/rebar_pkg_SUITE_data/badindexchk-1.0.0.tar diff --git a/test/rebar_pkg_SUITE_data/badpkg-1.0.0.tar b/test/rebar_pkg_SUITE_data/badpkg-1.0.0.tar Binary files differnew file mode 100644 index 0000000..4930cd2 --- /dev/null +++ b/test/rebar_pkg_SUITE_data/badpkg-1.0.0.tar diff --git a/test/rebar_pkg_SUITE_data/goodpkg-1.0.0.tar b/test/rebar_pkg_SUITE_data/goodpkg-1.0.0.tar Binary files differnew file mode 100644 index 0000000..e5b963f --- /dev/null +++ b/test/rebar_pkg_SUITE_data/goodpkg-1.0.0.tar |