-module(xdg_pipe_menu_cache_tests). -include_lib("eunit/include/eunit.hrl"). build_renders_entries_from_dir_test() -> Dir = mk_tmp_dir(), write_desktop(Dir, "foo.desktop", "Foo", "foo"), Menu = xdg_pipe_menu_cache:build([Dir]), ok = rm_rf(Dir), ?assert(binary:match(Menu, <<"Foo">>) =/= nomatch). build_groups_by_category_test() -> Dir = mk_tmp_dir(), write_desktop(Dir, "foo.desktop", "Foo", "foo", "Utility"), Menu = xdg_pipe_menu_cache:build([Dir]), ok = rm_rf(Dir), ?assert(binary:match(Menu, <<"label=\"Utility\"">>) =/= nomatch). build_skips_hidden_entries_test() -> Dir = mk_tmp_dir(), write_desktop(Dir, "visible.desktop", "Visible", "visible"), ok = file:write_file( filename:join(Dir, "hidden.desktop"), <<"[Desktop Entry]\nName=Hidden\nExec=hidden\nNoDisplay=true\n">> ), Menu = xdg_pipe_menu_cache:build([Dir]), ok = rm_rf(Dir), ?assert(binary:match(Menu, <<"Visible">>) =/= nomatch), ?assertEqual(nomatch, binary:match(Menu, <<"Hidden">>)). build_skips_unparseable_files_without_failing_test() -> Dir = mk_tmp_dir(), write_desktop(Dir, "good.desktop", "Good", "good"), ok = file:write_file(filename:join(Dir, "bad.desktop"), <<"[Desktop Entry]\nExec=bad\n">>), Menu = xdg_pipe_menu_cache:build([Dir]), ok = rm_rf(Dir), ?assert(binary:match(Menu, <<"Good">>) =/= nomatch). build_skips_missing_dirs_test() -> ?assertEqual( <<"\n" "\n" "\n">>, xdg_pipe_menu_cache:build(["/does-not-exist"]) ). gen_server_serves_and_invalidates_test() -> Root = mk_tmp_dir(), AppDir = filename:join(Root, "applications"), ok = file:make_dir(AppDir), write_desktop(AppDir, "foo.desktop", "Foo", "foo"), with_env( [{"XDG_DATA_HOME", Root}, {"XDG_DATA_DIRS", "/does-not-exist-eunit"}], fun() -> {ok, Pid} = xdg_pipe_menu_cache:start_link(), Menu1 = xdg_pipe_menu_cache:get_menu(), ?assert(binary:match(Menu1, <<"Foo">>) =/= nomatch), write_desktop(AppDir, "bar.desktop", "Bar", "bar"), ok = xdg_pipe_menu_cache:invalidate(), Menu2 = xdg_pipe_menu_cache:get_menu(), stop(Pid), ?assert(binary:match(Menu2, <<"Bar">>) =/= nomatch) end ), ok = rm_rf(Root). %% -- helpers ---------------------------------------------------------------- %% start_link/0 links the started process to us (the test process); %% unlink before killing it so the kill signal doesn't propagate back %% and take the test process down with it. stop(Pid) -> unlink(Pid), true = erlang:exit(Pid, kill). with_env(Vars, Fun) -> Saved = [{Name, os:getenv(Name)} || {Name, _} <- Vars], try lists:foreach(fun({Name, Value}) -> set_env(Name, Value) end, Vars), Fun() after lists:foreach(fun({Name, Value}) -> set_env(Name, Value) end, Saved) end. set_env(Name, false) -> os:unsetenv(Name); set_env(Name, Value) -> os:putenv(Name, Value). write_desktop(Dir, FileName, Name, Exec) -> ok = file:write_file( filename:join(Dir, FileName), iolist_to_binary(["[Desktop Entry]\nName=", Name, "\nExec=", Exec, "\n"]) ). write_desktop(Dir, FileName, Name, Exec, Categories) -> ok = file:write_file( filename:join(Dir, FileName), iolist_to_binary([ "[Desktop Entry]\nName=", Name, "\nExec=", Exec, "\nCategories=", Categories, ";\n" ]) ). mk_tmp_dir() -> Path = filename:join( test_tmp_dir(), "eunit-cache-" ++ integer_to_list(erlang:unique_integer([positive])) ), ok = file:make_dir(Path), Path. test_tmp_dir() -> case os:getenv("TMPDIR") of false -> "/tmp"; Dir -> Dir end. rm_rf(Path) -> case filelib:is_dir(Path) of true -> {ok, Entries} = file:list_dir(Path), lists:foreach(fun(E) -> rm_rf(filename:join(Path, E)) end, Entries), file:del_dir(Path); false -> file:delete(Path) end.