1let
2 clients = [
3 "ircclient1"
4 "ircclient2"
5 ];
6 server = "solanum";
7 ircPort = 6667;
8 channel = "nixos-cat";
9 iiDir = "/tmp/irc";
10in
11
12import ./make-test-python.nix (
13 { pkgs, lib, ... }:
14 {
15 name = "solanum";
16 nodes =
17 {
18 "${server}" = {
19 networking.firewall.allowedTCPPorts = [ ircPort ];
20 services.solanum = {
21 enable = true;
22 motd = ''
23 The default MOTD doesn't contain the word "nixos" in it.
24 This one does.
25 '';
26 };
27 };
28 }
29 // lib.listToAttrs (
30 builtins.map (
31 client:
32 lib.nameValuePair client {
33 imports = [
34 ./common/user-account.nix
35 ];
36
37 systemd.services.ii = {
38 requires = [ "network.target" ];
39 wantedBy = [ "default.target" ];
40
41 serviceConfig = {
42 Type = "simple";
43 ExecPreStartPre = "mkdir -p ${iiDir}";
44 ExecStart = ''
45 ${lib.getBin pkgs.ii}/bin/ii -n ${client} -s ${server} -i ${iiDir}
46 '';
47 User = "alice";
48 };
49 };
50 }
51 ) clients
52 );
53
54 testScript =
55 let
56 msg = client: "Hello, my name is ${client}";
57 clientScript =
58 client:
59 [
60 ''
61 ${client}.wait_for_unit("network.target")
62 ${client}.systemctl("start ii")
63 ${client}.wait_for_unit("ii")
64 ${client}.wait_for_file("${iiDir}/${server}/out")
65 ''
66 # look for the custom text in the MOTD.
67 ''
68 ${client}.wait_until_succeeds("grep 'nixos' ${iiDir}/${server}/out")
69 ''
70 # wait until first PING from server arrives before joining,
71 # so we don't try it too early
72 ''
73 ${client}.wait_until_succeeds("grep 'PING' ${iiDir}/${server}/out")
74 ''
75 # join ${channel}
76 ''
77 ${client}.succeed("echo '/j #${channel}' > ${iiDir}/${server}/in")
78 ${client}.wait_for_file("${iiDir}/${server}/#${channel}/in")
79 ''
80 # send a greeting
81 ''
82 ${client}.succeed(
83 "echo '${msg client}' > ${iiDir}/${server}/#${channel}/in"
84 )
85 ''
86 # check that all greetings arrived on all clients
87 ]
88 ++ builtins.map (other: ''
89 ${client}.succeed(
90 "grep '${msg other}$' ${iiDir}/${server}/#${channel}/out"
91 )
92 '') clients;
93
94 # foldl', but requires a non-empty list instead of a start value
95 reduce = f: list: builtins.foldl' f (builtins.head list) (builtins.tail list);
96 in
97 ''
98 start_all()
99 ${server}.systemctl("status solanum")
100 ${server}.wait_for_open_port(${toString ircPort})
101
102 # run clientScript for all clients so that every list
103 # entry is executed by every client before advancing
104 # to the next one.
105 ''
106 + lib.concatStrings (reduce (lib.zipListsWith (cs: c: cs + c)) (builtins.map clientScript clients));
107 }
108)