__init__.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. # coding: utf-8
  2. import re
  3. TEST_BT_COLORS = {
  4. "function_name": "[[alt1]]",
  5. "function_arg": "[[good]]",
  6. "stack_frame": "[[bad]]",
  7. "thread_prefix": "[[alt3]]",
  8. "thread_id": "[[bad]]",
  9. "file_path": "[[warn]]",
  10. "line_num": "[[alt2]]",
  11. "address": "[[unimp]]",
  12. }
  13. RESTART_TEST_INDICATOR = '##restart-test##'
  14. INFRASTRUCTURE_ERROR_INDICATOR = '##infrastructure-error##'
  15. RESTART_TEST_INDICATORS = [
  16. RESTART_TEST_INDICATOR,
  17. "network error",
  18. ]
  19. UID_PREFIX_DELIMITER = '-'
  20. # testing
  21. BIN_DIRECTORY = 'bin'
  22. CANON_DATA_DIR_NAME = "canondata"
  23. CANON_RESULT_FILE_NAME = "result.json"
  24. CANONIZATION_RESULT_FILE_NAME = "canonization_res.json"
  25. COMMON_CONTEXT_FILE_NAME = "common_test.context"
  26. CONSOLE_SNIPPET_LIMIT = 5000
  27. FAKE_OUTPUT_EXTS = frozenset([".mf", ".fake", ".cpf", ".cpsf"])
  28. LIST_NODE_LOG_FILE = "test_list.log"
  29. LIST_NODE_RESULT_FILE = "test_list.json"
  30. LIST_RESULT_NODE_LOG_FILE = "list_result.log"
  31. LIST_TRACE_FILE_NAME = "ytest_list.report.trace"
  32. MAX_FILE_SIZE = 1024 * 1024 * 2 # 2 MB
  33. MAX_TEST_RESTART_COUNT = 3
  34. NO_LISTED_TESTS = "NO_LISTED_TESTS"
  35. REPORT_SNIPPET_LIMIT = 12000
  36. SANITIZER_ERROR_RC = 100
  37. SUITE_CONTEXT_FILE_NAME = "test.context"
  38. TEST_LIST_FILE = "test_names_list.json"
  39. TEST_SUBTEST_SEPARATOR = '::'
  40. TESTING_OUT_DIR_NAME = "testing_out_stuff"
  41. TESTING_OUT_RAM_DRIVE_DIR_NAME = "ram_drive_output"
  42. TESTING_OUT_TAR_NAME = TESTING_OUT_DIR_NAME + ".tar.zstd"
  43. TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
  44. TRACE_FILE_NAME = "ytest.report.trace"
  45. TRUNCATING_IGNORE_FILE_LIST = {TRACE_FILE_NAME, SUITE_CONTEXT_FILE_NAME, "run_test.log"}
  46. YT_RUN_TEST_DIR_NAME = "yt_run_test"
  47. YT_RUN_TEST_TAR_NAME = "yt_run_test.tar"
  48. COVERAGE_CFLAGS = ["-fprofile-instr-generate", "-fcoverage-mapping", "-DCLANG_COVERAGE"]
  49. COVERAGE_LDFLAGS = ["-fprofile-instr-generate", "-fcoverage-mapping"]
  50. CANON_BACKEND_KEY = "{canondata_backend}"
  51. DEFAULT_CANONIZATION_BACKEND = "storage.yandex-team.ru/get-devtools"
  52. MDS_URI_PREFIX = 'https://storage.yandex-team.ru/get-devtools/'
  53. BACKEND_URI_PREFIX = 'https://' + CANON_BACKEND_KEY + '/'
  54. MDS_SCHEME = 'mds'
  55. CANON_MDS_RESOURCE_REGEX = re.compile(re.escape(MDS_URI_PREFIX) + r'(.*?)($|#)')
  56. CANON_BACKEND_RESOURCE_REGEX = re.compile(re.escape(BACKEND_URI_PREFIX) + r'(.*?)($|#)')
  57. CANON_SBR_RESOURCE_REGEX = re.compile(r'(sbr:/?/?(\d+))')
  58. MANDATORY_ENV_VAR_NAME = 'YA_MANDATORY_ENV_VARS'
  59. STYLE_CPP_SOURCE_EXTS = [".cpp", ".cxx", ".cc", ".c", ".C"]
  60. STYLE_CPP_HEADER_EXTS = [".h", ".H", ".hh", ".hpp", ".hxx", ".ipp"]
  61. STYLE_CPP_ALL_EXTS = STYLE_CPP_SOURCE_EXTS + STYLE_CPP_HEADER_EXTS
  62. BUILD_FLAGS_ALLOWED_IN_CONTEXT = {
  63. 'AUTOCHECK',
  64. # Required for local test runs
  65. 'TESTS_REQUESTED',
  66. 'USE_ARCADIA_PYTHON',
  67. 'USE_SYSTEM_PYTHON',
  68. }
  69. TEST_NODE_OUTPUT_RESULTS = [TESTING_OUT_TAR_NAME, YT_RUN_TEST_TAR_NAME]
  70. # kvm
  71. DEFAULT_RAM_REQUIREMENTS_FOR_KVM = 4
  72. MAX_RAM_REQUIREMENTS_FOR_KVM = 16
  73. # distbuild
  74. DISTBUILD_STATUS_REPORT_ENV_NAME = 'NODE_EXTENDED_STATUS_FILE_PATH'
  75. DEFAULT_TEST_NODE_TIMEOUT = 15 * 60
  76. TEST_NODE_FINISHING_TIME = 5 * 60
  77. # coverage
  78. COVERAGE_FUNCTION_ENTRIES_LIMIT = 2
  79. COVERAGE_PYTHON_EXTS = (".py", ".pyx", ".pxi", ".pxd")
  80. COVERAGE_RESOLVED_FILE_NAME_PATTERN = "coverage_resolved.{}.json"
  81. CPP_COVERAGE_RESOLVED_FILE_NAME = COVERAGE_RESOLVED_FILE_NAME_PATTERN.format("cpp")
  82. GO_COVERAGE_RESOLVED_FILE_NAME = COVERAGE_RESOLVED_FILE_NAME_PATTERN.format("go")
  83. JAVA_COVERAGE_RESOLVED_FILE_NAME = COVERAGE_RESOLVED_FILE_NAME_PATTERN.format("java")
  84. NLG_COVERAGE_RESOLVED_FILE_NAME = COVERAGE_RESOLVED_FILE_NAME_PATTERN.format("nlg")
  85. PYTHON2_COVERAGE_RESOLVED_FILE_NAME = COVERAGE_RESOLVED_FILE_NAME_PATTERN.format("py2")
  86. PYTHON3_COVERAGE_RESOLVED_FILE_NAME = COVERAGE_RESOLVED_FILE_NAME_PATTERN.format("py3")
  87. TS_COVERAGE_RESOLVED_FILE_NAME = COVERAGE_RESOLVED_FILE_NAME_PATTERN.format("ts")
  88. COVERAGE_CLANG_ENV_NAME = 'LLVM_PROFILE_FILE'
  89. COVERAGE_GCOV_ENV_NAME = 'GCOV_PREFIX'
  90. COVERAGE_GO_ENV_NAME = 'GO_COVERAGE_PREFIX'
  91. COVERAGE_PYTHON_ENV_NAME = 'PYTHON_COVERAGE_PREFIX'
  92. COVERAGE_TS_ENV_NAME = 'TS_COVERAGE_PREFIX'
  93. COVERAGE_NLG_ENV_NAME = 'NLG_COVERAGE_FILENAME'
  94. COVERAGE_ENV_VARS = (
  95. COVERAGE_CLANG_ENV_NAME,
  96. COVERAGE_GCOV_ENV_NAME,
  97. COVERAGE_GO_ENV_NAME,
  98. COVERAGE_NLG_ENV_NAME,
  99. COVERAGE_PYTHON_ENV_NAME,
  100. COVERAGE_TS_ENV_NAME,
  101. )
  102. PYTHON_COVERAGE_PREFIX_FILTER_ENV_NAME = 'PYTHON_COVERAGE_PREFIX_FILTER'
  103. PYTHON_COVERAGE_EXCLUDE_REGEXP_ENV_NAME = 'PYTHON_COVERAGE_EXCLUDE_REGEXP'
  104. # TODO get rid of this list - resolve nodes should be added automatically depending on the lang of the target module and their deps
  105. CLANG_COVERAGE_TEST_TYPES = (
  106. "boost_test",
  107. "coverage_extractor",
  108. "exectest",
  109. "fuzz",
  110. "gtest",
  111. "go_test",
  112. # java tests might use shared libraries
  113. "java",
  114. "py2test",
  115. "py3test",
  116. "pytest",
  117. "unittest",
  118. )
  119. COVERAGE_TABLE_CHUNKS = 20
  120. COVERAGE_TESTS_TIMEOUT_FACTOR = 1.5
  121. COVERAGE_YT_PROXY = "hahn.yt.yandex.net"
  122. COVERAGE_YT_ROOT_PATH = "//home/codecoverage"
  123. COVERAGE_YT_TABLE_PREFIX = "datatable"
  124. # fuzzing
  125. CORPUS_DATA_FILE_NAME = 'corpus.json'
  126. CORPUS_DATA_ROOT_DIR = 'fuzzing'
  127. CORPUS_DIR_NAME = 'corpus'
  128. FUZZING_COVERAGE_ARGS = ['--sanitize-coverage=trace-div,trace-gep']
  129. FUZZING_COMPRESSION_COEF = 1.1
  130. FUZZING_DEFAULT_TIMEOUT = 3600
  131. FUZZING_FINISHING_TIME = 600
  132. FUZZING_TIMEOUT_RE = re.compile(r'(^|\s)-max_total_time=(?P<max_time>\d+)')
  133. GENERATED_CORPUS_DIR_NAME = 'mined_corpus'
  134. MAX_CORPUS_RESOURCES_ALLOWED = 5
  135. # hermione
  136. HERMIONE_REPORT_DIR_NAME = "hermione-report"
  137. HERMIONE_REPORT_TAR_NAME = HERMIONE_REPORT_DIR_NAME + ".tar"
  138. HERMIONE_REPORT_INDEX_FILE_NAME = "index.html"
  139. HERMIONE_REPORT_DB_URLS_FILE_NAME = "databaseUrls.json"
  140. HERMIONE_TESTS_READ_FILE_NAME = "tests.json"
  141. HERMIONE_TESTS_READ_STDOUT_FILE_NAME = "read_tests.out"
  142. HERMIONE_TESTS_READ_STDERR_FILE_NAME = "read_tests.err"
  143. HERMIONE_TESTS_RUN_FILE_NAME = "test_results.jsonl"
  144. HERMIONE_TESTS_RUN_STDOUT_FILE_NAME = "run_tests.out"
  145. HERMIONE_TESTS_RUN_STDERR_FILE_NAME = "run_tests.err"
  146. # yt
  147. YT_OPERATION_ID_SUBSTITUTION = '$OPERATION_ID'
  148. YT_SANDBOX_ROOT_PREFIX = '$(YT_SANDBOX_ROOT)'
  149. # sandbox
  150. SANDBOX_RUN_TEST_YT_TOKEN_VALUE_NAME = 'YA_MAKE_SANDBOX_RUN_TEST_YT_TOKEN'
  151. # global resources
  152. ANDROID_AVD_ROOT = 'ANDROID_AVD_RESOURCE_GLOBAL'
  153. ANDROID_SDK_ROOT = 'ANDROID_SDK_RESOURCE_GLOBAL'
  154. FLAKE8_PY2_RESOURCE = 'FLAKE8_PY2_RESOURCE_GLOBAL'
  155. FLAKE8_PY3_RESOURCE = 'FLAKE8_PY3_RESOURCE_GLOBAL'
  156. GO_TOOLS_RESOURCE = 'GO_TOOLS_RESOURCE_GLOBAL'
  157. JSTYLE_RUNNER_LIB = 'JSTYLE_LIB_RESOURCE_GLOBAL'
  158. NODEJS_RESOURCE = 'NODEJS_RESOURCE_GLOBAL'
  159. NYC_RESOURCE = 'NYC_RESOURCE_GLOBAL'
  160. RUFF_RESOURCE = 'RUFF_RESOURCE_GLOBAL'
  161. CLANG_FORMAT_RESOURCE = 'CLANG_FORMAT_RESOURCE_GLOBAL'
  162. # test_tool resource for host platform.
  163. # source - build/platform/test_tool/host.ya.make.inc.
  164. # always using this test_tool resource except 2 cases:
  165. # 1. when we use TEST_TOOL_TARGET
  166. # 2. when --test-tool-bin passed
  167. TEST_TOOL_HOST = 'TEST_TOOL_HOST_RESOURCE_GLOBAL'
  168. # path to locally built test_tool passed by --test-tool-bin opt
  169. TEST_TOOL_HOST_LOCAL = 'TEST_TOOL_HOST_LOCAL'
  170. # test_tool resource for target platform.
  171. # source - build/platform/test_tool/ya.make.
  172. # The only usage of this resource is running tests under ios emulator
  173. TEST_TOOL_TARGET = 'TEST_TOOL_TARGET_RESOURCE_GLOBAL'
  174. # path to locally built test_tool passed by --test-tool-bin opt
  175. # always same as TEST_TOOL_HOST_LOCAL
  176. # The only usage of this path is running tests under ios emulator
  177. TEST_TOOL_TARGET_LOCAL = 'TEST_TOOL_TARGET_LOCAL'
  178. XCODE_TOOLS_RESOURCE = 'XCODE_TOOLS_ROOT_RESOURCE_GLOBAL'
  179. WINE_TOOL = 'WINE_TOOL_RESOURCE_GLOBAL'
  180. WINE32_TOOL = 'WINE32_TOOL_RESOURCE_GLOBAL'
  181. DEFAULT_CRASHED_STATUS_COMMENT = "Test crashed"
  182. DOCKER_LINK_RE = re.compile(r"(docker:\/\/)(\S+?)(\/\S*)?\@sha\d+:(\w+)")
  183. class Enum(object):
  184. @classmethod
  185. def enumerate(cls):
  186. return [v for k, v in cls.__dict__.items() if not k.startswith("_")]
  187. class SuiteClassType(Enum):
  188. UNCLASSIFIED = '0'
  189. REGULAR = '1'
  190. STYLE = '2'
  191. class TestRequirements(Enum):
  192. Container = 'container'
  193. Cpu = 'cpu'
  194. DiskUsage = 'disk_usage'
  195. Dns = 'dns'
  196. Kvm = 'kvm'
  197. Network = 'network'
  198. Ram = 'ram'
  199. RamDisk = 'ram_disk'
  200. SbVault = 'sb_vault'
  201. YavSecret = 'yav'
  202. class TestRequirementsConstants(Enum):
  203. All = 'all'
  204. AllCpuValue = 50
  205. AllRamDiskValue = 50
  206. MinCpu = 1
  207. MinRam = 1
  208. MinRamDisk = 0
  209. @classmethod
  210. def is_all_cpu(cls, value):
  211. return value == cls.All
  212. @classmethod
  213. def get_cpu_value(cls, value):
  214. return cls.AllCpuValue if cls.is_all_cpu(value) else value
  215. @classmethod
  216. def is_all_ram_disk(cls, value):
  217. return value == cls.All
  218. @classmethod
  219. def get_ram_disk_value(cls, value):
  220. return cls.AllRamDiskValue if cls.is_all_ram_disk(value) else value
  221. class TestSize(Enum):
  222. Small = 'small'
  223. Medium = 'medium'
  224. Large = 'large'
  225. DefaultTimeouts = {
  226. Small: 60,
  227. Medium: 600,
  228. Large: 3600,
  229. }
  230. DefaultPriorities = {
  231. Small: -1,
  232. Medium: -2,
  233. Large: -3,
  234. }
  235. DefaultRequirements = {
  236. Small: {
  237. TestRequirements.Cpu: 1,
  238. TestRequirements.Ram: 8,
  239. # TestRequirements.Ram: 2,
  240. TestRequirements.RamDisk: 0,
  241. },
  242. Medium: {
  243. TestRequirements.Cpu: 1,
  244. TestRequirements.Ram: 8,
  245. # TestRequirements.Ram: 4,
  246. TestRequirements.RamDisk: 0,
  247. },
  248. Large: {
  249. TestRequirements.Cpu: 1,
  250. TestRequirements.Ram: 8,
  251. # TestRequirements.Ram: 8,
  252. TestRequirements.RamDisk: 0,
  253. },
  254. }
  255. MaxRequirements = {
  256. Small: {
  257. TestRequirements.Cpu: 4,
  258. TestRequirements.Ram: 32,
  259. # TestRequirements.Ram: 4,
  260. TestRequirements.RamDisk: 32,
  261. },
  262. Medium: {
  263. TestRequirements.Cpu: 4,
  264. # TestRequirements.Cpu: 8,
  265. TestRequirements.Ram: 32,
  266. # TestRequirements.Ram: 16,
  267. TestRequirements.RamDisk: 32,
  268. },
  269. Large: {
  270. TestRequirements.Cpu: 4,
  271. TestRequirements.Ram: 32,
  272. TestRequirements.RamDisk: 32,
  273. },
  274. }
  275. LargeMarker = "TL"
  276. MediumMarker = "TM"
  277. SmallMarker = "TS"
  278. SizeMarkers = (LargeMarker, MediumMarker, SmallMarker)
  279. SizeShorthandMap = {
  280. Large: LargeMarker,
  281. Medium: MediumMarker,
  282. Small: SmallMarker,
  283. }
  284. @classmethod
  285. def sizes(cls):
  286. return cls.DefaultTimeouts.keys()
  287. @classmethod
  288. def get_shorthand(cls, size):
  289. return cls.SizeShorthandMap[size]
  290. @classmethod
  291. def is_test_shorthand(cls, name):
  292. return name in cls.SizeMarkers
  293. @classmethod
  294. def get_default_timeout(cls, size):
  295. if size in cls.DefaultTimeouts:
  296. return cls.DefaultTimeouts[size]
  297. raise Exception("Unknown test size '{}'".format(size))
  298. @classmethod
  299. def get_default_priorities(cls, size):
  300. if size in cls.DefaultPriorities:
  301. return cls.DefaultPriorities[size]
  302. raise Exception("Unknown test size '{}'".format(size))
  303. @classmethod
  304. def get_default_requirements(cls, size):
  305. if size in cls.DefaultRequirements:
  306. return cls.DefaultRequirements[size]
  307. raise Exception("Unknown test size '{}'".format(size))
  308. @classmethod
  309. def get_max_requirements(cls, size):
  310. if size in cls.MaxRequirements:
  311. return cls.MaxRequirements[size]
  312. raise Exception("Unknown test size '{}'".format(size))
  313. class ModuleLang(Enum):
  314. CPP = "cpp"
  315. DOCS = "docs"
  316. GO = "go"
  317. JAVA = "java"
  318. KOTLIN = "kotlin"
  319. LANG_AGNOSTIC = "agnostic" # This module (or node) is not language specific
  320. PY = "py"
  321. TS = "ts"
  322. UNKNOWN = "unknown"
  323. class AggregateLang(Enum):
  324. ABSENT = "absent"
  325. NUMEROUS = "numerous"
  326. class NodeType(Enum):
  327. TEST = "test"
  328. TEST_AUX = "test-aux"
  329. TEST_RESULTS = "test-results"
  330. DOWNLOAD = "download"
  331. class TestRunExitCode(Enum):
  332. Skipped = 2
  333. Failed = 3
  334. TimeOut = 10
  335. InfrastructureError = 12
  336. class YaTestTags(Enum):
  337. AlwaysMinimize = "ya:always_minimize"
  338. CopyData = "ya:copydata"
  339. CopyDataRO = "ya:copydataro"
  340. Dirty = "ya:dirty"
  341. DumpNodeEnvironment = "ya:dump_node_env"
  342. DumpTestEnvironment = "ya:dump_test_env"
  343. ExoticPlatform = "ya:exotic_platform"
  344. External = "ya:external"
  345. Fat = "ya:fat"
  346. ForceDistbuild = "ya:force_distbuild"
  347. ForceSandbox = "ya:force_sandbox"
  348. GoNoSubtestReport = "ya:go_no_subtest_report"
  349. GoTotalReport = "ya:go_total_report"
  350. HugeLogs = "ya:huge_logs"
  351. JavaTmpInRamDisk = "ya:java_tmp_in_ram_disk"
  352. Manual = "ya:manual"
  353. MapRootUser = "ya:map_root_user"
  354. NoGracefulShutdown = "ya:no_graceful_shutdown"
  355. NoPstreeTrim = "ya:no_pstree_trim"
  356. Norestart = "ya:norestart"
  357. Noretries = "ya:noretries"
  358. NotAutocheck = "ya:not_autocheck"
  359. Notags = "ya:notags"
  360. PerfTest = "ya:perftest"
  361. Privileged = "ya:privileged"
  362. ReportChunks = "ya:report_chunks"
  363. RunWithAsserts = "ya:relwithdebinfo"
  364. SandboxCoverage = "ya:sandbox_coverage"
  365. SequentialRun = "ya:sequential_run"
  366. TraceOutput = "ya:trace_output"
  367. YtRunner = "ya:yt"
  368. class ServiceTags(Enum):
  369. AnyTag = "ya:anytag"
  370. # Linter names must match `NAME` set in `_ADD_*_LINTER_CHECK`
  371. class PythonLinterName(Enum):
  372. Black = "black"
  373. DummyLinter = "dummy_linter"
  374. Flake8 = "flake8"
  375. Py2Flake8 = "py2_flake8"
  376. Ruff = "ruff"
  377. class CppLinterName(Enum):
  378. ClangFormat = "clang_format"
  379. class DefaultLinterConfig(Enum):
  380. Cpp = "build/config/tests/cpp_style/default_configs.json"
  381. Python = "build/config/tests/py_style/default_configs.json"
  382. LINTER_CONFIG_TYPES = {
  383. CppLinterName.ClangFormat: (".clang-format",),
  384. PythonLinterName.Black: ("pyproject.toml",),
  385. PythonLinterName.Ruff: ("pyproject.toml", "ruff.toml"),
  386. }
  387. AUTOINCLUDE_PATHS = (
  388. 'build/conf/autoincludes.json',
  389. 'build/internal/conf/autoincludes.json',
  390. )
  391. class Status(object):
  392. GOOD, XFAIL, FAIL, XPASS, MISSING, CRASHED, TIMEOUT = range(1, 8)
  393. SKIPPED = -100
  394. NOT_LAUNCHED = -200
  395. CANON_DIFF = -300
  396. DESELECTED = -400
  397. INTERNAL = -int(2**31 - 1) # maxint
  398. FLAKY = -50
  399. # XFAILDIFF is internal status and should be replaced
  400. # with XFAIL or XPASS during verification stage of canon data
  401. XFAILDIFF = -90
  402. BY_NAME = {
  403. 'crashed': CRASHED,
  404. 'deselected': DESELECTED,
  405. 'diff': CANON_DIFF,
  406. 'fail': FAIL,
  407. 'flaky': FLAKY,
  408. 'good': GOOD,
  409. 'internal': INTERNAL,
  410. 'missing': MISSING,
  411. 'not_launched': NOT_LAUNCHED,
  412. 'skipped': SKIPPED,
  413. 'timeout': TIMEOUT,
  414. 'xfail': XFAIL,
  415. 'xfaildiff': XFAILDIFF,
  416. 'xpass': XPASS,
  417. }
  418. TO_STR = {
  419. CANON_DIFF: 'diff',
  420. CRASHED: 'crashed',
  421. DESELECTED: 'deselected',
  422. FAIL: 'fail',
  423. FLAKY: 'flaky',
  424. GOOD: 'good',
  425. INTERNAL: 'internal',
  426. MISSING: 'missing',
  427. NOT_LAUNCHED: 'not_launched',
  428. SKIPPED: 'skipped',
  429. TIMEOUT: 'timeout',
  430. XFAIL: 'xfail',
  431. XFAILDIFF: 'xfaildiff',
  432. XPASS: 'xpass',
  433. }
  434. class _Colors(object):
  435. _NAMES = [
  436. "blue",
  437. "cyan",
  438. "default",
  439. "green",
  440. "grey",
  441. "magenta",
  442. "red",
  443. "white",
  444. "yellow",
  445. ]
  446. _PREFIXES = ["", "light", "dark"]
  447. def __init__(self):
  448. self._table = {}
  449. for prefix in self._PREFIXES:
  450. for value in self._NAMES:
  451. name = value
  452. if prefix:
  453. name = "{}_{}".format(prefix, value)
  454. value = "{}-{}".format(prefix, value)
  455. self.__add_color(name.upper(), value)
  456. def __add_color(self, name, value):
  457. self._table[name] = value
  458. self.__setattr__(name, value)
  459. Colors = _Colors()
  460. class _Highlight(object):
  461. _MARKERS = {
  462. # special
  463. "RESET": "rst",
  464. "IMPORTANT": "imp",
  465. "UNIMPORTANT": "unimp",
  466. "BAD": "bad",
  467. "WARNING": "warn",
  468. "GOOD": "good",
  469. "PATH": "path",
  470. "ALTERNATIVE1": "alt1",
  471. "ALTERNATIVE2": "alt2",
  472. "ALTERNATIVE3": "alt3",
  473. }
  474. def __init__(self):
  475. # setting attributes because __getattr__ is much slower
  476. for attr, value in self._MARKERS.items():
  477. self.__setattr__(attr, value)
  478. Highlight = _Highlight()
  479. class _StatusColorMap(object):
  480. # There should be no XFAILDIFF, because it's internal status.
  481. # It should be replaced with XFAIL or XPASS during verification of canon data.
  482. _MAP = {
  483. 'crashed': Highlight.WARNING,
  484. 'deselected': Highlight.UNIMPORTANT,
  485. 'diff': Highlight.BAD,
  486. 'fail': Highlight.BAD,
  487. 'flaky': Highlight.ALTERNATIVE3,
  488. 'good': Highlight.GOOD,
  489. 'internal': Highlight.BAD,
  490. 'missing': Highlight.ALTERNATIVE1,
  491. 'not_launched': Highlight.BAD,
  492. 'skipped': Highlight.UNIMPORTANT,
  493. 'timeout': Highlight.BAD,
  494. 'xfail': Highlight.WARNING,
  495. 'xpass': Highlight.WARNING,
  496. }
  497. def __getitem__(self, item):
  498. return self._MAP[item]
  499. StatusColorMap = _StatusColorMap()