v29.4-roots.4 · Commit 22: [PATCH 22/37] ci: consolidate sanitizer and apt workflows
ci/test/test_apt_refresh.py
Before: /dev/null · After: ci/test/test_apt_refresh.py
File metadata
new file mode 100644 index 0000000000000000000000000000000000000000..ddf581675359c2b686f10021dc402e747cbe557b
Download original patch · Release notes
Diff rows 1–100 of 100. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
ci/test/test_apt_refresh.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Regression tests for strict, retried APT index refreshes in Linux CI."""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import pathlib
|
|
6
|
+
import re
|
|
7
|
+
import subprocess
|
|
8
|
+
import tempfile
|
|
9
|
+
import unittest
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
CI_TEST_ROOT = pathlib.Path(__file__).resolve().parent
|
|
13
|
+
CI_ROOT = CI_TEST_ROOT.parent
|
|
14
|
+
APT_HELPER = CI_TEST_ROOT / "apt.sh"
|
|
15
|
+
CI_IMAGEFILE = CI_TEST_ROOT.parent / "test_imagefile"
|
|
16
|
+
LINT_IMAGEFILE = CI_ROOT / "lint_imagefile"
|
|
17
|
+
LINT_INSTALL = CI_ROOT / "lint" / "04_install.sh"
|
|
18
|
+
REFRESH_CALLERS = [
|
|
19
|
+
CI_TEST_ROOT / "01_base_install.sh",
|
|
20
|
+
CI_TEST_ROOT / "03_test_script.sh",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AptRefreshTest(unittest.TestCase):
|
|
25
|
+
def test_refresh_callers_use_the_shared_strict_helper(self):
|
|
26
|
+
helper = APT_HELPER.read_text(encoding="utf-8")
|
|
27
|
+
self.assertIn('APT::Update::Error-Mode=any update', helper)
|
|
28
|
+
self.assertIn('"${retry_command[@]}" apt-get', helper)
|
|
29
|
+
self.assertIn('./ci/test/apt.sh', CI_IMAGEFILE.read_text(encoding="utf-8"))
|
|
30
|
+
self.assertIn('./ci/test/apt.sh', LINT_IMAGEFILE.read_text(encoding="utf-8"))
|
|
31
|
+
|
|
32
|
+
for caller in REFRESH_CALLERS:
|
|
33
|
+
with self.subTest(caller=caller):
|
|
34
|
+
contents = caller.read_text(encoding="utf-8")
|
|
35
|
+
self.assertIn('source "$(dirname "${BASH_SOURCE[0]}")/apt.sh"', contents)
|
|
36
|
+
self.assertIn('ci_retry_apt_update', contents)
|
|
37
|
+
self.assertNotIn('apt-get update', contents)
|
|
38
|
+
self.assertNotIn('APT::Update::Error-Mode=any update', contents)
|
|
39
|
+
|
|
40
|
+
lint_install = LINT_INSTALL.read_text(encoding="utf-8")
|
|
41
|
+
self.assertIn('source /ci/test/apt.sh', lint_install)
|
|
42
|
+
self.assertIn('ci_retry_apt_update', lint_install)
|
|
43
|
+
|
|
44
|
+
refresh_pattern = re.compile(r"\bapt-get\b.*\bupdate\b")
|
|
45
|
+
for script in CI_ROOT.rglob("*.sh"):
|
|
46
|
+
matches = refresh_pattern.findall(script.read_text(encoding="utf-8"))
|
|
47
|
+
with self.subTest(script=script):
|
|
48
|
+
if script == APT_HELPER:
|
|
49
|
+
self.assertEqual(matches, ['apt-get -o APT::Update::Error-Mode=any update'])
|
|
50
|
+
else:
|
|
51
|
+
self.assertEqual(matches, [])
|
|
52
|
+
|
|
53
|
+
def test_invalid_repository_failure_is_retried_and_propagated(self):
|
|
54
|
+
with tempfile.TemporaryDirectory() as temporary_directory:
|
|
55
|
+
temporary_path = pathlib.Path(temporary_directory)
|
|
56
|
+
attempts = temporary_path / "attempts"
|
|
57
|
+
retry = temporary_path / "retry"
|
|
58
|
+
apt_get = temporary_path / "apt-get"
|
|
59
|
+
retry.write_text(
|
|
60
|
+
"#!/usr/bin/env bash\n"
|
|
61
|
+
"set -u\n"
|
|
62
|
+
"test \"$1\" = --\n"
|
|
63
|
+
"shift\n"
|
|
64
|
+
"for attempt in 1 2 3; do\n"
|
|
65
|
+
" \"$@\" || status=$?\n"
|
|
66
|
+
" test \"${status:-0}\" -eq 0 && exit 0\n"
|
|
67
|
+
"done\n"
|
|
68
|
+
"exit \"$status\"\n",
|
|
69
|
+
encoding="utf-8",
|
|
70
|
+
)
|
|
71
|
+
apt_get.write_text(
|
|
72
|
+
"#!/usr/bin/env bash\n"
|
|
73
|
+
"set -u\n"
|
|
74
|
+
"printf '%s\\n' \"$*\" >> \"$APT_ATTEMPTS\"\n"
|
|
75
|
+
"exit 100\n",
|
|
76
|
+
encoding="utf-8",
|
|
77
|
+
)
|
|
78
|
+
retry.chmod(0o755)
|
|
79
|
+
apt_get.chmod(0o755)
|
|
80
|
+
|
|
81
|
+
environment = os.environ | {
|
|
82
|
+
"APT_ATTEMPTS": str(attempts),
|
|
83
|
+
"CI_RETRY_EXE": f"{retry} --",
|
|
84
|
+
"PATH": f"{temporary_path}{os.pathsep}{os.environ['PATH']}",
|
|
85
|
+
}
|
|
86
|
+
result = subprocess.run(
|
|
87
|
+
["bash", "-c", f'source "{APT_HELPER}"; ci_retry_apt_update'],
|
|
88
|
+
check=False,
|
|
89
|
+
env=environment,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
self.assertEqual(result.returncode, 100)
|
|
93
|
+
self.assertEqual(
|
|
94
|
+
attempts.read_text(encoding="utf-8").splitlines(),
|
|
95
|
+
['-o APT::Update::Error-Mode=any update'] * 3,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
if __name__ == "__main__":
|
|
100
|
+
unittest.main()
|