|
6 | 6 | # https://www.linuxfabrik.ch/ |
7 | 7 | # License: The Unlicense, see LICENSE file. |
8 | 8 |
|
9 | | -# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.rst |
| 9 | +# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.md |
10 | 10 |
|
11 | 11 | """Provides test functions for unit tests. |
12 | 12 | """ |
13 | 13 |
|
14 | 14 | import os |
15 | 15 |
|
| 16 | +from . import base |
16 | 17 | from . import disk |
| 18 | +from . import shell |
17 | 19 |
|
18 | 20 |
|
19 | 21 | __author__ = 'Linuxfabrik GmbH, Zurich/Switzerland' |
20 | | -__version__ = '2025042001' |
| 22 | +__version__ = '2026040901' |
| 23 | + |
| 24 | + |
| 25 | +def run(test_instance, plugin, testcase): |
| 26 | + """Run a single testcase against a plugin and assert the results. |
| 27 | +
|
| 28 | + Designed to be used with unittest.TestCase.subTest() for declarative, |
| 29 | + data-driven test definitions. Each testcase is a dict describing what |
| 30 | + to run and what to expect. |
| 31 | +
|
| 32 | + ### Parameters |
| 33 | + - **test_instance** (`unittest.TestCase`): The test instance (self) |
| 34 | + for assertions. |
| 35 | + - **plugin** (`str`): Path to the plugin executable. |
| 36 | + - **testcase** (`dict`): Test definition with keys: |
| 37 | + - `test` (`str`): --test parameter value, |
| 38 | + e.g. `'stdout/ok-healthy,,0'`. |
| 39 | + - `params` (`str`, optional): Additional plugin parameters. |
| 40 | + Default: `''`. |
| 41 | + - `assert-retc` (`int`): Expected return code (STATE_OK, etc.). |
| 42 | + - `assert-in` (`list` of `str`, optional): Strings that must |
| 43 | + appear in stdout. |
| 44 | + - `assert-not-in` (`list` of `str`, optional): Strings that must |
| 45 | + not appear in stdout. |
| 46 | + - `assert-regex` (`str`, optional): Regex pattern that must match |
| 47 | + stdout. |
| 48 | + - `assert-stderr` (`str`, optional): Expected stderr content. |
| 49 | + Default: `''`. |
| 50 | +
|
| 51 | + ### Example |
| 52 | + >>> TESTS = [ |
| 53 | + ... { |
| 54 | + ... 'id': 'ok-all-healthy', |
| 55 | + ... 'test': 'stdout/ok-all-healthy,,0', |
| 56 | + ... 'assert-retc': STATE_OK, |
| 57 | + ... 'assert-in': ['Everything is ok.'], |
| 58 | + ... }, |
| 59 | + ... { |
| 60 | + ... 'id': 'crit-threshold-exceeded', |
| 61 | + ... 'test': 'stdout/crit-threshold-exceeded,,0', |
| 62 | + ... 'params': '--critical 50', |
| 63 | + ... 'assert-retc': STATE_CRIT, |
| 64 | + ... 'assert-regex': r'90.0%.*\\[CRITICAL\\]', |
| 65 | + ... }, |
| 66 | + ... ] |
| 67 | + ... |
| 68 | + ... class TestCheck(unittest.TestCase): |
| 69 | + ... check = '../my-plugin' |
| 70 | + ... |
| 71 | + ... def test(self): |
| 72 | + ... for t in TESTS: |
| 73 | + ... with self.subTest(id=t['id']): |
| 74 | + ... lib.lftest.run(self, self.check, t) |
| 75 | + """ |
| 76 | + params = testcase.get('params', '') |
| 77 | + cmd = f'{plugin} {params} --test={testcase["test"]}'.strip() |
| 78 | + stdout, stderr, retc = base.coe(shell.shell_exec(cmd)) |
| 79 | + |
| 80 | + test_instance.assertEqual( |
| 81 | + retc, |
| 82 | + testcase['assert-retc'], |
| 83 | + f'Expected retc {testcase["assert-retc"]}, got {retc}', |
| 84 | + ) |
| 85 | + |
| 86 | + expected_stderr = testcase.get('assert-stderr', '') |
| 87 | + test_instance.assertEqual(stderr, expected_stderr) |
| 88 | + |
| 89 | + for text in testcase.get('assert-in', []): |
| 90 | + test_instance.assertIn(text, stdout) |
| 91 | + |
| 92 | + for text in testcase.get('assert-not-in', []): |
| 93 | + test_instance.assertNotIn(text, stdout) |
| 94 | + |
| 95 | + if 'assert-regex' in testcase: |
| 96 | + test_instance.assertRegex(stdout, testcase['assert-regex']) |
21 | 97 |
|
22 | 98 |
|
23 | 99 | def test(args): |
24 | 100 | """ |
25 | | - Returns the content of two files and the provided return code. The first file represents STDOUT, |
| 101 | + Returns the content of two files and the provided return code. The first file represents STDOUT, |
26 | 102 | and the second represents STDERR. This function is useful for enabling unit tests. |
27 | 103 |
|
28 | 104 | ### Parameters |
|
0 commit comments