Merge ~sbeattie/qa-regression-testing:moar-ci-tests into qa-regression-testing:master

Proposed by Steve Beattie
Status: Merged
Merged at revision: a0489c38532078c29c32c97f97c47af0b38ceaba
Proposed branch: ~sbeattie/qa-regression-testing:moar-ci-tests
Merge into: qa-regression-testing:master
Diff against target: 213 lines (+93/-6)
4 files modified
.launchpad.yaml (+14/-0)
lpcraft-runner (+8/-2)
scripts/README.md (+28/-0)
scripts/test-busybox.py (+43/-4)
Reviewer Review Type Date Requested Status
Alex Murray Approve
Review via email: mp+442935@code.launchpad.net

Commit message

tests: add busybox tests to lpci plus infra to skip tests in lpci

Steve Beattie (7):
   * [0012d86b] test-busybox.py: switch to python3
   * [4c70d4a0] test-busybox.py: tests requires root due to udhcpc
   * [fa8ea339] test-busybox.py: older busybox wget doesn't support https
   * [4550df63] test-busybox.py: fix bitwise op test across all releases
   * [175e1a2b] lpcraft-runner: export env var for skipping tests in lpci
   * [841581fe] scripts/README.md: add notes on lpci
   * [14a0bc5f] .launchpad.yaml: add busybox QRT script to CI tests

Description of the change

The overall point of this branch is to enable the busybox qrt scripts in lpci. Along the way, I corrected some issues, including some behavioral differencs in 14.04's busybox, to make sure the tests run across all supported versions and also in lpci; in particular some tests that would work in a local vm would fail to run in the lp test environment.

In particular, the script would attempt to exercise busybox's simple dhcp client (udhcpc) as well as use busybox's wget implementation to access https URLs and the ubuntu archive via ftp. To skip those, I set an environment variable LPCRAFT_QRT_RUNNER in the lpcraft-runner script and then skip tests if that environment variable is set, using python unittest's skipIf decorator (the busybox tests is also converted to python3).

Arguably, this variable could be set in the launchpad.yaml file, and maybe it should be. The idea behind setting it in the runner script was so that local testing with lpci would get the same behavior, but opinions appreciated here.

I also added a bit on lpci and skipping tests to the README for the scripts.

To post a comment you must log in.
Revision history for this message
Alex Murray (alexmurray) wrote :

Thanks Steve, this looks awesome - I would have hoped that setting the variable inside the .launchpad.yaml would then mean that lpci would also set it when running locally - however, this would also mean we would have to duplicate that into every job entry in the yaml as well - so setting it in lpcraft-runner means we only have to put it in one place.

So FWIW I think your current approach is great.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.launchpad.yaml b/.launchpad.yaml
2index fa27693..242a4d9 100644
3--- a/.launchpad.yaml
4+++ b/.launchpad.yaml
5@@ -6,6 +6,7 @@ pipeline:
6 - sudo
7 - git
8 - ghostscript
9+ - busybox
10
11 jobs:
12 imagemagick:
13@@ -85,3 +86,16 @@ jobs:
14 - sudo
15 run: |
16 ./lpcraft-runner ghostscript
17+
18+ busybox:
19+ matrix:
20+ - series: jammy
21+ architectures: amd64
22+ - series: focal
23+ architectures: amd64
24+ - series: bionic
25+ architectures: amd64
26+ packages:
27+ - sudo
28+ run: |
29+ ./lpcraft-runner busybox
30diff --git a/lpcraft-runner b/lpcraft-runner
31index 0a6f690..ca94a85 100755
32--- a/lpcraft-runner
33+++ b/lpcraft-runner
34@@ -2,16 +2,22 @@
35 set -euo pipefail
36
37 test=$1
38+script="./scripts/test-${test}.py"
39+tarball="${TMPDIR:-/tmp}/qrt-test-${test}.tar.gz"
40+
41+# export this so that QRT test scripts can skip tests that will work in
42+# a local VM but not function in the lpci environment
43+export LPCRAFT_QRT_RUNNER=true
44
45 # setup an unprivileged user
46 getent passwd ubuntu >/dev/null || useradd -m -U ubuntu
47 # allow sudo access
48 grep -q "ubuntu ALL=(ALL) NOPASSWD: ALL" /etc/sudoers || echo "ubuntu ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
49 # one test for each require_nonroot, require_sudo and require_root
50-script="./scripts/test-${test}.py"
51-tarball="${TMPDIR:-/tmp}/qrt-test-${test}.tar.gz"
52+
53 rm -f "$tarball"
54 ./scripts/make-test-tarball "$script"
55+
56 # figure out what user we need to run as
57 user=ubuntu
58 if grep -q '^\s*testlib.require_sudo()' "$script"; then
59diff --git a/scripts/README.md b/scripts/README.md
60index 143fae0..41b0a85 100644
61--- a/scripts/README.md
62+++ b/scripts/README.md
63@@ -99,6 +99,34 @@ dependencies explicitly. Eg, `testlib_data.py` has in it:
64
65 so you don't need to specify `data` if you specify `testlib_data.py`.
66
67+
68+Running tests under launchpad CI (aka lpci)
69+-------------------------------------------
70+
71+Reference: <https://lpci.readthedocs.io/en/latest/>
72+
73+Enabling a given test script in lpci is fairly straightforward... in
74+most cases. For the easy cases, editing the top level `.launchpad.yaml`
75+will suffice; name a job and create a similar matrix as the existing
76+ones. Note that the initial job order definition and the later
77+definition should be in matching order.
78+
79+Some test cases will need to be skipped when run in the lpci
80+environment; generally we should try to avid this but sometimes it's
81+unavoidable. The lpcraft-runner script defines the environment variable
82+`LPCRAFT_QRT_RUNNER` for this reason. Python unitest's `skipIf()`
83+decorator can be used to do this:
84+
85+```python
86+ @unittest.skipIf(
87+ 'LPCRAFT_QRT_RUNNER' in os.environ,
88+ 'External URLs not allowed in lpci environ'
89+ )
90+ def test_that_accesses_external_url(self):
91+```
92+
93+
94+
95 Notes on unittest idioms
96 ------------------------
97
98diff --git a/scripts/test-busybox.py b/scripts/test-busybox.py
99index 48054fd..227f6d2 100755
100--- a/scripts/test-busybox.py
101+++ b/scripts/test-busybox.py
102@@ -1,4 +1,4 @@
103-#!/usr/bin/python2
104+#!/usr/bin/python3
105 #
106 # test-busybox.py quality assurance test script for busybox
107 # Copyright (C) 2019-2021 Canonical Ltd.
108@@ -18,6 +18,7 @@
109 #
110 # packages required for test to run:
111 # QRT-Packages: busybox-static busybox-initramfs udhcpc
112+# QRT-Privilege: root
113 # QRT-Depends: testlib_archive.py testlib_compressor.py data
114
115 '''
116@@ -254,6 +255,10 @@ class BusyboxUdhcpcTest(testlib.TestlibCase):
117 def tearDown(self):
118 '''Clean up after each test_* function'''
119
120+ @unittest.skipIf(
121+ 'LPCRAFT_QRT_RUNNER' in os.environ,
122+ 'unable to attach to interface in lpci environment'
123+ )
124 def test_dhcpc(self):
125 '''Test dhcpc renew'''
126
127@@ -278,9 +283,16 @@ class BusyboxWgetTest(testlib.TestlibCase):
128
129 def _test_url_wget(self, url="http://localhost/", content="", invert=False, expected=0, extra_opts=[]):
130 '''Test the given url with wget'''
131+
132+ if self.lsb_release['Release'] < 18.04 and url.startswith("https://"):
133+ self._skipped('busybox wget does not support https before bionic')
134+ expected = 1
135+
136 report = self._get_page_wget(url, expected=expected, extra_opts=extra_opts)
137
138- if content != "":
139+ if self.lsb_release['Release'] < 18.04 and url.startswith("https://"):
140+ self._word_find(report, "wget: not an http or ftp url:", invert)
141+ elif content != "":
142 self._word_find(report, content, invert)
143
144 def _get_page_wget(self, url="http://localhost/", expected=0, extra_opts=[]):
145@@ -304,21 +316,37 @@ class BusyboxWgetTest(testlib.TestlibCase):
146 self._test_url_wget("http://cdimage.ubuntu.com/",
147 "ubuntu-server")
148
149+ @unittest.skipIf(
150+ 'LPCRAFT_QRT_RUNNER' in os.environ,
151+ 'External https URLs not allowed in lpci environ'
152+ )
153 def test_https(self):
154 '''Test https'''
155 self._test_url_wget("https://cdimage.ubuntu.com/",
156 "ubuntu-server")
157
158+ @unittest.skipIf(
159+ 'LPCRAFT_QRT_RUNNER' in os.environ,
160+ 'External https URLs not allowed in lpci environ'
161+ )
162 def test_bad_https_selfsigned(self):
163 '''Test bad https (self-signed)'''
164 self._test_url_wget("https://self-signed.badssl.com/",
165 content="error getting response", expected=1)
166
167+ @unittest.skipIf(
168+ 'LPCRAFT_QRT_RUNNER' in os.environ,
169+ 'External https URLs not allowed in lpci environ'
170+ )
171 def test_bad_https_wrong_host(self):
172 '''Test bad https (wrong host)'''
173 self._test_url_wget("https://wrong.host.badssl.com/",
174 content="error getting response", expected=1)
175
176+ @unittest.skipIf(
177+ 'LPCRAFT_QRT_RUNNER' in os.environ,
178+ 'External ftp URLs not allowed in lpci environ'
179+ )
180 def test_ftp(self):
181 '''Test ftp (ftp.ubuntu.com)'''
182
183@@ -334,10 +362,18 @@ class BusyboxAwkTest(testlib.TestlibCase):
184 def test_bitwise_op(self):
185 expected = 0
186 rc, report = testlib.cmd_pipe(['echo', ''],
187- ['busybox', 'awk', '{ print or(4294967295,1) }'])
188+ ['busybox', 'awk', r'{ printf "%8x\n", or(4294967295,1) }'])
189+ result = 'Got exit code %d, expected %d\n' % (rc, expected)
190+ self.assertEqual(expected, rc, result + report)
191+ self.assertTrue("80000000" in report, "Couldn't find search string.\n" + report)
192+
193+ def test_bitwise_op_2(self):
194+ expected = 0
195+ rc, report = testlib.cmd_pipe(['echo', ''],
196+ ['busybox', 'awk', r'{ printf "%8x\n", or(4294967294,1) }'])
197 result = 'Got exit code %d, expected %d\n' % (rc, expected)
198 self.assertEqual(expected, rc, result + report)
199- self.assertTrue("4294967295" in report, "Couldn't find search string.\n")
200+ self.assertTrue("80000000" in report, "Couldn't find search string.\n" + report)
201
202 def test_dash_f(self):
203 expected = 0
204@@ -354,6 +390,9 @@ class BusyboxAwkTest(testlib.TestlibCase):
205 self.assertTrue("2" in report, "Couldn't find search string.\n")
206
207 if __name__ == '__main__':
208+ # needed for udhcpc tests
209+ testlib.require_root()
210+
211 # more configurable
212 suite = unittest.TestSuite()
213 suite.addTest(unittest.TestLoader().loadTestsFromTestCase(BusyboxTarTest))

Subscribers

People subscribed via source and target branches