-module(xdg_pipe_menu_socket_tests). -include_lib("eunit/include/eunit.hrl"). serves_the_cached_menu_test() -> Root = mk_tmp_dir(), AppDir = filename:join(Root, "applications"), ok = file:make_dir(AppDir), write_desktop(AppDir, "foo.desktop", "Foo", "foo"), SockPath = filename:join( test_tmp_dir(), "eunit-socket-" ++ integer_to_list(erlang:unique_integer([positive])) ), PrevSockPath = application:get_env(xdg_pipe_menu, socket_path), application:set_env(xdg_pipe_menu, socket_path, SockPath), with_env( [{"XDG_DATA_HOME", Root}, {"XDG_DATA_DIRS", "/does-not-exist-eunit"}], fun() -> {ok, CachePid} = xdg_pipe_menu_cache:start_link(), {ok, SocketPid} = xdg_pipe_menu_socket:start_link(), {ok, Conn} = gen_tcp:connect({local, SockPath}, 0, [binary, {active, false}], 1000), Received = recv_all(Conn, []), gen_tcp:close(Conn), Expected = xdg_pipe_menu_cache:get_menu(), stop(SocketPid), stop(CachePid), ?assertEqual(Expected, Received), ?assert(binary:match(Received, <<"Foo">>) =/= nomatch) end ), _ = file:delete(SockPath), ok = rm_rf(Root), restore_env(xdg_pipe_menu, socket_path, PrevSockPath). %% -- 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). recv_all(Socket, Acc) -> case gen_tcp:recv(Socket, 0, 1000) of {ok, Data} -> recv_all(Socket, [Data | Acc]); {error, closed} -> iolist_to_binary(lists:reverse(Acc)) end. restore_env(App, Key, undefined) -> application:unset_env(App, Key); restore_env(App, Key, {ok, Value}) -> application:set_env(App, Key, Value). 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"]) ). mk_tmp_dir() -> Path = filename:join( test_tmp_dir(), "eunit-socket-dir-" ++ 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.