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