1# Configuration file for the Sphinx documentation builder. 2# 3# For the full list of built-in configuration values, see the documentation: 4# https://www.sphinx-doc.org/en/master/usage/configuration.html 5 6import os 7import re 8import sphinx 9import socket 10import urllib.request 11 12# -- Project information ----------------------------------------------------- 13# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 14 15project = 'Linux Test Project' 16copyright = '2024, Linux Test Project' 17author = 'Linux Test Project' 18release = '1.0' 19 20# -- General configuration --------------------------------------------------- 21# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 22 23extensions = [ 24 'linuxdoc.rstKernelDoc', 25 'sphinxcontrib.spelling', 26 'sphinx.ext.extlinks' 27] 28 29exclude_patterns = ["html*", '_static*'] 30extlinks = { 31 'repo': ('https://github.com/linux-test-project/ltp/%s', '%s'), 32 'master': ('https://github.com/linux-test-project/ltp/blob/master/%s', '%s'), 33 'git_man': ('https://git-scm.com/docs/git-%s', 'git %s'), 34 # TODO: allow 2nd parameter to show page description instead of plain URL 35 'kernel_doc': ('https://docs.kernel.org/%s.html', 'https://docs.kernel.org/%s.html'), 36 'kernel_tree': ('https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/%s', '%s'), 37} 38 39spelling_lang = "en_US" 40spelling_warning = True 41spelling_exclude_patterns=['users/stats.rst'] 42spelling_word_list_filename = "spelling_wordlist" 43 44# -- Options for HTML output ------------------------------------------------- 45# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 46 47html_theme = 'sphinx_rtd_theme' 48html_static_path = ['_static'] 49 50 51def generate_syscalls_stats(_): 52 """ 53 Generate statistics for syscalls. We fetch the syscalls list from the kernel 54 sources, then we compare it with testcases/kernel/syscalls folder and 55 generate a file that is included in the statistics documentation section. 56 """ 57 output = '_static/syscalls.rst' 58 59 # sometimes checking testcases/kernel/syscalls file names are not enough, 60 # because in some cases (i.e. io_ring) syscalls are tested, but they are 61 # part of a more complex scenario. In the following list, we define syscalls 62 # which we know they are 100% tested already. 63 white_list = [ 64 'rt_sigpending', 65 'sethostname', 66 'lsetxattr', 67 'inotify_add_watch', 68 'inotify_rm_watch', 69 'newfstatat', 70 'pselect6', 71 'fanotify_init', 72 'fanotify_mark', 73 'prlimit64', 74 'getdents64', 75 'pkey_mprotect', 76 'pkey_alloc', 77 'pkey_free', 78 'io_uring_setup', 79 'io_uring_enter', 80 'io_uring_register', 81 'epoll_pwait2', 82 'quotactl_fd', 83 'pread64', 84 'pwrite64', 85 'fadvise64', 86 'getmsg', 87 'getpmsg', 88 'putmsg', 89 'putpmsg', 90 ] 91 92 # populate with not implemented, reserved, unmaintained syscalls defined 93 # inside the syscalls file 94 black_list = [ 95 'reserved177', 96 'reserved193', 97 'rseq', 98 '_newselect', 99 '_sysctl', 100 'create_module', 101 'get_kernel_syms', 102 'query_module', 103 'nfsservctl', 104 'afs_syscall', 105 'sysmips', 106 'mq_getsetattr', 107 'vserver', 108 ] 109 110 # fetch syscalls file 111 error = False 112 try: 113 socket.setdefaulttimeout(3) 114 urllib.request.urlretrieve( 115 "https://raw.githubusercontent.com/torvalds/linux/master/arch/mips/kernel/syscalls/syscall_n64.tbl", 116 "syscalls.tbl") 117 except Exception as err: 118 error = True 119 logger = sphinx.util.logging.getLogger(__name__) 120 msg = "Can't download syscall_n64.tbl from kernel sources" 121 logger.warning(msg) 122 123 with open(output, 'w+') as stats: 124 stats.write(f".. warning::\n\n {msg}") 125 126 if error: 127 return 128 129 text = [ 130 'Syscalls\n', 131 '--------\n\n', 132 ] 133 134 # collect all available kernel syscalls 135 regexp = re.compile(r'\d+\s+n64\s+(?P<syscall>\w+)\s+\w+') 136 ker_syscalls = [] 137 with open("syscalls.tbl", 'r') as data: 138 for line in data: 139 match = regexp.search(line) 140 if match: 141 ker_syscalls.append(match.group('syscall')) 142 143 # collect all LTP tested syscalls 144 ltp_syscalls = [] 145 for root, _, files in os.walk('../testcases/kernel/syscalls'): 146 for myfile in files: 147 if myfile.endswith('.c'): 148 ltp_syscalls.append(myfile) 149 150 # compare kernel syscalls with LTP tested syscalls 151 syscalls = {} 152 for kersc in ker_syscalls: 153 if kersc in black_list: 154 continue 155 156 if kersc not in syscalls: 157 if kersc in white_list: 158 syscalls[kersc] = True 159 continue 160 161 syscalls[kersc] = False 162 163 for ltpsc in ltp_syscalls: 164 if ltpsc.startswith(kersc): 165 syscalls[kersc] = True 166 167 # generate the statistics file 168 tested_syscalls = [key for key, val in syscalls.items() if val] 169 text.append('syscalls which are tested under :master:`testcases/kernel/syscalls`:\n\n') 170 text.append(f'* kernel syscalls: {len(ker_syscalls)}\n') 171 text.append(f'* tested syscalls: {len(tested_syscalls)}\n\n') 172 173 # create tested/untested syscalls table 174 index_tested = 0 175 table_tested = [ 176 'Tested syscalls\n', 177 '~~~~~~~~~~~~~~~\n\n', 178 '.. list-table::\n', 179 ' :header-rows: 0\n\n', 180 ] 181 182 index_untest = 0 183 table_untest = [ 184 'Untested syscalls\n', 185 '~~~~~~~~~~~~~~~~~\n\n', 186 '.. list-table::\n', 187 ' :header-rows: 0\n\n', 188 ] 189 190 for sysname, tested in syscalls.items(): 191 if tested: 192 if (index_tested % 3) == 0: 193 table_tested.append(f' * - {sysname}\n') 194 else: 195 table_tested.append(f' - {sysname}\n') 196 197 index_tested += 1 198 else: 199 if (index_untest % 3) == 0: 200 table_untest.append(f' * - {sysname}\n') 201 else: 202 table_untest.append(f' - {sysname}\n') 203 204 index_untest += 1 205 206 left = index_tested % 3 207 if left > 0: 208 for index in range(0, 3 - left): 209 table_tested.append(f' -\n') 210 211 left = index_untest % 3 212 if left > 0: 213 for index in range(0, 3 - left): 214 table_untest.append(f' -\n') 215 216 text.extend(table_tested) 217 text.append('\n') 218 text.extend(table_untest) 219 220 # write the file 221 with open(output, 'w+') as stats: 222 stats.writelines(text) 223 224 225def setup(app): 226 app.add_css_file('custom.css') 227 app.connect('builder-inited', generate_syscalls_stats) 228