aboutsummaryrefslogtreecommitdiffstats
path: root/tests/mason-core/terminator_spec.lua
blob: 24c1ec25570fc773819df2b16867ff9f97e07bfe (plain) (blame)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
local InstallHandle = require "mason-core.installer.handle"
local _ = require "mason-core.functional"
local a = require "mason-core.async"
local match = require "luassert.match"
local registry = require "mason-registry"
local spy = require "luassert.spy"
local stub = require "luassert.stub"
local terminator = require "mason-core.terminator"

describe("terminator", function()
    it(
        "should terminate all active handles on nvim exit",
        async_test(function()
            spy.on(InstallHandle, "terminate")
            local dummy = registry.get_package "dummy"
            local dummy2 = registry.get_package "dummy2"
            for _, pkg in ipairs { dummy, dummy2 } do
                stub(pkg.spec.source, "install", function()
                    a.sleep(10000)
                end)
            end

            local dummy_handle = dummy:install()
            local dummy2_handle = dummy2:install()

            assert.wait_for(function()
                assert.spy(dummy.spec.source.install).was_called()
                assert.spy(dummy2.spec.source.install).was_called()
            end)

            terminator.terminate(5000)

            assert.spy(InstallHandle.terminate).was_called(2)
            assert.spy(InstallHandle.terminate).was_called_with(match.is_ref(dummy_handle))
            assert.spy(InstallHandle.terminate).was_called_with(match.is_ref(dummy2_handle))
            assert.wait_for(function()
                assert.is_true(dummy_handle:is_closed())
                assert.is_true(dummy2_handle:is_closed())
            end)
        end)
    )

    it(
        "should print warning messages",
        async_test(function()
            spy.on(vim.api, "nvim_echo")
            spy.on(vim.api, "nvim_err_writeln")
            spy.on(InstallHandle, "terminate")
            local dummy = registry.get_package "dummy"
            local dummy2 = registry.get_package "dummy2"
            for _, pkg in ipairs { dummy, dummy2 } do
                stub(pkg.spec.source, "install", function()
                    a.sleep(10000)
                end)
            end

            local dummy_handle = dummy:install()
            local dummy2_handle = dummy2:install()

            assert.wait_for(function()
                assert.spy(dummy.spec.source.install).was_called()
                assert.spy(dummy2.spec.source.install).was_called()
            end)

            terminator.terminate(5000)

            assert.spy(vim.api.nvim_echo).was_called(1)
            assert.spy(vim.api.nvim_echo).was_called_with({
                {
                    "[mason.nvim] Neovim is exiting while packages are still installing. Terminating all installations…",
                    "WarningMsg",
                },
            }, true, {})

            a.wait(vim.schedule)

            assert.spy(vim.api.nvim_err_writeln).was_called(1)
            assert.spy(vim.api.nvim_err_writeln).was_called_with(_.dedent [[
                [mason.nvim] Neovim exited while the following packages were installing. Installation was aborted.
                - dummy
                - dummy2
            ]])
            assert.wait_for(function()
                assert.is_true(dummy_handle:is_closed())
                assert.is_true(dummy2_handle:is_closed())
            end)
        end)
    )

    it(
        "should send SIGTERM and then SIGKILL after grace period",
        async_test(function()
            spy.on(InstallHandle, "kill")
            local dummy = registry.get_package "dummy"
            stub(dummy.spec.source, "install")
            dummy.spec.source.install.invokes(function(ctx)
                -- your signals have no power here
                ctx.spawn.bash { "-c", "function noop { :; }; trap noop SIGTERM; sleep 999999;" }
            end)

            local handle = dummy:install()

            assert.wait_for(function()
                assert.spy(dummy.spec.source.install).was_called()
            end)
            terminator.terminate(50)

            assert.wait_for(function()
                assert.spy(InstallHandle.kill).was_called(2)
                assert.spy(InstallHandle.kill).was_called_with(match.is_ref(handle), 15) -- SIGTERM
                assert.spy(InstallHandle.kill).was_called_with(match.is_ref(handle), 9) -- SIGKILL
            end)

            assert.wait_for(function()
                assert.is_true(handle:is_closed())
            end)
        end)
    )
end)