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