1f08c3bdfSopenharmony_ciMotivation for metadata extraction
2f08c3bdfSopenharmony_ci==================================
3f08c3bdfSopenharmony_ci
4f08c3bdfSopenharmony_ciExporting documentation
5f08c3bdfSopenharmony_ci-----------------------
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ciThis allow us to build browsable documentation for the testcases, e.g. a
8f08c3bdfSopenharmony_cicatalogue of test information that would be searchable etc. At this point there
9f08c3bdfSopenharmony_ciis a single page generated from the extracted data that tries to outline the
10f08c3bdfSopenharmony_ciintent.
11f08c3bdfSopenharmony_ci
12f08c3bdfSopenharmony_ci
13f08c3bdfSopenharmony_ciPropagating test requirements
14f08c3bdfSopenharmony_ci-----------------------------
15f08c3bdfSopenharmony_ci
16f08c3bdfSopenharmony_ciSome subtests require different hardware resources/software versions/etc. the
17f08c3bdfSopenharmony_citest execution framework needs to consume these so that it can locate proper
18f08c3bdfSopenharmony_cihardware, install proper software, etc.
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ciSome examples of requirements are:
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci* Test needs at least 1GB of RAM.
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_ci* Test needs a block device at least 512MB in size
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_ci* Test needs a NUMA machine with two memory nodes and at least 300 free pages on each node
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci* Test needs i2c eeprom connected on a i2c bus
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_ci* Test needs two serial ports connected via null-modem cable
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ciWith this information extracted from the tests the testrunner can then map the
34f08c3bdfSopenharmony_cirequirements on the available machines in a lab and select a proper machine for
35f08c3bdfSopenharmony_cithe particular (sub)set of testcases as well as supply a particular test with
36f08c3bdfSopenharmony_ciadditional information needed for the test, such as address of the i2c device,
37f08c3bdfSopenharmony_cipaths to the serial devices, etc. In the case of virtual machines the test could
38f08c3bdfSopenharmony_cialso dynamically prepare the correct environment for the test on demand.
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci
41f08c3bdfSopenharmony_ciParallel test execution
42f08c3bdfSopenharmony_ci-----------------------
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ciAn LTP testrun on a modern hardware wastes most of the machine resources
45f08c3bdfSopenharmony_cibecause the testcases are running sequentially. However in order to execute
46f08c3bdfSopenharmony_citests in parallel we need to know which system resources are utilized by a
47f08c3bdfSopenharmony_cigiven test, as obviously we cannot run two tests that monopolize the same
48f08c3bdfSopenharmony_ciresource. In some cases we would also need to partition the system resource
49f08c3bdfSopenharmony_ciaccordingly, e.g. if we have two memory stress tests running at the same time
50f08c3bdfSopenharmony_ciwe will need to cap each of these tests on half of the available memory, or
51f08c3bdfSopenharmony_cimake sure that sum of the memory used by these two tests is not greater than
52f08c3bdfSopenharmony_ciavailable memory.
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ciExamples of such tests are:
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci* Tests that mess with global system state
57f08c3bdfSopenharmony_ci   - system time (e.g. settimeofday() test and leap second test)
58f08c3bdfSopenharmony_ci   - SysV SHM
59f08c3bdfSopenharmony_ci   - ...
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci* Tests that use block device
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_ci* Tests that work with a particular hardware resource
64f08c3bdfSopenharmony_ci  - i2c eeprom test
65f08c3bdfSopenharmony_ci  - serial port tests
66f08c3bdfSopenharmony_ci  - ...
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ciExporting test runtime/timeout to the testrunner
69f08c3bdfSopenharmony_ci------------------------------------------------
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_ciCurrently most of the testrunners usually do not know for how long is the test
72f08c3bdfSopenharmony_cisupposed to run, this means that we have to guess some upper limit on how long
73f08c3bdfSopenharmony_cia test is supposed to run. The value is usually twice of the maximal runtime
74f08c3bdfSopenharmony_cifor all testcases or whole suite or even larger. This means that we are wasting
75f08c3bdfSopenharmony_citime in the case that the test ends up stuck and we could have failed it much
76f08c3bdfSopenharmony_cisooner in most of the cases. This becomes quite important for a kernel
77f08c3bdfSopenharmony_ciregression tests that do crash the host, if the information that the test is
78f08c3bdfSopenharmony_cisupposed to crash a kernel under a minute is exported to the testrunner we can
79f08c3bdfSopenharmony_cireboot the machine much faster in an event of a crash.
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ciGetting rid of runtest files
82f08c3bdfSopenharmony_ci----------------------------
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ciThis would also allow us to get rid of the unflexible and hard to maintain
85f08c3bdfSopenharmony_ciruntest files. Once this system is in place we will have a list of all tests
86f08c3bdfSopenharmony_cialong with their respective metadata - which means that we will be able to
87f08c3bdfSopenharmony_cigenerate subsets of the test easily on the fly.
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ciIn order to achieve this we need two things:
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ciEach test will describe which syscall/functionality it tests in the metadata.
92f08c3bdfSopenharmony_ciThen we could define groups of tests based on that. I.e. instead of having
93f08c3bdfSopenharmony_cisyscall runtest file we would ask the testrunner to run all test that have a
94f08c3bdfSopenharmony_cidefined which syscall they test, or whose filename matches a particular syscall name.
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ciSecondly we will have to store the test variants in the test metadata instead
97f08c3bdfSopenharmony_ciof putting them in a file that is unrelated to the test.
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ciFor example:
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci* To run CVE related test we would select testcases with CVE tag
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci* To run IPC test we will define a list of IPC syscalls and run all syscall
104f08c3bdfSopenharmony_ci  test that are in the list
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci* And many more...
107f08c3bdfSopenharmony_ci
108f08c3bdfSopenharmony_ci
109f08c3bdfSopenharmony_ciImplementation
110f08c3bdfSopenharmony_ci==============
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ciThe docparser is implemented as a minimal C tokenizer that can parse and
113f08c3bdfSopenharmony_ciextract code comments and C structures. The docparser then runs over all C
114f08c3bdfSopenharmony_cisources in the testcases directory and if tst\_test structure is present in the
115f08c3bdfSopenharmony_cisource it's parsed and the result is included in the resulting metadata.
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ciDuring parsing the metadata is stored in a simple key/value storage that more
118f08c3bdfSopenharmony_cior less follows C structure layout, i.e. can include hash, array, and string.
119f08c3bdfSopenharmony_ciOnce the parsing is finished the result is filtered so that only interesting
120f08c3bdfSopenharmony_cifields of the tst\_test structure are included and then converted into JSON
121f08c3bdfSopenharmony_cioutput.
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ciThis process produces one big JSON file with metadata for all tests, that
124f08c3bdfSopenharmony_ciis then installed along with the testcases. This would then be used by the
125f08c3bdfSopenharmony_citestrunner.
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_ciThe test requirements are stored in the tst\_test structure either as
128f08c3bdfSopenharmony_cibitflags, integers or arrays of strings:
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_ci```c
131f08c3bdfSopenharmony_cistruct tst_test test = {
132f08c3bdfSopenharmony_ci	...
133f08c3bdfSopenharmony_ci	/* tests needs to run with UID=0 */
134f08c3bdfSopenharmony_ci	.needs_root = 1,
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ci	/*
137f08c3bdfSopenharmony_ci	 * Tests needs a block device at least 1024MB in size and also
138f08c3bdfSopenharmony_ci	 * mkfs.ext4 installed.
139f08c3bdfSopenharmony_ci	 */
140f08c3bdfSopenharmony_ci	.needs_device = 1,
141f08c3bdfSopenharmony_ci	.dev_min_size = 1024,
142f08c3bdfSopenharmony_ci	.dev_fs_type = ext4,
143f08c3bdfSopenharmony_ci
144f08c3bdfSopenharmony_ci	/* Indicates that the test is messing with system wall clock */
145f08c3bdfSopenharmony_ci	.restore_wallclock = 1,
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_ci	/* Tests needs uinput either compiled in or loaded as a module */
148f08c3bdfSopenharmony_ci	.needs_drivers = (const char *[]) {
149f08c3bdfSopenharmony_ci		"uinput",
150f08c3bdfSopenharmony_ci		NULL
151f08c3bdfSopenharmony_ci	},
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_ci	/* Tests needs enabled kernel config flags */
154f08c3bdfSopenharmony_ci	.needs_kconfigs = (const char *[]) {
155f08c3bdfSopenharmony_ci		"CONFIG_X86_INTEL_UMIP=y",
156f08c3bdfSopenharmony_ci		NULL
157f08c3bdfSopenharmony_ci	},
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_ci	/* Additional array of key value pairs */
160f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
161f08c3bdfSopenharmony_ci                {"linux-git", "43a6684519ab"},
162f08c3bdfSopenharmony_ci                {"CVE", "2017-2671"},
163f08c3bdfSopenharmony_ci                {NULL, NULL}
164f08c3bdfSopenharmony_ci        }
165f08c3bdfSopenharmony_ci};
166f08c3bdfSopenharmony_ci```
167f08c3bdfSopenharmony_ci
168f08c3bdfSopenharmony_ciThe test documentation is stored in a special comment such as:
169f08c3bdfSopenharmony_ci
170f08c3bdfSopenharmony_ci```
171f08c3bdfSopenharmony_ci/*\
172f08c3bdfSopenharmony_ci * Test description
173f08c3bdfSopenharmony_ci *
174f08c3bdfSopenharmony_ci * This is a test description.
175f08c3bdfSopenharmony_ci * Consisting of several lines.
176f08c3bdfSopenharmony_ci */
177f08c3bdfSopenharmony_ci```
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ciWhich will yield following JSON output:
180f08c3bdfSopenharmony_ci
181f08c3bdfSopenharmony_ci```json
182f08c3bdfSopenharmony_ci "testcaseXY": {
183f08c3bdfSopenharmony_ci  "needs_root": "1",
184f08c3bdfSopenharmony_ci  "needs_device": "1",
185f08c3bdfSopenharmony_ci  "dev_min_size": "1024",
186f08c3bdfSopenharmony_ci  "dev_fs_type": "ext4",
187f08c3bdfSopenharmony_ci  "restore_wallclock": "1",
188f08c3bdfSopenharmony_ci  "needs_drivers": [
189f08c3bdfSopenharmony_ci    "uinput",
190f08c3bdfSopenharmony_ci  ],
191f08c3bdfSopenharmony_ci  "needs_kconfigs": [
192f08c3bdfSopenharmony_ci    "CONFIG_X86_INTEL_UMIP=y",
193f08c3bdfSopenharmony_ci  ],
194f08c3bdfSopenharmony_ci  "tags": [
195f08c3bdfSopenharmony_ci    [
196f08c3bdfSopenharmony_ci     "linux-git",
197f08c3bdfSopenharmony_ci     "43a6684519ab"
198f08c3bdfSopenharmony_ci    ],
199f08c3bdfSopenharmony_ci    [
200f08c3bdfSopenharmony_ci     "CVE",
201f08c3bdfSopenharmony_ci     "2017-2671"
202f08c3bdfSopenharmony_ci    ],
203f08c3bdfSopenharmony_ci   ],
204f08c3bdfSopenharmony_ci  "doc": [
205f08c3bdfSopenharmony_ci    "Test description",
206f08c3bdfSopenharmony_ci    "",
207f08c3bdfSopenharmony_ci    "This is a test description.",
208f08c3bdfSopenharmony_ci    "Consisting of several lines."
209f08c3bdfSopenharmony_ci  ],
210f08c3bdfSopenharmony_ci  "fname": "testcases/kernel/syscalls/foo/testcaseXY.c"
211f08c3bdfSopenharmony_ci },
212f08c3bdfSopenharmony_ci```
213f08c3bdfSopenharmony_ci
214f08c3bdfSopenharmony_ciThe final JSON file is JSON object of test descriptions indexed by a test name
215f08c3bdfSopenharmony_ciwith a header describing the testsuite:
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci```json
218f08c3bdfSopenharmony_ci{
219f08c3bdfSopenharmony_ci "testsuite": "Linux Test Project",
220f08c3bdfSopenharmony_ci "testsuite_short": "LTP",
221f08c3bdfSopenharmony_ci "url": "https://github.com/linux-test-project/ltp/",
222f08c3bdfSopenharmony_ci "scm_url_base": "https://github.com/linux-test-project/ltp/tree/master/",
223f08c3bdfSopenharmony_ci "timeout": 300,
224f08c3bdfSopenharmony_ci "version": "20200930",
225f08c3bdfSopenharmony_ci "tests": {
226f08c3bdfSopenharmony_ci  "testcaseXY": {
227f08c3bdfSopenharmony_ci   ...
228f08c3bdfSopenharmony_ci  },
229f08c3bdfSopenharmony_ci  ...
230f08c3bdfSopenharmony_ci }
231f08c3bdfSopenharmony_ci}
232f08c3bdfSopenharmony_ci```
233f08c3bdfSopenharmony_ci
234f08c3bdfSopenharmony_ciOpen Points
235f08c3bdfSopenharmony_ci===========
236f08c3bdfSopenharmony_ci
237f08c3bdfSopenharmony_ciThere are stil some loose ends. Mostly it's not well defined where to put
238f08c3bdfSopenharmony_cithings and how to format them.
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_ci* Some of the hardware requirements are already listed in the tst\_test. Should
241f08c3bdfSopenharmony_ci  we put all of them there?
242f08c3bdfSopenharmony_ci
243f08c3bdfSopenharmony_ci* What would be the format for test documentation and how to store things such
244f08c3bdfSopenharmony_ci  as test variants there?
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ciSo far this proof of concept generates a metadata file. I guess that we need
247f08c3bdfSopenharmony_ciactual consumers which will help to settle things down, I will try to look into
248f08c3bdfSopenharmony_cimaking use of this in the runltp-ng at least as a reference implementation.
249