1{ system ? builtins.currentSystem
2, config ? { }
3, pkgs ? import ../.. { inherit system config; }
4}:
5
6with import ../lib/testing-python.nix { inherit system pkgs; };
7with pkgs.lib;
8
9let assertions = rec {
10 path = program: path: ''
11 with subtest("The path of ${program} should be ${path}"):
12 p = machine.succeed("type -p \"${program}\" | head -c -1")
13 assert p == "${path}", f"${program} is {p}, expected ${path}"
14 '';
15 unit = name: state: ''
16 with subtest("Unit ${name} should be ${state}"):
17 if "${state}" == "active":
18 machine.wait_for_unit("${name}")
19 else:
20 machine.require_unit_state("${name}", "${state}")
21 '';
22 version = ''
23 import re
24
25 with subtest("binary should report the correct version"):
26 pkgver = "${pkgs.atop.version}"
27 ver = re.sub(r'(?s)^Version: (\d\.\d\.\d).*', r'\1', machine.succeed("atop -V"))
28 assert ver == pkgver, f"Version is `{ver}`, expected `{pkgver}`"
29 '';
30 atoprc = contents:
31 if builtins.stringLength contents > 0 then ''
32 with subtest("/etc/atoprc should have the correct contents"):
33 f = machine.succeed("cat /etc/atoprc")
34 assert f == "${contents}", f"/etc/atoprc contents: '{f}', expected '${contents}'"
35 '' else ''
36 with subtest("/etc/atoprc should not be present"):
37 machine.succeed("test ! -e /etc/atoprc")
38 '';
39 wrapper = present:
40 if present then path "atop" "/run/wrappers/bin/atop" + ''
41 with subtest("Wrapper should be setuid root"):
42 stat = machine.succeed("stat --printf '%a %u' /run/wrappers/bin/atop")
43 assert stat == "4511 0", f"Wrapper stat is {stat}, expected '4511 0'"
44 ''
45 else path "atop" "/run/current-system/sw/bin/atop";
46 atopService = present:
47 if present then
48 unit "atop.service" "active"
49 + ''
50 with subtest("atop.service should write some data to /var/log/atop"):
51
52 def has_data_files(last: bool) -> bool:
53 files = int(machine.succeed("ls -1 /var/log/atop | wc -l"))
54 if files == 0:
55 machine.log("Did not find at least one 1 data file")
56 if not last:
57 machine.log("Will retry...")
58 return False
59 return True
60
61 with machine.nested("Waiting for data files"):
62 retry(has_data_files)
63 '' else unit "atop.service" "inactive";
64 atopRotateTimer = present:
65 unit "atop-rotate.timer" (if present then "active" else "inactive");
66 atopacctService = present:
67 if present then
68 unit "atopacct.service" "active"
69 + ''
70 with subtest("atopacct.service should enable process accounting"):
71 machine.wait_until_succeeds("test -f /run/pacct_source")
72
73 with subtest("atopacct.service should write data to /run/pacct_shadow.d"):
74
75 def has_data_files(last: bool) -> bool:
76 files = int(machine.succeed("ls -1 /run/pacct_shadow.d | wc -l"))
77 if files == 0:
78 machine.log("Did not find at least one 1 data file")
79 if not last:
80 machine.log("Will retry...")
81 return False
82 return True
83
84 with machine.nested("Waiting for data files"):
85 retry(has_data_files)
86 '' else unit "atopacct.service" "inactive";
87 netatop = present:
88 if present then
89 unit "netatop.service" "active"
90 + ''
91 with subtest("The netatop kernel module should be loaded"):
92 out = machine.succeed("modprobe -n -v netatop")
93 assert out == "", f"Module should be loaded already, but modprobe would have done {out}."
94 '' else ''
95 with subtest("The netatop kernel module should be absent"):
96 machine.fail("modprobe -n -v netatop")
97 '';
98 atopgpu = present:
99 if present then
100 (unit "atopgpu.service" "active") + (path "atopgpud" "/run/current-system/sw/bin/atopgpud")
101 else (unit "atopgpu.service" "inactive") + ''
102 with subtest("atopgpud should not be present"):
103 machine.fail("type -p atopgpud")
104 '';
105};
106in
107{
108 justThePackage = makeTest {
109 name = "atop-justThePackage";
110 nodes.machine = {
111 environment.systemPackages = [ pkgs.atop ];
112 };
113 testScript = with assertions; builtins.concatStringsSep "\n" [
114 version
115 (atoprc "")
116 (wrapper false)
117 (atopService false)
118 (atopRotateTimer false)
119 (atopacctService false)
120 (netatop false)
121 (atopgpu false)
122 ];
123 };
124 defaults = makeTest {
125 name = "atop-defaults";
126 nodes.machine = {
127 programs.atop = {
128 enable = true;
129 };
130 };
131 testScript = with assertions; builtins.concatStringsSep "\n" [
132 version
133 (atoprc "")
134 (wrapper false)
135 (atopService true)
136 (atopRotateTimer true)
137 (atopacctService true)
138 (netatop false)
139 (atopgpu false)
140 ];
141 };
142 minimal = makeTest {
143 name = "atop-minimal";
144 nodes.machine = {
145 programs.atop = {
146 enable = true;
147 atopService.enable = false;
148 atopRotateTimer.enable = false;
149 atopacctService.enable = false;
150 };
151 };
152 testScript = with assertions; builtins.concatStringsSep "\n" [
153 version
154 (atoprc "")
155 (wrapper false)
156 (atopService false)
157 (atopRotateTimer false)
158 (atopacctService false)
159 (netatop false)
160 (atopgpu false)
161 ];
162 };
163 netatop = makeTest {
164 name = "atop-netatop";
165 nodes.machine = {
166 programs.atop = {
167 enable = true;
168 netatop.enable = true;
169 };
170 };
171 testScript = with assertions; builtins.concatStringsSep "\n" [
172 version
173 (atoprc "")
174 (wrapper false)
175 (atopService true)
176 (atopRotateTimer true)
177 (atopacctService true)
178 (netatop true)
179 (atopgpu false)
180 ];
181 };
182 atopgpu = makeTest {
183 name = "atop-atopgpu";
184 nodes.machine = {
185 programs.atop = {
186 enable = true;
187 atopgpu.enable = true;
188 };
189 };
190 testScript = with assertions; builtins.concatStringsSep "\n" [
191 version
192 (atoprc "")
193 (wrapper false)
194 (atopService true)
195 (atopRotateTimer true)
196 (atopacctService true)
197 (netatop false)
198 (atopgpu true)
199 ];
200 };
201 everything = makeTest {
202 name = "atop-everthing";
203 nodes.machine = {
204 programs.atop = {
205 enable = true;
206 settings = {
207 flags = "faf1";
208 interval = 2;
209 };
210 setuidWrapper.enable = true;
211 netatop.enable = true;
212 atopgpu.enable = true;
213 };
214 };
215 testScript = with assertions; builtins.concatStringsSep "\n" [
216 version
217 (atoprc "flags faf1\\ninterval 2\\n")
218 (wrapper true)
219 (atopService true)
220 (atopRotateTimer true)
221 (atopacctService true)
222 (netatop true)
223 (atopgpu true)
224 ];
225 };
226}