vuls: init at 0.27.0
[NixPkgs.git] / nixos / tests / castopod.nix
blob57e035354d23ef51ea2be74c7ae574899bbfa5b9
1 import ./make-test-python.nix ({ pkgs, lib, ... }:
3   name = "castopod";
4   meta = with lib.maintainers; {
5     maintainers = [ alexoundos ];
6   };
8   nodes.castopod = { nodes, ... }: {
9     # otherwise 500 MiB file upload fails!
10     virtualisation.diskSize = 512 + 3 * 512;
12     networking.firewall.allowedTCPPorts = [ 80 ];
13     networking.extraHosts =
14       lib.strings.concatStringsSep "\n"
15         (lib.attrsets.mapAttrsToList
16           (name: _: "127.0.0.1 ${name}")
17           nodes.castopod.services.nginx.virtualHosts);
19     services.castopod = {
20       enable = true;
21       database.createLocally = true;
22       localDomain = "castopod.example.com";
23       maxUploadSize = "512M";
24     };
25   };
27   nodes.client = { nodes, pkgs, lib, ... }:
28     let
29       domain = nodes.castopod.services.castopod.localDomain;
31       getIP = node:
32         (builtins.head node.networking.interfaces.eth1.ipv4.addresses).address;
34       targetPodcastSize = 500 * 1024 * 1024;
35       lameMp3Bitrate = 348300;
36       lameMp3FileAdjust = -800;
37       targetPodcastDuration = toString
38         ((targetPodcastSize + lameMp3FileAdjust) / (lameMp3Bitrate / 8));
39       bannerWidth = 3000;
40       banner = pkgs.runCommand "gen-castopod-cover.jpg" { } ''
41         ${pkgs.imagemagick}/bin/magick `
42         `-background green -bordercolor white -gravity northwest xc:black `
43         `-duplicate 99 `
44         `-seed 1 -resize "%[fx:rand()*72+24]" `
45         `-seed 0 -rotate "%[fx:rand()*360]" -border 6x6 -splice 16x36 `
46         `-seed 0 -rotate "%[fx:floor(rand()*4)*90]" -resize "150x50!" `
47         `+append -crop 10x1@ +repage -roll "+%[fx:(t%2)*72]+0" -append `
48         `-resize ${toString bannerWidth} -quality 1 $out
49       '';
51       coverWidth = toString 3000;
52       cover = pkgs.runCommand "gen-castopod-banner.jpg" { } ''
53         ${pkgs.imagemagick}/bin/magick `
54         `-background white -bordercolor white -gravity northwest xc:black `
55         `-duplicate 99 `
56         `-seed 1 -resize "%[fx:rand()*72+24]" `
57         `-seed 0 -rotate "%[fx:rand()*360]" -border 6x6 -splice 36x36 `
58         `-seed 0 -rotate "%[fx:floor(rand()*4)*90]" -resize "144x144!" `
59         `+append -crop 10x1@ +repage -roll "+%[fx:(t%2)*72]+0" -append `
60         `-resize ${coverWidth} -quality 1 $out
61       '';
62     in
63     {
64       networking.extraHosts =
65         lib.strings.concatStringsSep "\n"
66           (lib.attrsets.mapAttrsToList
67             (name: _: "${getIP nodes.castopod} ${name}")
68             nodes.castopod.services.nginx.virtualHosts);
70       environment.systemPackages =
71         let
72           username = "admin";
73           email = "admin@${domain}";
74           password = "Abcd1234";
75           podcastTitle = "Some Title";
76           episodeTitle = "Episode Title";
77           browser-test = pkgs.writers.writePython3Bin "browser-test"
78             {
79               libraries = [ pkgs.python3Packages.selenium ];
80               flakeIgnore = [ "E124" "E501" ];
81             } ''
82             from selenium.webdriver.common.by import By
83             from selenium.webdriver import Firefox
84             from selenium.webdriver.firefox.options import Options
85             from selenium.webdriver.firefox.service import Service
86             from selenium.webdriver.support.ui import WebDriverWait
87             from selenium.webdriver.support import expected_conditions as EC
88             from subprocess import STDOUT
89             import logging
91             selenium_logger = logging.getLogger("selenium")
92             selenium_logger.setLevel(logging.DEBUG)
93             selenium_logger.addHandler(logging.StreamHandler())
95             options = Options()
96             options.add_argument('--headless')
97             service = Service(log_output=STDOUT)
98             driver = Firefox(options=options, service=service)
99             driver = Firefox(options=options)
100             driver.implicitly_wait(30)
101             driver.set_page_load_timeout(60)
103             # install ##########################################################
105             driver.get('http://${domain}/cp-install')
107             wait = WebDriverWait(driver, 20)
109             wait.until(EC.title_contains("installer"))
111             driver.find_element(By.CSS_SELECTOR, '#username').send_keys(
112                 '${username}'
113             )
114             driver.find_element(By.CSS_SELECTOR, '#email').send_keys(
115                 '${email}'
116             )
117             driver.find_element(By.CSS_SELECTOR, '#password').send_keys(
118                 '${password}'
119             )
120             driver.find_element(By.XPATH,
121                                 "//button[contains(., 'Finish install')]"
122             ).click()
124             wait.until(EC.title_contains("Auth"))
126             driver.find_element(By.CSS_SELECTOR, '#email').send_keys(
127                 '${email}'
128             )
129             driver.find_element(By.CSS_SELECTOR, '#password').send_keys(
130                 '${password}'
131             )
132             driver.find_element(By.XPATH,
133                                 "//button[contains(., 'Login')]"
134             ).click()
136             wait.until(EC.title_contains("Admin dashboard"))
138             # create podcast ###################################################
140             driver.get('http://${domain}/admin/podcasts/new')
142             wait.until(EC.title_contains("Create podcast"))
144             driver.find_element(By.CSS_SELECTOR, '#cover').send_keys(
145                 '${cover}'
146             )
147             driver.find_element(By.CSS_SELECTOR, '#banner').send_keys(
148                 '${banner}'
149             )
150             driver.find_element(By.CSS_SELECTOR, '#title').send_keys(
151                 '${podcastTitle}'
152             )
153             driver.find_element(By.CSS_SELECTOR, '#handle').send_keys(
154                 'some_handle'
155             )
156             driver.find_element(By.CSS_SELECTOR, '#description').send_keys(
157                 'Some description'
158             )
159             driver.find_element(By.CSS_SELECTOR, '#owner_name').send_keys(
160                 'Owner Name'
161             )
162             driver.find_element(By.CSS_SELECTOR, '#owner_email').send_keys(
163                 'owner@email.xyz'
164             )
165             driver.find_element(By.XPATH,
166                                 "//button[contains(., 'Create podcast')]"
167             ).click()
169             wait.until(EC.title_contains("${podcastTitle}"))
171             driver.find_element(By.XPATH,
172                                 "//span[contains(., 'Add an episode')]"
173             ).click()
175             wait.until(EC.title_contains("Add an episode"))
177             # upload podcast ###################################################
179             driver.find_element(By.CSS_SELECTOR, '#audio_file').send_keys(
180                 '/tmp/podcast.mp3'
181             )
182             driver.find_element(By.CSS_SELECTOR, '#cover').send_keys(
183                 '${cover}'
184             )
185             driver.find_element(By.CSS_SELECTOR, '#description').send_keys(
186                 'Episode description'
187             )
188             driver.find_element(By.CSS_SELECTOR, '#title').send_keys(
189                 '${episodeTitle}'
190             )
191             driver.find_element(By.XPATH,
192                                 "//button[contains(., 'Create episode')]"
193             ).click()
195             wait.until(EC.title_contains("${episodeTitle}"))
197             driver.close()
198             driver.quit()
199           '';
200         in
201         [
202           pkgs.firefox-unwrapped
203           pkgs.geckodriver
204           browser-test
205           (pkgs.writeShellApplication {
206             name = "build-mp3";
207             runtimeInputs = with pkgs; [ sox lame ];
208             text = ''
209               out=/tmp/podcast.mp3
210               sox -n -r 48000 -t wav - synth ${targetPodcastDuration} sine 440 `
211               `| lame --noreplaygain --cbr -q 9 -b 320 - $out
212               FILESIZE="$(stat -c%s $out)"
213               [ "$FILESIZE" -gt 0 ]
214               [ "$FILESIZE" -le "${toString targetPodcastSize}" ]
215             '';
216           })
217         ];
218     };
220   testScript = ''
221     start_all()
222     castopod.wait_for_unit("castopod-setup.service")
223     castopod.wait_for_file("/run/phpfpm/castopod.sock")
224     castopod.wait_for_unit("nginx.service")
225     castopod.wait_for_open_port(80)
226     castopod.wait_until_succeeds("curl -sS -f http://castopod.example.com")
228     client.succeed("build-mp3")
230     with subtest("Create superadmin, log in, create and upload a podcast"):
231         client.succeed(\
232           "PYTHONUNBUFFERED=1 systemd-cat -t browser-test browser-test")
233   '';