aboutsummaryrefslogtreecommitdiff
path: root/test/xdg_pipe_menu_socket_tests.erl
blob: 91cd3e4d9a77fad6dd7160b34e55cd9e1e8ba213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
-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.