ytest.py 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475
  1. from __future__ import print_function
  2. import base64
  3. import collections
  4. import copy
  5. import json
  6. import os
  7. import re
  8. import six
  9. import subprocess
  10. try:
  11. from StringIO import StringIO
  12. except ImportError:
  13. from io import StringIO
  14. import _common
  15. import _dart_fields as df
  16. import _requirements as reqs
  17. import lib.test_const as consts
  18. import ymake
  19. from _dart_fields import (
  20. serialize_list,
  21. get_unit_list_variable,
  22. deserialize_list,
  23. create_dart_record,
  24. )
  25. BLOCK_SEPARATOR = '============================================================='
  26. SPLIT_FACTOR_MAX_VALUE = 1000
  27. SPLIT_FACTOR_TEST_FILES_MAX_VALUE = 4250
  28. PARTITION_MODS = ('SEQUENTIAL', 'MODULO')
  29. DEFAULT_TIDY_CONFIG = "build/config/tests/clang_tidy/config.yaml"
  30. DEFAULT_TIDY_CONFIG_MAP_PATH = "build/yandex_specific/config/clang_tidy/tidy_default_map.json"
  31. PROJECT_TIDY_CONFIG_MAP_PATH = "build/yandex_specific/config/clang_tidy/tidy_project_map.json"
  32. KTLINT_CURRENT_EDITOR_CONFIG = "arcadia/build/platform/java/ktlint/.editorconfig"
  33. KTLINT_OLD_EDITOR_CONFIG = "arcadia/build/platform/java/ktlint_old/.editorconfig"
  34. YTEST_FIELDS_BASE = (
  35. df.AndroidApkTestActivity.value,
  36. df.BinaryPath.normalized,
  37. df.BuildFolderPath.normalized,
  38. df.CustomDependencies.all_standard,
  39. df.GlobalLibraryPath.value,
  40. df.ScriptRelPath.second_flat,
  41. df.SkipTest.value,
  42. df.SourceFolderPath.normalized,
  43. df.SplitFactor.from_macro_args_and_unit,
  44. df.TestCwd.from_unit,
  45. df.TestedProjectFilename.value,
  46. df.TestedProjectName.unit_name,
  47. df.TestEnv.value,
  48. df.TestIosDeviceType.value,
  49. df.TestIosRuntimeType.value,
  50. df.TestRecipes.value,
  51. )
  52. YTEST_FIELDS_EXTRA = (
  53. df.Blob.value,
  54. df.ForkMode.from_macro_and_unit,
  55. df.Size.from_macro_args_and_unit,
  56. df.Tag.from_macro_args_and_unit,
  57. df.TestTimeout.from_macro_args_and_unit,
  58. df.YtSpec.from_macro_args_and_unit,
  59. )
  60. PY_EXEC_FIELDS_BASE = (
  61. df.Blob.value,
  62. df.BuildFolderPath.stripped,
  63. df.CanonizeSubPath.value,
  64. df.CustomDependencies.test_depends_only,
  65. df.ForkMode.test_fork_mode,
  66. df.ForkTestFiles.value,
  67. df.PythonPaths.value,
  68. df.Requirements.from_unit,
  69. df.Size.from_unit,
  70. df.SkipTest.value,
  71. df.SourceFolderPath.normalized,
  72. df.SplitFactor.from_unit,
  73. df.Tag.from_macro_args_and_unit,
  74. df.TestCwd.keywords_replaced,
  75. df.TestData.from_unit_with_canonical,
  76. df.TestEnv.value,
  77. df.TestFiles.test_srcs,
  78. df.TestPartition.value,
  79. df.TestRecipes.value,
  80. df.TestTimeout.from_unit_with_default,
  81. df.UseArcadiaPython.value,
  82. )
  83. CHECK_FIELDS_BASE = (
  84. df.CustomDependencies.depends_only,
  85. df.Requirements.from_macro_args,
  86. df.ScriptRelPath.first_flat,
  87. df.TestEnv.value,
  88. df.TestName.first_flat,
  89. df.UseArcadiaPython.value,
  90. )
  91. LINTER_FIELDS_BASE = (
  92. df.LintName.value,
  93. df.LintExtraParams.from_macro_args,
  94. df.TestName.name_from_macro_args,
  95. df.TestedProjectName.unit_name,
  96. df.SourceFolderPath.normalized,
  97. df.TestEnv.value,
  98. df.UseArcadiaPython.value,
  99. df.LintFileProcessingTime.from_macro_args,
  100. df.Linter.value,
  101. df.CustomDependencies.depends_with_linter,
  102. )
  103. tidy_config_map = None
  104. def ontest_data(unit, *args):
  105. ymake.report_configure_error("TEST_DATA is removed in favour of DATA")
  106. def is_yt_spec_contain_pool_info(filename): # XXX switch to yson in ymake + perf test for configure
  107. pool_re = re.compile(r"""['"]*pool['"]*\s*?=""")
  108. cypress_root_re = re.compile(r"""['"]*cypress_root['"]*\s*=""")
  109. with open(filename, 'r') as afile:
  110. yt_spec = afile.read()
  111. return pool_re.search(yt_spec) and cypress_root_re.search(yt_spec)
  112. def validate_test(unit, kw):
  113. def get_list(key):
  114. return deserialize_list(kw.get(key, ""))
  115. valid_kw = copy.deepcopy(kw)
  116. errors = []
  117. warnings = []
  118. mandatory_fields = {"SCRIPT-REL-PATH", "SOURCE-FOLDER-PATH", "TEST-NAME"}
  119. for field in mandatory_fields - valid_kw.keys():
  120. errors.append(f"Mandatory field {field!r} is not set in DART")
  121. if valid_kw.get('SCRIPT-REL-PATH') == 'boost.test':
  122. project_path = valid_kw.get('BUILD-FOLDER-PATH', "")
  123. if not project_path.startswith(
  124. ("contrib", "mail", "maps", "tools/idl", "metrika", "devtools", "mds", "yandex_io", "smart_devices")
  125. ):
  126. errors.append("BOOSTTEST is not allowed here")
  127. size_timeout = collections.OrderedDict(sorted(consts.TestSize.DefaultTimeouts.items(), key=lambda t: t[1]))
  128. size = valid_kw.get('SIZE', consts.TestSize.Small).lower()
  129. tags = set(get_list("TAG"))
  130. requirements_orig = get_list("REQUIREMENTS")
  131. in_autocheck = consts.YaTestTags.NotAutocheck not in tags and consts.YaTestTags.Manual not in tags
  132. is_fat = consts.YaTestTags.Fat in tags
  133. is_force_sandbox = consts.YaTestTags.ForceDistbuild not in tags and is_fat
  134. is_ytexec_run = consts.YaTestTags.YtRunner in tags
  135. is_fuzzing = valid_kw.get("FUZZING", False)
  136. is_kvm = 'kvm' in requirements_orig
  137. requirements = {}
  138. secret_requirements = ('sb_vault', 'yav')
  139. list_requirements = secret_requirements
  140. for req in requirements_orig:
  141. if req in ('kvm',):
  142. requirements[req] = str(True)
  143. continue
  144. if ":" in req:
  145. req_name, req_value = req.split(":", 1)
  146. if req_name in list_requirements:
  147. requirements[req_name] = ",".join(filter(None, [requirements.get(req_name), req_value]))
  148. else:
  149. if req_name in requirements:
  150. if req_value in ["0"]:
  151. warnings.append(
  152. "Requirement [[imp]]{}[[rst]] is dropped [[imp]]{}[[rst]] -> [[imp]]{}[[rst]]".format(
  153. req_name, requirements[req_name], req_value
  154. )
  155. )
  156. del requirements[req_name]
  157. elif requirements[req_name] != req_value:
  158. warnings.append(
  159. "Requirement [[imp]]{}[[rst]] is redefined [[imp]]{}[[rst]] -> [[imp]]{}[[rst]]".format(
  160. req_name, requirements[req_name], req_value
  161. )
  162. )
  163. requirements[req_name] = req_value
  164. else:
  165. requirements[req_name] = req_value
  166. else:
  167. errors.append("Invalid requirement syntax [[imp]]{}[[rst]]: expect <requirement>:<value>".format(req))
  168. if not errors:
  169. for req_name, req_value in requirements.items():
  170. try:
  171. error_msg = reqs.validate_requirement(
  172. req_name,
  173. req_value,
  174. size,
  175. is_force_sandbox,
  176. in_autocheck,
  177. is_fuzzing,
  178. is_kvm,
  179. is_ytexec_run,
  180. requirements,
  181. )
  182. except Exception as e:
  183. error_msg = str(e)
  184. if error_msg:
  185. errors += [error_msg]
  186. invalid_requirements_for_distbuild = [
  187. requirement for requirement in requirements.keys() if requirement not in ('ram', 'ram_disk', 'cpu', 'network')
  188. ]
  189. sb_tags = []
  190. # XXX Unfortunately, some users have already started using colons
  191. # in their tag names. Use skip set to avoid treating their tag as system ones.
  192. # Remove this check when all such user tags are removed.
  193. skip_set = ('ynmt_benchmark', 'bert_models', 'zeliboba_map')
  194. # Verify the prefixes of the system tags to avoid pointless use of the REQUIREMENTS macro parameters in the TAG macro.
  195. for tag in tags:
  196. if tag.startswith('sb:'):
  197. sb_tags.append(tag)
  198. elif ':' in tag and not tag.startswith('ya:') and tag.split(':')[0] not in skip_set:
  199. errors.append(
  200. "Only [[imp]]sb:[[rst]] and [[imp]]ya:[[rst]] prefixes are allowed in system tags: {}".format(tag)
  201. )
  202. if is_fat:
  203. if size != consts.TestSize.Large:
  204. errors.append("Only LARGE test may have ya:fat tag")
  205. if in_autocheck and not is_force_sandbox:
  206. if invalid_requirements_for_distbuild:
  207. errors.append(
  208. "'{}' REQUIREMENTS options can be used only for FAT tests without ya:force_distbuild tag. Remove TAG(ya:force_distbuild) or an option.".format(
  209. invalid_requirements_for_distbuild
  210. )
  211. )
  212. if sb_tags:
  213. errors.append(
  214. "You can set sandbox tags '{}' only for FAT tests without ya:force_distbuild. Remove TAG(ya:force_sandbox) or sandbox tags.".format(
  215. sb_tags
  216. )
  217. )
  218. if consts.YaTestTags.SandboxCoverage in tags:
  219. errors.append("You can set 'ya:sandbox_coverage' tag only for FAT tests without ya:force_distbuild.")
  220. if is_ytexec_run:
  221. errors.append(
  222. "Running LARGE tests over YT (ya:yt) on Distbuild (ya:force_distbuild) is forbidden. Consider removing TAG(ya:force_distbuild)."
  223. )
  224. else:
  225. if is_force_sandbox:
  226. errors.append('ya:force_sandbox can be used with LARGE tests only')
  227. if consts.YaTestTags.Privileged in tags:
  228. errors.append("ya:privileged can be used with LARGE tests only")
  229. if in_autocheck and size == consts.TestSize.Large:
  230. errors.append("LARGE test must have ya:fat tag")
  231. if consts.YaTestTags.Privileged in tags and 'container' not in requirements:
  232. errors.append("Only tests with 'container' requirement can have 'ya:privileged' tag")
  233. if size not in size_timeout:
  234. errors.append(
  235. "Unknown test size: [[imp]]{}[[rst]], choose from [[imp]]{}[[rst]]".format(
  236. size.upper(), ", ".join([sz.upper() for sz in size_timeout.keys()])
  237. )
  238. )
  239. else:
  240. try:
  241. timeout = int(valid_kw.get('TEST-TIMEOUT', size_timeout[size]) or size_timeout[size])
  242. script_rel_path = valid_kw.get('SCRIPT-REL-PATH')
  243. if timeout < 0:
  244. raise Exception("Timeout must be > 0")
  245. skip_timeout_verification = script_rel_path in ('java.style', 'ktlint')
  246. if size_timeout[size] < timeout and in_autocheck and not skip_timeout_verification:
  247. suggested_size = None
  248. for s, t in size_timeout.items():
  249. if timeout <= t:
  250. suggested_size = s
  251. break
  252. if suggested_size:
  253. suggested_size = ", suggested size: [[imp]]{}[[rst]]".format(suggested_size.upper())
  254. else:
  255. suggested_size = ""
  256. errors.append(
  257. "Max allowed timeout for test size [[imp]]{}[[rst]] is [[imp]]{} sec[[rst]]{}".format(
  258. size.upper(), size_timeout[size], suggested_size
  259. )
  260. )
  261. except Exception as e:
  262. errors.append("Error when parsing test timeout: [[bad]]{}[[rst]]".format(e))
  263. requirements_list = []
  264. for req_name, req_value in six.iteritems(requirements):
  265. requirements_list.append(req_name + ":" + req_value)
  266. valid_kw['REQUIREMENTS'] = serialize_list(sorted(requirements_list))
  267. # Mark test with ya:external tag if it requests any secret from external storages
  268. # It's not stable and nonreproducible by definition
  269. for x in secret_requirements:
  270. if x in requirements:
  271. tags.add(consts.YaTestTags.External)
  272. if valid_kw.get("FUZZ-OPTS"):
  273. for option in get_list("FUZZ-OPTS"):
  274. if not option.startswith("-"):
  275. errors.append(
  276. "Unrecognized fuzzer option '[[imp]]{}[[rst]]'. All fuzzer options should start with '-'".format(
  277. option
  278. )
  279. )
  280. break
  281. eqpos = option.find("=")
  282. if eqpos == -1 or len(option) == eqpos + 1:
  283. errors.append(
  284. "Unrecognized fuzzer option '[[imp]]{}[[rst]]'. All fuzzer options should obtain value specified after '='".format(
  285. option
  286. )
  287. )
  288. break
  289. if option[eqpos - 1] == " " or option[eqpos + 1] == " ":
  290. errors.append("Spaces are not allowed: '[[imp]]{}[[rst]]'".format(option))
  291. break
  292. if option[:eqpos] in ("-runs", "-dict", "-jobs", "-workers", "-artifact_prefix", "-print_final_stats"):
  293. errors.append(
  294. "You can't use '[[imp]]{}[[rst]]' - it will be automatically calculated or configured during run".format(
  295. option
  296. )
  297. )
  298. break
  299. if valid_kw.get("YT-SPEC"):
  300. if not is_ytexec_run:
  301. errors.append("You can use YT_SPEC macro only tests marked with ya:yt tag")
  302. else:
  303. for filename in get_list("YT-SPEC"):
  304. filename = unit.resolve('$S/' + filename)
  305. if not os.path.exists(filename):
  306. errors.append("File '{}' specified in the YT_SPEC macro doesn't exist".format(filename))
  307. continue
  308. if not is_yt_spec_contain_pool_info(filename):
  309. tags.add(consts.YaTestTags.External)
  310. tags.add("ya:yt_research_pool")
  311. partition = valid_kw.get('TEST_PARTITION', 'SEQUENTIAL')
  312. if partition not in PARTITION_MODS:
  313. raise ValueError('partition mode should be one of {}, detected: {}'.format(PARTITION_MODS, partition))
  314. if valid_kw.get('SPLIT-FACTOR'):
  315. if valid_kw.get('FORK-MODE') == 'none':
  316. errors.append('SPLIT_FACTOR must be use with FORK_TESTS() or FORK_SUBTESTS() macro')
  317. value = 1
  318. try:
  319. value = int(valid_kw.get('SPLIT-FACTOR'))
  320. if value <= 0:
  321. raise ValueError("must be > 0")
  322. if value > SPLIT_FACTOR_MAX_VALUE:
  323. raise ValueError("the maximum allowed value is {}".format(SPLIT_FACTOR_MAX_VALUE))
  324. except ValueError as e:
  325. errors.append('Incorrect SPLIT_FACTOR value: {}'.format(e))
  326. if valid_kw.get('FORK-TEST-FILES') and size != consts.TestSize.Large:
  327. nfiles = count_entries(valid_kw.get('TEST-FILES'))
  328. if nfiles * value > SPLIT_FACTOR_TEST_FILES_MAX_VALUE:
  329. errors.append(
  330. 'Too much chunks generated:{} (limit: {}). Remove FORK_TEST_FILES() macro or reduce SPLIT_FACTOR({}).'.format(
  331. nfiles * value, SPLIT_FACTOR_TEST_FILES_MAX_VALUE, value
  332. )
  333. )
  334. if tags:
  335. valid_kw['TAG'] = serialize_list(sorted(tags))
  336. unit_path = _common.get_norm_unit_path(unit)
  337. if (
  338. not is_fat
  339. and consts.YaTestTags.Noretries in tags
  340. and not is_ytexec_run
  341. and not unit_path.startswith("devtools/dummy_arcadia/test/noretries")
  342. ):
  343. errors.append("Only LARGE tests can have 'ya:noretries' tag")
  344. if errors:
  345. return None, warnings, errors
  346. return valid_kw, warnings, errors
  347. def dump_test(unit, kw):
  348. kw = {k: v for k, v in kw.items() if v and (not isinstance(v, str | bytes) or v.strip())}
  349. valid_kw, warnings, errors = validate_test(unit, kw)
  350. for w in warnings:
  351. unit.message(['warn', w])
  352. for e in errors:
  353. ymake.report_configure_error(e)
  354. if valid_kw is None:
  355. return None
  356. string_handler = StringIO()
  357. for k, v in six.iteritems(valid_kw):
  358. print(k + ': ' + six.ensure_str(v), file=string_handler)
  359. print(BLOCK_SEPARATOR, file=string_handler)
  360. data = string_handler.getvalue()
  361. string_handler.close()
  362. return data
  363. def count_entries(x):
  364. # see (de)serialize_list
  365. assert x is None or isinstance(x, str), type(x)
  366. if not x:
  367. return 0
  368. return x.count(";") + 1
  369. def implies(a, b):
  370. return bool((not a) or b)
  371. def match_coverage_extractor_requirements(unit):
  372. # we add test if
  373. return all(
  374. (
  375. # tests are requested
  376. unit.get("TESTS_REQUESTED") == "yes",
  377. # build implies clang coverage, which supports segment extraction from the binaries
  378. unit.get("CLANG_COVERAGE") == "yes",
  379. # contrib was requested
  380. implies(
  381. _common.get_norm_unit_path(unit).startswith("contrib/"), unit.get("ENABLE_CONTRIB_COVERAGE") == "yes"
  382. ),
  383. )
  384. )
  385. def get_tidy_config_map(unit, map_path):
  386. config_map_path = unit.resolve(os.path.join("$S", map_path))
  387. config_map = {}
  388. try:
  389. with open(config_map_path, 'r') as afile:
  390. config_map = json.load(afile)
  391. except ValueError:
  392. ymake.report_configure_error("{} is invalid json".format(map_path))
  393. except Exception as e:
  394. ymake.report_configure_error(str(e))
  395. return config_map
  396. def prepare_config_map(config_map):
  397. return list(reversed(sorted(config_map.items())))
  398. def get_default_tidy_config(unit):
  399. unit_path = _common.get_norm_unit_path(unit)
  400. tidy_default_config_map = prepare_config_map(get_tidy_config_map(unit, DEFAULT_TIDY_CONFIG_MAP_PATH))
  401. for project_prefix, config_path in tidy_default_config_map:
  402. if unit_path.startswith(project_prefix):
  403. return config_path
  404. return DEFAULT_TIDY_CONFIG
  405. ordered_tidy_map = None
  406. def get_project_tidy_config(unit):
  407. global ordered_tidy_map
  408. if ordered_tidy_map is None:
  409. ordered_tidy_map = prepare_config_map(get_tidy_config_map(unit, PROJECT_TIDY_CONFIG_MAP_PATH))
  410. unit_path = _common.get_norm_unit_path(unit)
  411. for project_prefix, config_path in ordered_tidy_map:
  412. if unit_path.startswith(project_prefix):
  413. return config_path
  414. else:
  415. return get_default_tidy_config(unit)
  416. @df.with_fields(
  417. CHECK_FIELDS_BASE
  418. + (
  419. df.TestedProjectName.normalized_basename,
  420. df.SourceFolderPath.normalized,
  421. df.SbrUidExt.value,
  422. df.TestFiles.value,
  423. )
  424. )
  425. def check_data(fields, unit, *args):
  426. flat_args, spec_args = _common.sort_by_keywords(
  427. {
  428. "DEPENDS": -1,
  429. "TIMEOUT": 1,
  430. "DATA": -1,
  431. "TAG": -1,
  432. "REQUIREMENTS": -1,
  433. "FORK_MODE": 1,
  434. "SPLIT_FACTOR": 1,
  435. "FORK_SUBTESTS": 0,
  436. "FORK_TESTS": 0,
  437. "SIZE": 1,
  438. },
  439. args,
  440. )
  441. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  442. if not dart_record[df.TestFiles.KEY]:
  443. return
  444. data = dump_test(unit, dart_record)
  445. if data:
  446. unit.set_property(["DART_DATA", data])
  447. @df.with_fields(
  448. CHECK_FIELDS_BASE
  449. + (
  450. df.TestedProjectName.normalized_basename,
  451. df.SourceFolderPath.normalized,
  452. df.SbrUidExt.value,
  453. df.TestFiles.flat_args_wo_first,
  454. )
  455. )
  456. def check_resource(fields, unit, *args):
  457. flat_args, spec_args = _common.sort_by_keywords(
  458. {
  459. "DEPENDS": -1,
  460. "TIMEOUT": 1,
  461. "DATA": -1,
  462. "TAG": -1,
  463. "REQUIREMENTS": -1,
  464. "FORK_MODE": 1,
  465. "SPLIT_FACTOR": 1,
  466. "FORK_SUBTESTS": 0,
  467. "FORK_TESTS": 0,
  468. "SIZE": 1,
  469. },
  470. args,
  471. )
  472. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  473. data = dump_test(unit, dart_record)
  474. if data:
  475. unit.set_property(["DART_DATA", data])
  476. @df.with_fields(
  477. CHECK_FIELDS_BASE
  478. + (
  479. df.TestedProjectName.normalized_basename,
  480. df.SourceFolderPath.normalized,
  481. df.TestData.ktlint,
  482. df.TestFiles.flat_args_wo_first,
  483. df.ModuleLang.value,
  484. df.KtlintBinary.value,
  485. df.UseKtlintOld.value,
  486. df.KtlintBaselineFile.value,
  487. )
  488. )
  489. def ktlint(fields, unit, *args):
  490. flat_args, spec_args = _common.sort_by_keywords(
  491. {
  492. "DEPENDS": -1,
  493. "TIMEOUT": 1,
  494. "DATA": -1,
  495. "TAG": -1,
  496. "REQUIREMENTS": -1,
  497. "FORK_MODE": 1,
  498. "SPLIT_FACTOR": 1,
  499. "FORK_SUBTESTS": 0,
  500. "FORK_TESTS": 0,
  501. "SIZE": 1,
  502. },
  503. args,
  504. )
  505. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  506. dart_record[df.TestTimeout.KEY] = '120'
  507. data = dump_test(unit, dart_record)
  508. if data:
  509. unit.set_property(["DART_DATA", data])
  510. @df.with_fields(
  511. CHECK_FIELDS_BASE
  512. + (
  513. df.TestedProjectName.normalized_basename,
  514. df.SourceFolderPath.normalized,
  515. df.TestData.java_style,
  516. df.ForkMode.test_fork_mode,
  517. df.TestFiles.java_style,
  518. df.JdkLatestVersion.value,
  519. df.JdkResource.value,
  520. df.ModuleLang.value,
  521. )
  522. )
  523. def java_style(fields, unit, *args):
  524. flat_args, spec_args = _common.sort_by_keywords(
  525. {
  526. "DEPENDS": -1,
  527. "TIMEOUT": 1,
  528. "DATA": -1,
  529. "TAG": -1,
  530. "REQUIREMENTS": -1,
  531. "FORK_MODE": 1,
  532. "SPLIT_FACTOR": 1,
  533. "FORK_SUBTESTS": 0,
  534. "FORK_TESTS": 0,
  535. "SIZE": 1,
  536. },
  537. args,
  538. )
  539. if len(flat_args) < 2:
  540. raise Exception("Not enough arguments for JAVA_STYLE check")
  541. # jstyle should use the latest jdk
  542. unit.onpeerdir([unit.get('JDK_LATEST_PEERDIR')])
  543. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  544. dart_record[df.TestTimeout.KEY] = '240'
  545. dart_record[df.ScriptRelPath.KEY] = 'java.style'
  546. data = dump_test(unit, dart_record)
  547. if data:
  548. unit.set_property(["DART_DATA", data])
  549. @df.with_fields(
  550. CHECK_FIELDS_BASE
  551. + (
  552. df.TestedProjectName.test_dir,
  553. df.SourceFolderPath.test_dir,
  554. df.ForkMode.test_fork_mode,
  555. df.TestFiles.flat_args_wo_first,
  556. df.ModuleLang.value,
  557. )
  558. )
  559. def gofmt(fields, unit, *args):
  560. flat_args, spec_args = _common.sort_by_keywords(
  561. {
  562. "DEPENDS": -1,
  563. "TIMEOUT": 1,
  564. "DATA": -1,
  565. "TAG": -1,
  566. "REQUIREMENTS": -1,
  567. "FORK_MODE": 1,
  568. "SPLIT_FACTOR": 1,
  569. "FORK_SUBTESTS": 0,
  570. "FORK_TESTS": 0,
  571. "SIZE": 1,
  572. },
  573. args,
  574. )
  575. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  576. data = dump_test(unit, dart_record)
  577. if data:
  578. unit.set_property(["DART_DATA", data])
  579. @df.with_fields(
  580. CHECK_FIELDS_BASE
  581. + (
  582. df.TestedProjectName.normalized_basename,
  583. df.SourceFolderPath.normalized,
  584. df.ForkMode.test_fork_mode,
  585. df.TestFiles.flat_args_wo_first,
  586. df.ModuleLang.value,
  587. )
  588. )
  589. def govet(fields, unit, *args):
  590. flat_args, spec_args = _common.sort_by_keywords(
  591. {
  592. "DEPENDS": -1,
  593. "TIMEOUT": 1,
  594. "DATA": -1,
  595. "TAG": -1,
  596. "REQUIREMENTS": -1,
  597. "FORK_MODE": 1,
  598. "SPLIT_FACTOR": 1,
  599. "FORK_SUBTESTS": 0,
  600. "FORK_TESTS": 0,
  601. "SIZE": 1,
  602. },
  603. args,
  604. )
  605. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  606. data = dump_test(unit, dart_record)
  607. if data:
  608. unit.set_property(["DART_DATA", data])
  609. @df.with_fields(
  610. CHECK_FIELDS_BASE
  611. + (
  612. df.TestedProjectName.normalized_basename,
  613. df.SourceFolderPath.normalized,
  614. df.TestFiles.flat_args_wo_first,
  615. df.ModuleLang.value,
  616. )
  617. )
  618. def detekt_report(fields, unit, *args):
  619. flat_args, spec_args = _common.sort_by_keywords(
  620. {
  621. "DEPENDS": -1,
  622. "TIMEOUT": 1,
  623. "DATA": -1,
  624. "TAG": -1,
  625. "REQUIREMENTS": -1,
  626. "FORK_MODE": 1,
  627. "SPLIT_FACTOR": 1,
  628. "FORK_SUBTESTS": 0,
  629. "FORK_TESTS": 0,
  630. "SIZE": 1,
  631. },
  632. args,
  633. )
  634. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  635. data = dump_test(unit, dart_record)
  636. if data:
  637. unit.set_property(["DART_DATA", data])
  638. def onadd_check(unit, *args):
  639. if unit.get("TIDY") == "yes":
  640. # graph changed for clang_tidy tests
  641. return
  642. flat_args, *_ = _common.sort_by_keywords(
  643. {
  644. "DEPENDS": -1,
  645. "TIMEOUT": 1,
  646. "DATA": -1,
  647. "TAG": -1,
  648. "REQUIREMENTS": -1,
  649. "FORK_MODE": 1,
  650. "SPLIT_FACTOR": 1,
  651. "FORK_SUBTESTS": 0,
  652. "FORK_TESTS": 0,
  653. "SIZE": 1,
  654. },
  655. args,
  656. )
  657. check_type = flat_args[0]
  658. if check_type == "check.data" and unit.get('VALIDATE_DATA') != "no":
  659. check_data(unit, *args)
  660. elif check_type == "check.resource" and unit.get('VALIDATE_DATA') != "no":
  661. check_resource(unit, *args)
  662. elif check_type == "ktlint":
  663. ktlint(unit, *args)
  664. elif check_type == "JAVA_STYLE" and (unit.get('YMAKE_JAVA_TEST') != 'yes' or unit.get('ALL_SRCDIRS')):
  665. java_style(unit, *args)
  666. elif check_type == "gofmt":
  667. gofmt(unit, *args)
  668. elif check_type == "govet":
  669. govet(unit, *args)
  670. elif check_type == "detekt.report":
  671. detekt_report(unit, *args)
  672. def on_register_no_check_imports(unit):
  673. s = unit.get('NO_CHECK_IMPORTS_FOR_VALUE')
  674. if s not in ('', 'None'):
  675. unit.onresource(['-', 'py/no_check_imports/{}="{}"'.format(_common.pathid(s), s)])
  676. @df.with_fields(
  677. (
  678. df.TestedProjectName.normalized_basename,
  679. df.SourceFolderPath.normalized,
  680. df.TestEnv.value,
  681. df.UseArcadiaPython.value,
  682. df.TestFiles.normalized,
  683. df.ModuleLang.value,
  684. df.NoCheck.value,
  685. )
  686. )
  687. def onadd_check_py_imports(fields, unit, *args):
  688. if unit.get("TIDY") == "yes":
  689. # graph changed for clang_tidy tests
  690. return
  691. if unit.get('NO_CHECK_IMPORTS_FOR_VALUE').strip() == "":
  692. return
  693. unit.onpeerdir(['library/python/testing/import_test'])
  694. dart_record = create_dart_record(fields, unit, (), {})
  695. dart_record[df.TestName.KEY] = 'pyimports'
  696. dart_record[df.ScriptRelPath.KEY] = 'py.imports'
  697. data = dump_test(unit, dart_record)
  698. if data:
  699. unit.set_property(["DART_DATA", data])
  700. @df.with_fields(
  701. PY_EXEC_FIELDS_BASE
  702. + (
  703. df.TestName.filename_without_ext,
  704. df.ScriptRelPath.pytest,
  705. df.TestedProjectName.path_filename_basename,
  706. df.ModuleLang.value,
  707. df.BinaryPath.stripped,
  708. df.TestRunnerBin.value,
  709. df.DockerImage.value,
  710. )
  711. )
  712. def onadd_pytest_bin(fields, unit, *args):
  713. if unit.get("TIDY") == "yes":
  714. # graph changed for clang_tidy tests
  715. return
  716. flat_args, spec_args = _common.sort_by_keywords({'RUNNER_BIN': 1}, args)
  717. if flat_args:
  718. ymake.report_configure_error(
  719. 'Unknown arguments found while processing add_pytest_bin macro: {!r}'.format(flat_args)
  720. )
  721. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  722. unit.ondata_files(_common.get_norm_unit_path(unit))
  723. yt_spec = df.YtSpec.from_unit(unit, flat_args, spec_args)
  724. if yt_spec and yt_spec[df.YtSpec.KEY]:
  725. unit.ondata_files(deserialize_list(yt_spec[df.YtSpec.KEY]))
  726. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  727. if yt_spec:
  728. dart_record |= yt_spec
  729. data = dump_test(unit, dart_record)
  730. if data:
  731. unit.set_property(["DART_DATA", data])
  732. @df.with_fields(
  733. (
  734. df.SourceFolderPath.normalized,
  735. df.TestName.normalized_joined_dir_basename,
  736. df.ScriptRelPath.junit,
  737. df.TestTimeout.from_unit,
  738. df.TestedProjectName.normalized,
  739. df.TestEnv.value,
  740. df.TestData.java_test,
  741. df.ForkMode.test_fork_mode,
  742. df.SplitFactor.from_unit,
  743. df.CustomDependencies.test_depends_only,
  744. df.Tag.from_macro_args_and_unit,
  745. df.Size.from_unit,
  746. df.Requirements.with_maybe_fuzzing,
  747. df.TestRecipes.value,
  748. df.ModuleType.value,
  749. df.UnittestDir.value,
  750. df.JvmArgs.value,
  751. # TODO optimize, SystemProperties is used in TestData
  752. df.SystemProperties.value,
  753. df.TestCwd.from_unit,
  754. df.SkipTest.value,
  755. df.JavaClasspathCmdType.value,
  756. df.JdkResource.value,
  757. df.JdkForTests.value,
  758. df.ModuleLang.value,
  759. df.TestClasspath.value,
  760. df.TestClasspathOrigins.value,
  761. df.TestClasspathDeps.value,
  762. df.TestJar.value,
  763. df.DockerImage.value,
  764. )
  765. )
  766. def onjava_test(fields, unit, *args):
  767. if unit.get("TIDY") == "yes":
  768. # graph changed for clang_tidy tests
  769. return
  770. assert unit.get('MODULE_TYPE') is not None
  771. if unit.get('MODULE_TYPE') == 'JTEST_FOR':
  772. if not unit.get('UNITTEST_DIR'):
  773. ymake.report_configure_error('skip JTEST_FOR in {}: no args provided'.format(unit.path()))
  774. return
  775. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  776. unit.ondata_files(_common.get_norm_unit_path(unit))
  777. yt_spec = df.YtSpec.from_unit_list_var(unit, (), {})
  778. unit.ondata_files(deserialize_list(yt_spec[df.YtSpec.KEY]))
  779. try:
  780. dart_record = create_dart_record(fields, unit, (), {})
  781. except df.DartValueError:
  782. return
  783. dart_record |= yt_spec
  784. data = dump_test(unit, dart_record)
  785. if data:
  786. unit.set_property(['DART_DATA', data])
  787. @df.with_fields(
  788. (
  789. df.SourceFolderPath.normalized,
  790. df.TestName.normalized_joined_dir_basename_deps,
  791. df.TestedProjectName.normalized,
  792. df.CustomDependencies.test_depends_only,
  793. df.IgnoreClasspathClash.value,
  794. df.ModuleType.value,
  795. df.ModuleLang.value,
  796. df.Classpath.value,
  797. )
  798. )
  799. def onjava_test_deps(fields, unit, *args):
  800. if unit.get("TIDY") == "yes":
  801. # graph changed for clang_tidy tests
  802. return
  803. assert unit.get('MODULE_TYPE') is not None
  804. assert len(args) == 1
  805. mode = args[0]
  806. dart_record = create_dart_record(fields, unit, (args[0],), {})
  807. dart_record[df.ScriptRelPath.KEY] = 'java.dependency.test'
  808. if mode == 'strict':
  809. dart_record[df.StrictClasspathClash.KEY] = 'yes'
  810. data = dump_test(unit, dart_record)
  811. unit.set_property(['DART_DATA', data])
  812. def onsetup_pytest_bin(unit, *args):
  813. use_arcadia_python = unit.get('USE_ARCADIA_PYTHON') == "yes"
  814. if use_arcadia_python:
  815. unit.onresource(['-', 'PY_MAIN={}'.format("library.python.pytest.main:main")]) # XXX
  816. unit.onadd_pytest_bin(list(args))
  817. def onrun(unit, *args):
  818. exectest_cmd = unit.get(["EXECTEST_COMMAND_VALUE"]) or ''
  819. exectest_cmd += "\n" + subprocess.list2cmdline(args)
  820. unit.set(["EXECTEST_COMMAND_VALUE", exectest_cmd])
  821. @df.with_fields(
  822. PY_EXEC_FIELDS_BASE
  823. + (
  824. df.TestName.filename_without_pkg_ext,
  825. df.TestedProjectName.path_filename_basename_without_pkg_ext,
  826. df.BinaryPath.stripped_without_pkg_ext,
  827. df.DockerImage.value,
  828. )
  829. )
  830. def onsetup_exectest(fields, unit, *args):
  831. if unit.get("TIDY") == "yes":
  832. # graph changed for clang_tidy tests
  833. return
  834. command = unit.get(["EXECTEST_COMMAND_VALUE"])
  835. if command is None:
  836. ymake.report_configure_error("EXECTEST must have at least one RUN macro")
  837. return
  838. command = command.replace("$EXECTEST_COMMAND_VALUE", "")
  839. if "PYTHON_BIN" in command:
  840. unit.ondepends('contrib/tools/python')
  841. unit.set(["TEST_BLOB_DATA", base64.b64encode(six.ensure_binary(command))])
  842. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  843. unit.ondata_files(_common.get_norm_unit_path(unit))
  844. yt_spec = df.YtSpec.from_unit(unit, (), {})
  845. if yt_spec and yt_spec[df.YtSpec.KEY]:
  846. unit.ondata_files(deserialize_list(yt_spec[df.YtSpec.KEY]))
  847. dart_record = create_dart_record(fields, unit, (), {})
  848. dart_record[df.ScriptRelPath.KEY] = 'exectest'
  849. if yt_spec:
  850. dart_record |= yt_spec
  851. data = dump_test(unit, dart_record)
  852. if data:
  853. unit.set_property(["DART_DATA", data])
  854. def onsetup_run_python(unit):
  855. if unit.get("USE_ARCADIA_PYTHON") == "yes":
  856. unit.ondepends('contrib/tools/python')
  857. @df.with_fields(
  858. (
  859. df.TestFiles.cpp_linter_files,
  860. df.LintConfigs.cpp_configs,
  861. )
  862. + LINTER_FIELDS_BASE
  863. )
  864. def on_add_cpp_linter_check(fields, unit, *args):
  865. if unit.get("TIDY") == "yes":
  866. return
  867. no_lint_value = _common.get_no_lint_value(unit)
  868. if no_lint_value in ("none", "none_internal"):
  869. return
  870. unlimited = -1
  871. keywords = {
  872. "NAME": 1,
  873. "LINTER": 1,
  874. "DEPENDS": unlimited,
  875. "CONFIGS": 1,
  876. "CUSTOM_CONFIG": 1,
  877. "GLOBAL_RESOURCES": unlimited,
  878. "FILE_PROCESSING_TIME": 1,
  879. "EXTRA_PARAMS": unlimited,
  880. }
  881. _, spec_args = _common.sort_by_keywords(keywords, args)
  882. global_resources = spec_args.get('GLOBAL_RESOURCES', [])
  883. for resource in global_resources:
  884. unit.onpeerdir(resource)
  885. try:
  886. dart_record = create_dart_record(fields, unit, (), spec_args)
  887. except df.DartValueError as e:
  888. if msg := str(e):
  889. unit.message(['WARN', msg])
  890. return
  891. dart_record[df.ScriptRelPath.KEY] = 'custom_lint'
  892. data = dump_test(unit, dart_record)
  893. if data:
  894. unit.set_property(["DART_DATA", data])
  895. @df.with_fields(
  896. (
  897. df.TestFiles.py_linter_files,
  898. df.LintConfigs.python_configs,
  899. )
  900. + LINTER_FIELDS_BASE
  901. )
  902. def on_add_py_linter_check(fields, unit, *args):
  903. if unit.get("TIDY") == "yes":
  904. return
  905. no_lint_value = _common.get_no_lint_value(unit)
  906. if no_lint_value in ("none", "none_internal"):
  907. return
  908. unlimited = -1
  909. keywords = {
  910. "NAME": 1,
  911. "LINTER": 1,
  912. "DEPENDS": unlimited,
  913. "CONFIGS": 1,
  914. "GLOBAL_RESOURCES": unlimited,
  915. "FILE_PROCESSING_TIME": 1,
  916. "EXTRA_PARAMS": unlimited,
  917. "PROJECT_TO_CONFIG_MAP": 1,
  918. "FLAKE_MIGRATIONS_CONFIG": 1,
  919. "CUSTOM_CONFIG": 1,
  920. }
  921. _, spec_args = _common.sort_by_keywords(keywords, args)
  922. global_resources = spec_args.get('GLOBAL_RESOURCES', [])
  923. for resource in global_resources:
  924. unit.onpeerdir(resource)
  925. try:
  926. dart_record = create_dart_record(fields, unit, (), spec_args)
  927. except df.DartValueError as e:
  928. if msg := str(e):
  929. unit.message(['WARN', msg])
  930. return
  931. dart_record[df.ScriptRelPath.KEY] = 'custom_lint'
  932. data = dump_test(unit, dart_record)
  933. if data:
  934. unit.set_property(["DART_DATA", data])
  935. @df.with_fields(
  936. YTEST_FIELDS_BASE
  937. + (
  938. df.TestName.value,
  939. df.TestPartition.value,
  940. df.ModuleLang.value,
  941. )
  942. )
  943. def clang_tidy(fields, unit, *args):
  944. keywords = {
  945. "DEPENDS": -1,
  946. "DATA": -1,
  947. "TIMEOUT": 1,
  948. "FORK_MODE": 1,
  949. "SPLIT_FACTOR": 1,
  950. "FORK_SUBTESTS": 0,
  951. "FORK_TESTS": 0,
  952. }
  953. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  954. if unit.get("TIDY_CONFIG"):
  955. default_config_path = unit.get("TIDY_CONFIG")
  956. project_config_path = unit.get("TIDY_CONFIG")
  957. else:
  958. default_config_path = get_default_tidy_config(unit)
  959. project_config_path = get_project_tidy_config(unit)
  960. unit.set(["DEFAULT_TIDY_CONFIG", default_config_path])
  961. unit.set(["PROJECT_TIDY_CONFIG", project_config_path])
  962. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  963. data = dump_test(unit, dart_record)
  964. if data:
  965. unit.set_property(["DART_DATA", data])
  966. @df.with_fields(
  967. YTEST_FIELDS_BASE
  968. + YTEST_FIELDS_EXTRA
  969. + (
  970. df.TestName.value,
  971. df.TestData.from_macro_args_and_unit,
  972. df.Requirements.from_macro_args_and_unit,
  973. df.TestPartition.value,
  974. df.ModuleLang.value,
  975. df.DockerImage.value,
  976. )
  977. )
  978. def unittest_py(fields, unit, *args):
  979. keywords = {
  980. "DEPENDS": -1,
  981. "DATA": -1,
  982. "TIMEOUT": 1,
  983. "FORK_MODE": 1,
  984. "SPLIT_FACTOR": 1,
  985. "FORK_SUBTESTS": 0,
  986. "FORK_TESTS": 0,
  987. }
  988. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  989. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  990. unit.ondata_files(_common.get_norm_unit_path(unit))
  991. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  992. data = dump_test(unit, dart_record)
  993. if data:
  994. unit.set_property(["DART_DATA", data])
  995. @df.with_fields(
  996. YTEST_FIELDS_BASE
  997. + YTEST_FIELDS_EXTRA
  998. + (
  999. df.TestName.value,
  1000. df.TestData.from_macro_args_and_unit,
  1001. df.Requirements.from_macro_args_and_unit,
  1002. df.TestPartition.value,
  1003. df.ModuleLang.value,
  1004. df.DockerImage.value,
  1005. )
  1006. )
  1007. def gunittest(fields, unit, *args):
  1008. keywords = {
  1009. "DEPENDS": -1,
  1010. "DATA": -1,
  1011. "TIMEOUT": 1,
  1012. "FORK_MODE": 1,
  1013. "SPLIT_FACTOR": 1,
  1014. "FORK_SUBTESTS": 0,
  1015. "FORK_TESTS": 0,
  1016. }
  1017. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1018. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  1019. unit.ondata_files(_common.get_norm_unit_path(unit))
  1020. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1021. data = dump_test(unit, dart_record)
  1022. if data:
  1023. unit.set_property(["DART_DATA", data])
  1024. @df.with_fields(
  1025. YTEST_FIELDS_BASE
  1026. + YTEST_FIELDS_EXTRA
  1027. + (
  1028. df.TestName.value,
  1029. df.TestData.from_macro_args_and_unit,
  1030. df.Requirements.from_macro_args_and_unit,
  1031. df.TestPartition.value,
  1032. df.ModuleLang.value,
  1033. df.BenchmarkOpts.value,
  1034. df.DockerImage.value,
  1035. )
  1036. )
  1037. def g_benchmark(fields, unit, *args):
  1038. keywords = {
  1039. "DEPENDS": -1,
  1040. "DATA": -1,
  1041. "TIMEOUT": 1,
  1042. "FORK_MODE": 1,
  1043. "SPLIT_FACTOR": 1,
  1044. "FORK_SUBTESTS": 0,
  1045. "FORK_TESTS": 0,
  1046. }
  1047. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1048. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  1049. unit.ondata_files(_common.get_norm_unit_path(unit))
  1050. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1051. data = dump_test(unit, dart_record)
  1052. if data:
  1053. unit.set_property(["DART_DATA", data])
  1054. @df.with_fields(
  1055. YTEST_FIELDS_BASE
  1056. + YTEST_FIELDS_EXTRA
  1057. + (
  1058. df.TestName.value,
  1059. df.TestData.from_macro_args_and_unit_with_canonical,
  1060. df.Requirements.from_macro_args_and_unit,
  1061. df.TestPartition.value,
  1062. df.ModuleLang.value,
  1063. df.DockerImage.value,
  1064. )
  1065. )
  1066. def go_test(fields, unit, *args):
  1067. keywords = {
  1068. "DEPENDS": -1,
  1069. "DATA": -1,
  1070. "TIMEOUT": 1,
  1071. "FORK_MODE": 1,
  1072. "SPLIT_FACTOR": 1,
  1073. "FORK_SUBTESTS": 0,
  1074. "FORK_TESTS": 0,
  1075. }
  1076. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1077. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  1078. unit.ondata_files(_common.get_norm_unit_path(unit))
  1079. unit.ondata_files(get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE'))
  1080. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1081. data = dump_test(unit, dart_record)
  1082. if data:
  1083. unit.set_property(["DART_DATA", data])
  1084. @df.with_fields(
  1085. YTEST_FIELDS_BASE
  1086. + YTEST_FIELDS_EXTRA
  1087. + (
  1088. df.TestName.value,
  1089. df.TestData.from_macro_args_and_unit,
  1090. df.Requirements.from_macro_args_and_unit,
  1091. df.TestPartition.value,
  1092. df.DockerImage.value,
  1093. )
  1094. )
  1095. def boost_test(fields, unit, *args):
  1096. keywords = {
  1097. "DEPENDS": -1,
  1098. "DATA": -1,
  1099. "TIMEOUT": 1,
  1100. "FORK_MODE": 1,
  1101. "SPLIT_FACTOR": 1,
  1102. "FORK_SUBTESTS": 0,
  1103. "FORK_TESTS": 0,
  1104. }
  1105. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1106. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  1107. unit.ondata_files(_common.get_norm_unit_path(unit))
  1108. unit.ondata_files(get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE'))
  1109. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1110. data = dump_test(unit, dart_record)
  1111. if data:
  1112. unit.set_property(["DART_DATA", data])
  1113. @df.with_fields(
  1114. YTEST_FIELDS_BASE
  1115. + YTEST_FIELDS_EXTRA
  1116. + (
  1117. df.TestName.value,
  1118. df.TestData.from_macro_args_and_unit,
  1119. df.Requirements.with_maybe_fuzzing,
  1120. df.FuzzDicts.value,
  1121. df.FuzzOpts.value,
  1122. df.Fuzzing.value,
  1123. df.DockerImage.value,
  1124. )
  1125. )
  1126. def fuzz_test(fields, unit, *args):
  1127. keywords = {
  1128. "DEPENDS": -1,
  1129. "DATA": -1,
  1130. "TIMEOUT": 1,
  1131. "FORK_MODE": 1,
  1132. "SPLIT_FACTOR": 1,
  1133. "FORK_SUBTESTS": 0,
  1134. "FORK_TESTS": 0,
  1135. }
  1136. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1137. if unit.get('ADD_SRCDIR_TO_TEST_DATA') == "yes":
  1138. unit.ondata_files(_common.get_norm_unit_path(unit))
  1139. unit.ondata_files("fuzzing/{}/corpus.json".format(_common.get_norm_unit_path(unit)))
  1140. unit.ondata_files(get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE'))
  1141. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1142. data = dump_test(unit, dart_record)
  1143. if data:
  1144. unit.set_property(["DART_DATA", data])
  1145. @df.with_fields(
  1146. YTEST_FIELDS_BASE
  1147. + YTEST_FIELDS_EXTRA
  1148. + (
  1149. df.TestName.value,
  1150. df.TestData.from_macro_args_and_unit,
  1151. df.Requirements.from_macro_args_and_unit,
  1152. df.TestPartition.value,
  1153. df.ModuleLang.value,
  1154. df.BenchmarkOpts.value,
  1155. df.DockerImage.value,
  1156. )
  1157. )
  1158. def y_benchmark(fields, unit, *args):
  1159. keywords = {
  1160. "DEPENDS": -1,
  1161. "DATA": -1,
  1162. "TIMEOUT": 1,
  1163. "FORK_MODE": 1,
  1164. "SPLIT_FACTOR": 1,
  1165. "FORK_SUBTESTS": 0,
  1166. "FORK_TESTS": 0,
  1167. }
  1168. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1169. unit.ondata_files(get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE'))
  1170. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1171. data = dump_test(unit, dart_record)
  1172. if data:
  1173. unit.set_property(["DART_DATA", data])
  1174. @df.with_fields(
  1175. YTEST_FIELDS_BASE
  1176. + YTEST_FIELDS_EXTRA
  1177. + (
  1178. df.TestName.value,
  1179. df.TestData.from_macro_args_and_unit,
  1180. df.Requirements.from_macro_args_and_unit,
  1181. df.TestPartition.value,
  1182. )
  1183. )
  1184. def coverage_extractor(fields, unit, *args):
  1185. keywords = {
  1186. "DEPENDS": -1,
  1187. "DATA": -1,
  1188. "TIMEOUT": 1,
  1189. "FORK_MODE": 1,
  1190. "SPLIT_FACTOR": 1,
  1191. "FORK_SUBTESTS": 0,
  1192. "FORK_TESTS": 0,
  1193. }
  1194. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1195. unit.ondata_files(get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE'))
  1196. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1197. data = dump_test(unit, dart_record)
  1198. if data:
  1199. unit.set_property(["DART_DATA", data])
  1200. @df.with_fields(
  1201. YTEST_FIELDS_BASE
  1202. + YTEST_FIELDS_EXTRA
  1203. + (
  1204. df.TestName.first_flat_with_bench,
  1205. df.TestData.from_macro_args_and_unit,
  1206. df.Requirements.from_macro_args_and_unit,
  1207. df.TestPartition.value,
  1208. df.GoBenchTimeout.value,
  1209. df.ModuleLang.value,
  1210. df.DockerImage.value,
  1211. )
  1212. )
  1213. def go_bench(fields, unit, *args):
  1214. keywords = {
  1215. "DEPENDS": -1,
  1216. "DATA": -1,
  1217. "TIMEOUT": 1,
  1218. "FORK_MODE": 1,
  1219. "SPLIT_FACTOR": 1,
  1220. "FORK_SUBTESTS": 0,
  1221. "FORK_TESTS": 0,
  1222. }
  1223. flat_args, spec_args = _common.sort_by_keywords(keywords, args)
  1224. tags = df.Tag.from_macro_args_and_unit(unit, flat_args, spec_args)[df.Tag.KEY]
  1225. if "ya:run_go_benchmark" not in tags:
  1226. return
  1227. unit.ondata_files(get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE'))
  1228. dart_record = create_dart_record(fields, unit, flat_args, spec_args)
  1229. data = dump_test(unit, dart_record)
  1230. if data:
  1231. unit.set_property(["DART_DATA", data])
  1232. def onadd_ytest(unit, *args):
  1233. keywords = {
  1234. "DEPENDS": -1,
  1235. "DATA": -1,
  1236. "TIMEOUT": 1,
  1237. "FORK_MODE": 1,
  1238. "SPLIT_FACTOR": 1,
  1239. "FORK_SUBTESTS": 0,
  1240. "FORK_TESTS": 0,
  1241. }
  1242. flat_args, *_ = _common.sort_by_keywords(keywords, args)
  1243. test_type = flat_args[1]
  1244. # TIDY not supported for module
  1245. if unit.get("TIDY_ENABLED") == "yes" and test_type != "clang_tidy":
  1246. return
  1247. # TIDY explicitly disabled for module in ymake.core.conf
  1248. elif test_type == "clang_tidy" and unit.get("TIDY_ENABLED") != "yes":
  1249. return
  1250. # TIDY disabled for module in ya.make
  1251. elif unit.get("TIDY") == "yes" and unit.get("TIDY_ENABLED") != "yes":
  1252. return
  1253. elif test_type == "no.test":
  1254. return
  1255. elif test_type == "clang_tidy" and unit.get("TIDY_ENABLED") == "yes":
  1256. clang_tidy(unit, *args)
  1257. elif test_type == "unittest.py":
  1258. unittest_py(unit, *args)
  1259. elif test_type == "gunittest":
  1260. gunittest(unit, *args)
  1261. elif test_type == "g_benchmark":
  1262. g_benchmark(unit, *args)
  1263. elif test_type == "go.test":
  1264. go_test(unit, *args)
  1265. elif test_type == "boost.test":
  1266. boost_test(unit, *args)
  1267. elif test_type == "fuzz.test":
  1268. fuzz_test(unit, *args)
  1269. elif test_type == "y_benchmark":
  1270. y_benchmark(unit, *args)
  1271. elif test_type == "coverage.extractor" and match_coverage_extractor_requirements(unit):
  1272. coverage_extractor(unit, *args)
  1273. elif test_type == "go.bench":
  1274. go_bench(unit, *args)