_dart_fields.py 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447
  1. import base64
  2. import functools
  3. import json
  4. import operator
  5. import os
  6. import re
  7. import shlex
  8. import sys
  9. from functools import reduce
  10. import six
  11. import ymake
  12. import _common
  13. import lib.test_const as consts
  14. CANON_RESULT_FILE_NAME = 'result.json'
  15. CANON_DATA_DIR_NAME = 'canondata'
  16. CANON_OUTPUT_STORAGE = 'canondata_storage'
  17. KTLINT_CURRENT_EDITOR_CONFIG = "arcadia/build/platform/java/ktlint/.editorconfig"
  18. KTLINT_OLD_EDITOR_CONFIG = "arcadia/build/platform/java/ktlint_old/.editorconfig"
  19. ARCADIA_ROOT = '${ARCADIA_ROOT}/'
  20. SOURCE_ROOT_SHORT = '$S/'
  21. class DartValueError(ValueError):
  22. pass
  23. def create_dart_record(fields, *args):
  24. try:
  25. return reduce(operator.or_, (value for field in fields if (value := field(*args))), {})
  26. except Exception as e:
  27. if str(e) != "":
  28. ymake.report_configure_error("Exception: {}".format(e))
  29. else:
  30. raise (e)
  31. return None
  32. def with_fields(fields):
  33. def inner(func):
  34. @functools.wraps(func)
  35. def innermost(*args, **kwargs):
  36. func(fields, *args, **kwargs)
  37. return innermost
  38. return inner
  39. def serialize_list(lst):
  40. lst = list(filter(None, lst))
  41. return '\"' + ';'.join(lst) + '\"' if lst else ''
  42. def deserialize_list(val):
  43. return list(filter(None, val.replace('"', "").split(";")))
  44. def get_unit_list_variable(unit, name):
  45. items = unit.get(name)
  46. if items:
  47. items = items.split(' ')
  48. assert items[0] == "${}".format(name), (items, name)
  49. return items[1:]
  50. return []
  51. def get_values_list(unit, key):
  52. res = map(str.strip, (unit.get(key) or '').replace('$' + key, '').strip().split())
  53. return [r for r in res if r and r not in ['""', "''"]]
  54. def _get_test_tags(unit, spec_args=None):
  55. if spec_args is None:
  56. spec_args = {}
  57. tags = spec_args.get('TAG', []) + get_values_list(unit, 'TEST_TAGS_VALUE')
  58. tags = set(tags)
  59. if unit.get('EXPORT_SEM') == 'yes':
  60. filter_only_tags = sorted(t for t in tags if ':' not in t)
  61. unit.set(['FILTER_ONLY_TEST_TAGS', ' '.join(filter_only_tags)])
  62. # DEVTOOLS-7571
  63. if unit.get('SKIP_TEST_VALUE') and consts.YaTestTags.Fat in tags:
  64. tags.add(consts.YaTestTags.NotAutocheck)
  65. return tags
  66. def format_recipes(data: str | None) -> str:
  67. if not data:
  68. return ""
  69. data = data.replace('"USE_RECIPE_DELIM"', "\n")
  70. data = data.replace("$TEST_RECIPES_VALUE", "")
  71. return data
  72. def prepare_recipes(data: str | None) -> bytes:
  73. formatted = format_recipes(data)
  74. return base64.b64encode(six.ensure_binary(formatted))
  75. def prepare_env(data):
  76. data = data.replace("$TEST_ENV_VALUE", "")
  77. return serialize_list(shlex.split(data))
  78. def get_norm_paths(unit, key):
  79. # return paths without trailing (back)slash
  80. return [x.rstrip('\\/').replace('${ARCADIA_ROOT}/', '') for x in get_values_list(unit, key)]
  81. def _load_canonical_file(filename, unit_path):
  82. try:
  83. with open(filename, 'rb') as results_file:
  84. return json.load(results_file)
  85. except Exception as e:
  86. print("malformed canonical data in {}: {} ({})".format(unit_path, e, filename), file=sys.stderr)
  87. return {}
  88. def _get_resource_from_uri(uri):
  89. m = consts.CANON_MDS_RESOURCE_REGEX.match(uri)
  90. if m:
  91. key = m.group(1)
  92. return "{}:{}".format(consts.MDS_SCHEME, key)
  93. m = consts.CANON_BACKEND_RESOURCE_REGEX.match(uri)
  94. if m:
  95. key = m.group(1)
  96. return "{}:{}".format(consts.MDS_SCHEME, key)
  97. m = consts.CANON_SBR_RESOURCE_REGEX.match(uri)
  98. if m:
  99. # There might be conflict between resources, because all resources in sandbox have 'resource.tar.gz' name
  100. # That's why we use notation with '=' to specify specific path for resource
  101. uri = m.group(1)
  102. res_id = m.group(2)
  103. return "{}={}".format(uri, '/'.join([CANON_OUTPUT_STORAGE, res_id]))
  104. def _get_external_resources_from_canon_data(data):
  105. # Method should work with both canonization versions:
  106. # result.json: {'uri':X 'checksum':Y}
  107. # result.json: {'testname': {'uri':X 'checksum':Y}}
  108. # result.json: {'testname': [{'uri':X 'checksum':Y}]}
  109. # Also there is a bug - if user returns {'uri': 1} from test - machinery will fail
  110. # That's why we check 'uri' and 'checksum' fields presence
  111. # (it's still a bug - user can return {'uri':X, 'checksum': Y}, we need to unify canonization format)
  112. res = set()
  113. if isinstance(data, dict):
  114. if 'uri' in data and 'checksum' in data:
  115. resource = _get_resource_from_uri(data['uri'])
  116. if resource:
  117. res.add(resource)
  118. else:
  119. for k, v in six.iteritems(data):
  120. res.update(_get_external_resources_from_canon_data(v))
  121. elif isinstance(data, list):
  122. for e in data:
  123. res.update(_get_external_resources_from_canon_data(e))
  124. return res
  125. def _get_canonical_data_resources_v2(filename, unit_path):
  126. return (_get_external_resources_from_canon_data(_load_canonical_file(filename, unit_path)), [filename])
  127. def get_canonical_test_resources(unit):
  128. unit_path = unit.path()
  129. if unit.get("CUSTOM_CANONDATA_PATH"):
  130. path_to_canondata = unit_path.replace("$S", unit.get("CUSTOM_CANONDATA_PATH"))
  131. else:
  132. path_to_canondata = unit.resolve(unit_path)
  133. canon_data_dir = os.path.join(path_to_canondata, CANON_DATA_DIR_NAME, unit.get('CANONIZE_SUB_PATH') or '')
  134. try:
  135. _, dirs, files = next(os.walk(canon_data_dir))
  136. except StopIteration:
  137. # path doesn't exist
  138. return [], []
  139. if CANON_RESULT_FILE_NAME in files:
  140. return _get_canonical_data_resources_v2(os.path.join(canon_data_dir, CANON_RESULT_FILE_NAME), unit_path)
  141. return [], []
  142. def java_srcdirs_to_data(unit, var, serialize_result=True):
  143. extra_data = []
  144. for srcdir in (unit.get(var) or '').replace('$' + var, '').split():
  145. if srcdir == '.':
  146. srcdir = unit.get('MODDIR')
  147. if srcdir.startswith('${ARCADIA_ROOT}/') or srcdir.startswith('$ARCADIA_ROOT/'):
  148. srcdir = srcdir.replace('${ARCADIA_ROOT}/', '$S/')
  149. srcdir = srcdir.replace('$ARCADIA_ROOT/', '$S/')
  150. if srcdir.startswith('${CURDIR}') or srcdir.startswith('$CURDIR'):
  151. srcdir = srcdir.replace('${CURDIR}', os.path.join('$S', unit.get('MODDIR')))
  152. srcdir = srcdir.replace('$CURDIR', os.path.join('$S', unit.get('MODDIR')))
  153. srcdir = unit.resolve_arc_path(srcdir)
  154. if not srcdir.startswith('$'):
  155. srcdir = os.path.join('$S', unit.get('MODDIR'), srcdir)
  156. if srcdir.startswith('$S'):
  157. extra_data.append(srcdir.replace('$S', 'arcadia'))
  158. return serialize_list(extra_data) if serialize_result else extra_data
  159. def extract_java_system_properties(unit, args):
  160. if len(args) % 2:
  161. return [], 'Wrong use of SYSTEM_PROPERTIES in {}: odd number of arguments'.format(unit.path())
  162. props = []
  163. for x, y in zip(args[::2], args[1::2]):
  164. if x == 'FILE':
  165. if y.startswith('${BINDIR}') or y.startswith('${ARCADIA_BUILD_ROOT}') or y.startswith('/'):
  166. return [], 'Wrong use of SYSTEM_PROPERTIES in {}: absolute/build file path {}'.format(unit.path(), y)
  167. y = _common.rootrel_arc_src(y, unit)
  168. if not os.path.exists(unit.resolve('$S/' + y)):
  169. return [], 'Wrong use of SYSTEM_PROPERTIES in {}: can\'t resolve {}'.format(unit.path(), y)
  170. y = '${ARCADIA_ROOT}/' + y
  171. props.append({'type': 'file', 'path': y})
  172. else:
  173. props.append({'type': 'inline', 'key': x, 'value': y})
  174. return props, None
  175. def _resolve_module_files(unit, mod_dir, file_paths):
  176. mod_dir_with_sep_len = len(mod_dir) + 1
  177. resolved_files = []
  178. for path in file_paths:
  179. resolved = _common.rootrel_arc_src(path, unit)
  180. if resolved.startswith(mod_dir):
  181. resolved = resolved[mod_dir_with_sep_len:]
  182. resolved_files.append(resolved)
  183. return resolved_files
  184. def _resolve_config_path(unit, test_runner, rel_to):
  185. config_path = unit.get("ESLINT_CONFIG_PATH") if test_runner == "eslint" else unit.get("TS_TEST_CONFIG_PATH")
  186. arc_config_path = unit.resolve_arc_path(config_path)
  187. abs_config_path = unit.resolve(arc_config_path)
  188. if not abs_config_path:
  189. raise Exception("{} config not found: {}".format(test_runner, config_path))
  190. unit.onsrcs([arc_config_path])
  191. abs_rel_to = unit.resolve(unit.resolve_arc_path(unit.get(rel_to)))
  192. return os.path.relpath(abs_config_path, start=abs_rel_to)
  193. def _get_ts_test_data_dirs(unit):
  194. return sorted(
  195. set(
  196. [
  197. os.path.dirname(_common.rootrel_arc_src(p, unit))
  198. for p in (get_values_list(unit, "_TS_TEST_DATA_VALUE") or [])
  199. ]
  200. )
  201. )
  202. @_common.cache_by_second_arg
  203. def get_linter_configs(unit, config_paths):
  204. rel_config_path = _common.rootrel_arc_src(config_paths, unit)
  205. arc_config_path = unit.resolve_arc_path(rel_config_path)
  206. abs_config_path = unit.resolve(arc_config_path)
  207. with open(abs_config_path, 'r') as fd:
  208. return json.load(fd)
  209. def _reference_group_var(varname: str, extensions: list[str] | None = None) -> str:
  210. if extensions is None:
  211. return f'"${{join=\\;:{varname}}}"'
  212. return serialize_list(f'${{ext={ext};join=\\;:{varname}}}' for ext in extensions)
  213. def assert_file_exists(unit, path):
  214. path = unit.resolve(SOURCE_ROOT_SHORT + path)
  215. if not os.path.exists(path):
  216. message = 'File {} is not found'.format(path)
  217. ymake.report_configure_error(message)
  218. raise DartValueError()
  219. class AndroidApkTestActivity:
  220. KEY = 'ANDROID_APK_TEST_ACTIVITY'
  221. @classmethod
  222. def value(cls, unit, flat_args, spec_args):
  223. return {cls.KEY: unit.get('ANDROID_APK_TEST_ACTIVITY_VALUE')}
  224. class BenchmarkOpts:
  225. KEY = 'BENCHMARK-OPTS'
  226. @classmethod
  227. def value(cls, unit, flat_args, spec_args):
  228. return {cls.KEY: serialize_list(get_unit_list_variable(unit, 'BENCHMARK_OPTS_VALUE'))}
  229. class BinaryPath:
  230. KEY = 'BINARY-PATH'
  231. @classmethod
  232. def normalized(cls, unit, flat_args, spec_args):
  233. unit_path = _common.get_norm_unit_path(unit)
  234. return {cls.KEY: os.path.join(unit_path, unit.filename())}
  235. @classmethod
  236. def stripped(cls, unit, flat_args, spec_args):
  237. unit_path = unit.path()
  238. binary_path = os.path.join(unit_path, unit.filename())
  239. if binary_path:
  240. return {cls.KEY: _common.strip_roots(binary_path)}
  241. @classmethod
  242. def stripped_without_pkg_ext(cls, unit, flat_args, spec_args):
  243. value = _common.strip_roots(os.path.join(unit.path(), unit.filename()).replace(".pkg", ""))
  244. return {cls.KEY: value}
  245. class Blob:
  246. KEY = 'BLOB'
  247. @classmethod
  248. def value(cls, unit, flat_args, spec_args):
  249. return {cls.KEY: unit.get('TEST_BLOB_DATA')}
  250. class BuildFolderPath:
  251. KEY = 'BUILD-FOLDER-PATH'
  252. @classmethod
  253. def normalized(cls, unit, flat_args, spec_args):
  254. return {cls.KEY: _common.get_norm_unit_path(unit)}
  255. @classmethod
  256. def stripped(cls, unit, flat_args, spec_args):
  257. return {cls.KEY: _common.strip_roots(unit.path())}
  258. class CanonizeSubPath:
  259. KEY = 'CANONIZE_SUB_PATH'
  260. @classmethod
  261. def value(cls, unit, flat_args, spec_args):
  262. return {cls.KEY: unit.get('CANONIZE_SUB_PATH')}
  263. class Classpath:
  264. KEY = 'CLASSPATH'
  265. @classmethod
  266. def value(cls, unit, flat_args, spec_args):
  267. value = '$B/{}/{}.jar ${{DART_CLASSPATH}}'.format(unit.get('MODDIR'), unit.get('REALPRJNAME'))
  268. return {cls.KEY: value}
  269. class ConfigPath:
  270. KEY = 'CONFIG-PATH'
  271. @classmethod
  272. def value(cls, unit, flat_args, spec_args):
  273. test_runner, rel_to = flat_args
  274. return {cls.KEY: _resolve_config_path(unit, test_runner, rel_to=rel_to)}
  275. class CustomDependencies:
  276. KEY = 'CUSTOM-DEPENDENCIES'
  277. @classmethod
  278. def all_standard(cls, unit, flat_args, spec_args):
  279. custom_deps = ' '.join(spec_args.get('DEPENDS', []) + get_values_list(unit, 'TEST_DEPENDS_VALUE'))
  280. return {cls.KEY: custom_deps}
  281. @classmethod
  282. def depends_only(cls, unit, flat_args, spec_args):
  283. return {cls.KEY: " ".join(spec_args.get('DEPENDS', []))}
  284. @classmethod
  285. def test_depends_only(cls, unit, flat_args, spec_args):
  286. custom_deps = get_values_list(unit, 'TEST_DEPENDS_VALUE')
  287. return {cls.KEY: " ".join(custom_deps)}
  288. @classmethod
  289. def depends_with_linter(cls, unit, flat_args, spec_args):
  290. linter = Linter.value(unit, flat_args, spec_args)[Linter.KEY]
  291. deps = spec_args.get('DEPENDS', []) + [os.path.dirname(linter)]
  292. for dep in deps:
  293. unit.ondepends(dep)
  294. return {cls.KEY: " ".join(deps)}
  295. @classmethod
  296. def nots_with_recipies(cls, unit, flat_args, spec_args):
  297. deps = flat_args[0]
  298. recipes_lines = format_recipes(unit.get("TEST_RECIPES_VALUE")).strip().splitlines()
  299. if recipes_lines:
  300. deps = deps or []
  301. deps.extend([os.path.dirname(r.strip().split(" ")[0]) for r in recipes_lines])
  302. return {cls.KEY: " ".join(deps)}
  303. class EslintConfigPath:
  304. KEY = 'ESLINT_CONFIG_PATH'
  305. @classmethod
  306. def value(cls, unit, flat_args, spec_args):
  307. test_runner, rel_to = flat_args
  308. return {cls.KEY: _resolve_config_path(unit, test_runner, rel_to=rel_to)}
  309. class ForkMode:
  310. KEY = 'FORK-MODE'
  311. @classmethod
  312. def from_macro_and_unit(cls, unit, flat_args, spec_args):
  313. fork_mode = []
  314. if 'FORK_SUBTESTS' in spec_args:
  315. fork_mode.append('subtests')
  316. if 'FORK_TESTS' in spec_args:
  317. fork_mode.append('tests')
  318. fork_mode = fork_mode or spec_args.get('FORK_MODE', []) or unit.get('TEST_FORK_MODE').split()
  319. fork_mode = ' '.join(fork_mode) if fork_mode else ''
  320. return {cls.KEY: fork_mode}
  321. @classmethod
  322. def test_fork_mode(cls, unit, flat_args, spec_args):
  323. return {cls.KEY: unit.get('TEST_FORK_MODE')}
  324. class ForkTestFiles:
  325. KEY = 'FORK-TEST-FILES'
  326. @classmethod
  327. def value(cls, unit, flat_args, spec_args):
  328. return {cls.KEY: unit.get('FORK_TEST_FILES_MODE')}
  329. class FuzzDicts:
  330. KEY = 'FUZZ-DICTS'
  331. @classmethod
  332. def value(cls, unit, flat_args, spec_args):
  333. value = serialize_list(spec_args.get('FUZZ_DICTS', []) + get_unit_list_variable(unit, 'FUZZ_DICTS_VALUE'))
  334. return {cls.KEY: value}
  335. class FuzzOpts:
  336. KEY = 'FUZZ-OPTS'
  337. @classmethod
  338. def value(cls, unit, flat_args, spec_args):
  339. value = serialize_list(spec_args.get('FUZZ_OPTS', []) + get_unit_list_variable(unit, 'FUZZ_OPTS_VALUE'))
  340. return {cls.KEY: value}
  341. class Fuzzing:
  342. KEY = 'FUZZING'
  343. @classmethod
  344. def value(cls, unit, flat_args, spec_args):
  345. if unit.get('FUZZING') == 'yes':
  346. return {cls.KEY: '1'}
  347. class GlobalLibraryPath:
  348. KEY = 'GLOBAL-LIBRARY-PATH'
  349. @classmethod
  350. def value(cls, unit, flat_args, spec_args):
  351. return {cls.KEY: unit.global_filename()}
  352. class GoBenchTimeout:
  353. KEY = 'GO_BENCH_TIMEOUT'
  354. @classmethod
  355. def value(cls, unit, flat_args, spec_args):
  356. return {cls.KEY: unit.get('GO_BENCH_TIMEOUT')}
  357. class IgnoreClasspathClash:
  358. KEY = 'IGNORE_CLASSPATH_CLASH'
  359. @classmethod
  360. def value(cls, unit, flat_args, spec_args):
  361. value = ' '.join(get_values_list(unit, 'JAVA_IGNORE_CLASSPATH_CLASH_VALUE'))
  362. return {cls.KEY: value}
  363. class JavaClasspathCmdType:
  364. KEY = 'JAVA_CLASSPATH_CMD_TYPE'
  365. @classmethod
  366. def value(cls, unit, flat_args, spec_args):
  367. java_cp_arg_type = unit.get('JAVA_CLASSPATH_CMD_TYPE_VALUE') or 'MANIFEST'
  368. if java_cp_arg_type not in ('MANIFEST', 'COMMAND_FILE', 'LIST'):
  369. # TODO move error reporting out of field classes
  370. ymake.report_configure_error(
  371. '{}: TEST_JAVA_CLASSPATH_CMD_TYPE({}) are invalid. Choose argument from MANIFEST, COMMAND_FILE or LIST)'.format(
  372. unit.path(), java_cp_arg_type
  373. )
  374. )
  375. raise DartValueError()
  376. return {cls.KEY: java_cp_arg_type}
  377. class JdkForTests:
  378. KEY = 'JDK_FOR_TESTS'
  379. @classmethod
  380. def value(cls, unit, flat_args, spec_args):
  381. value = 'JDK' + (unit.get('JDK_VERSION') or unit.get('JDK_REAL_VERSION') or '_DEFAULT') + '_FOR_TESTS'
  382. return {cls.KEY: value}
  383. class JdkLatestVersion:
  384. KEY = 'JDK_LATEST_VERSION'
  385. @classmethod
  386. def value(cls, unit, flat_args, spec_args):
  387. return {cls.KEY: unit.get('JDK_LATEST_VERSION')}
  388. class JdkResource:
  389. KEY = 'JDK_RESOURCE'
  390. @classmethod
  391. def value(cls, unit, flat_args, spec_args):
  392. value = 'JDK' + (unit.get('JDK_VERSION') or unit.get('JDK_REAL_VERSION') or '_DEFAULT')
  393. return {cls.KEY: value}
  394. class KtlintBaselineFile:
  395. KEY = 'KTLINT_BASELINE_FILE'
  396. @classmethod
  397. def value(cls, unit, flat_args, spec_args):
  398. if unit.get('_USE_KTLINT_OLD') != 'yes':
  399. baseline_path_relative = unit.get('_KTLINT_BASELINE_FILE')
  400. if baseline_path_relative:
  401. return {cls.KEY: baseline_path_relative}
  402. class KtlintBinary:
  403. KEY = 'KTLINT_BINARY'
  404. @classmethod
  405. def value(cls, unit, flat_args, spec_args):
  406. value = '$(KTLINT_OLD)/run.bat' if unit.get('_USE_KTLINT_OLD') == 'yes' else '$(KTLINT)/run.bat'
  407. return {cls.KEY: value}
  408. class Linter:
  409. KEY = 'LINTER'
  410. @classmethod
  411. def value(cls, unit, flat_args, spec_args):
  412. return {cls.KEY: spec_args['LINTER'][0]}
  413. class LintConfigs:
  414. KEY = 'LINT-CONFIGS'
  415. @staticmethod
  416. def _from_config_type(unit, spec_args):
  417. if not spec_args.get('CONFIG_TYPE') or not spec_args.get('CONFIG_TYPE')[0]:
  418. return
  419. linter_name = spec_args['NAME'][0]
  420. config_type = spec_args.get('CONFIG_TYPE')[0]
  421. if config_type not in consts.LINTER_CONFIG_TYPES[linter_name]:
  422. message = "Unknown {} linter config type: {}. Allowed types: {}".format(
  423. linter_name, config_type, ', '.join(consts.LINTER_CONFIG_TYPES[linter_name])
  424. )
  425. ymake.report_configure_error(message)
  426. raise DartValueError()
  427. if common_configs_dir := unit.get('MODULE_COMMON_CONFIGS_DIR'):
  428. config = os.path.join(common_configs_dir, config_type)
  429. path = unit.resolve(config)
  430. if os.path.exists(path):
  431. return _common.strip_roots(config)
  432. message = "File not found: {}".format(path)
  433. ymake.report_configure_error(message)
  434. raise DartValueError()
  435. else:
  436. message = "Config type specifier is only allowed with autoincludes"
  437. ymake.report_configure_error(message)
  438. raise DartValueError()
  439. @classmethod
  440. def python_configs(cls, unit, flat_args, spec_args):
  441. resolved_configs = []
  442. if (custom_config := spec_args.get('CUSTOM_CONFIG')) and '/' in custom_config[0]:
  443. # black if custom config is passed.
  444. # XXX During migration we want to use the same macro parameter
  445. # for path to linter config and config type
  446. # thus, we check if '/' is present, if it is then it's a path
  447. # TODO delete once custom configs migrated to autoincludes scheme
  448. custom_config = custom_config[0]
  449. assert_file_exists(unit, custom_config)
  450. resolved_configs.append(custom_config)
  451. return {cls.KEY: serialize_list(resolved_configs)}
  452. if config := cls._from_config_type(unit, spec_args):
  453. # specified by config type, autoincludes scheme
  454. return {cls.KEY: serialize_list([config])}
  455. if project_to_config_map := spec_args.get('PROJECT_TO_CONFIG_MAP'):
  456. # ruff, TODO delete once custom configs migrated to autoincludes scheme
  457. project_to_config_map = project_to_config_map[0]
  458. assert_file_exists(unit, project_to_config_map)
  459. resolved_configs.append(project_to_config_map)
  460. cfgs = get_linter_configs(unit, project_to_config_map).values()
  461. for c in cfgs:
  462. assert_file_exists(unit, c)
  463. resolved_configs.append(c)
  464. return {cls.KEY: serialize_list(resolved_configs)}
  465. # default config
  466. linter_name = spec_args['NAME'][0]
  467. default_configs_path = spec_args['CONFIGS'][0]
  468. assert_file_exists(unit, default_configs_path)
  469. config = get_linter_configs(unit, default_configs_path).get(linter_name)
  470. if not config:
  471. message = f"Default config in {default_configs_path} can't be found for a linter {linter_name}"
  472. ymake.report_configure_error(message)
  473. raise DartValueError()
  474. assert_file_exists(unit, config)
  475. resolved_configs.append(config)
  476. if linter_name in ('flake8', 'py2_flake8'):
  477. resolved_configs.extend(spec_args.get('FLAKE_MIGRATIONS_CONFIG', []))
  478. return {cls.KEY: serialize_list(resolved_configs)}
  479. @classmethod
  480. def cpp_configs(cls, unit, flat_args, spec_args):
  481. custom_config = spec_args.get('CUSTOM_CONFIG')
  482. if custom_config:
  483. # TODO delete CUSTOM_CONFIG, it's used only by arc
  484. config = custom_config[0]
  485. assert_file_exists(unit, config)
  486. return {cls.KEY: serialize_list([config])}
  487. if config := cls._from_config_type(unit, spec_args):
  488. # specified by config type, autoincludes scheme
  489. return {cls.KEY: serialize_list([config])}
  490. # default config
  491. linter_name = spec_args['NAME'][0]
  492. default_configs_path = spec_args.get('CONFIGS')[0]
  493. assert_file_exists(unit, default_configs_path)
  494. config = get_linter_configs(unit, default_configs_path).get(linter_name)
  495. if not config:
  496. message = f"Default config in {default_configs_path} can't be found for a linter {linter_name}"
  497. ymake.report_configure_error(message)
  498. raise DartValueError()
  499. assert_file_exists(unit, config)
  500. return {cls.KEY: serialize_list([config])}
  501. class LintExtraParams:
  502. KEY = 'LINT-EXTRA-PARAMS'
  503. _CUSTOM_CLANG_FORMAT_BIN_ALLOWED_PATHS = consts.CUSTOM_CLANG_FORMAT_YT_ALLOWED_PATHS
  504. @classmethod
  505. def from_macro_args(cls, unit, flat_args, spec_args):
  506. extra_params = spec_args.get('EXTRA_PARAMS', [])
  507. for arg in extra_params:
  508. if '=' not in arg:
  509. message = 'Wrong EXTRA_PARAMS value: "{}". Values must have format "name=value".'.format(arg)
  510. ymake.report_configure_error(message)
  511. raise DartValueError()
  512. if 'clang_format_bin' in arg:
  513. upath = unit.path()[3:]
  514. if not upath.startswith(cls._CUSTOM_CLANG_FORMAT_BIN_ALLOWED_PATHS):
  515. message = f'Custom clang-format is not allowed in upath: {upath}'
  516. ymake.report_configure_error(message)
  517. raise DartValueError()
  518. return {cls.KEY: serialize_list(extra_params)}
  519. class LintFileProcessingTime:
  520. KEY = 'LINT-FILE-PROCESSING-TIME'
  521. @classmethod
  522. def from_macro_args(cls, unit, flat_args, spec_args):
  523. return {cls.KEY: spec_args.get('FILE_PROCESSING_TIME', [''])[0]}
  524. class LintName:
  525. KEY = 'LINT-NAME'
  526. @classmethod
  527. def value(cls, unit, flat_args, spec_args):
  528. lint_name = spec_args['NAME'][0]
  529. if lint_name in ('flake8', 'py2_flake8') and (unit.get('DISABLE_FLAKE8') or 'no') == 'yes':
  530. unit.message(['INFO', 'Flake8 linting is disabled by `DISABLE_FLAKE8`'])
  531. raise DartValueError()
  532. return {cls.KEY: lint_name}
  533. class ModuleLang:
  534. KEY = 'MODULE_LANG'
  535. @classmethod
  536. def value(cls, unit, flat_args, spec_args):
  537. return {cls.KEY: unit.get("MODULE_LANG").lower() or consts.ModuleLang.UNKNOWN}
  538. class ModuleType:
  539. KEY = 'MODULE_TYPE'
  540. @classmethod
  541. def value(cls, unit, flat_args, spec_args):
  542. return {cls.KEY: unit.get('MODULE_TYPE')}
  543. class NoCheck:
  544. KEY = 'NO-CHECK'
  545. @classmethod
  546. def value(cls, unit, flat_args, spec_args):
  547. if unit.get('NO_CHECK_IMPORTS_FOR_VALUE') != "None":
  548. value = serialize_list(get_values_list(unit, 'NO_CHECK_IMPORTS_FOR_VALUE') or ["*"])
  549. return {cls.KEY: value}
  550. class NodejsRootVarName:
  551. KEY = 'NODEJS-ROOT-VAR-NAME'
  552. @classmethod
  553. def value(cls, unit, flat_args, spec_args):
  554. return {cls.KEY: unit.get("NODEJS-ROOT-VAR-NAME")}
  555. class NodeModulesBundleFilename:
  556. KEY = 'NODE-MODULES-BUNDLE-FILENAME'
  557. @classmethod
  558. def value(cls, unit, flat_args, spec_args):
  559. return {cls.KEY: spec_args.get('nm_bundle')}
  560. class PythonPaths:
  561. KEY = 'PYTHON-PATHS'
  562. @classmethod
  563. def value(cls, unit, flat_args, spec_args):
  564. python_paths = get_values_list(unit, 'TEST_PYTHON_PATH_VALUE')
  565. return {cls.KEY: serialize_list(python_paths)}
  566. class Requirements:
  567. KEY = 'REQUIREMENTS'
  568. @classmethod
  569. def from_macro_args_and_unit(cls, unit, flat_args, spec_args):
  570. test_requirements = spec_args.get('REQUIREMENTS', []) + get_values_list(unit, 'TEST_REQUIREMENTS_VALUE')
  571. return {cls.KEY: serialize_list(test_requirements)}
  572. @classmethod
  573. def with_maybe_fuzzing(cls, unit, flat_args, spec_args):
  574. test_requirements = serialize_list(
  575. spec_args.get('REQUIREMENTS', []) + get_values_list(unit, 'TEST_REQUIREMENTS_VALUE')
  576. )
  577. if unit.get('FUZZING') == 'yes':
  578. value = serialize_list(filter(None, deserialize_list(test_requirements) + ["cpu:all", "ram:all"]))
  579. return {cls.KEY: value}
  580. else:
  581. return {cls.KEY: test_requirements}
  582. @classmethod
  583. def from_macro_args(cls, unit, flat_args, spec_args):
  584. value = " ".join(spec_args.get('REQUIREMENTS', []))
  585. return {cls.KEY: value}
  586. @classmethod
  587. def from_unit(cls, unit, flat_args, spec_args):
  588. requirements = get_values_list(unit, 'TEST_REQUIREMENTS_VALUE')
  589. return {cls.KEY: serialize_list(requirements)}
  590. @classmethod
  591. def from_unit_with_full_network(cls, unit, flat_args, spec_args):
  592. requirements = sorted(set(["network:full"] + get_values_list(unit, "TEST_REQUIREMENTS_VALUE")))
  593. return {cls.KEY: serialize_list(requirements)}
  594. class SbrUidExt:
  595. KEY = 'SBR-UID-EXT'
  596. @classmethod
  597. def value(cls, unit, flat_args, spec_args):
  598. uid_ext = unit.get("SBR_UID_EXT").split(" ", 1)[-1] # strip variable name
  599. return {cls.KEY: uid_ext}
  600. class ScriptRelPath:
  601. KEY = 'SCRIPT-REL-PATH'
  602. @classmethod
  603. def second_flat(cls, unit, flat_args, spec_args):
  604. return {cls.KEY: flat_args[1]}
  605. @classmethod
  606. def first_flat(cls, unit, flat_args, spec_args):
  607. return {cls.KEY: flat_args[0]}
  608. @classmethod
  609. def pytest(cls, unit, flat_args, spec_args):
  610. return {cls.KEY: 'py3test.bin' if (unit.get("PYTHON3") == 'yes') else "pytest.bin"}
  611. @classmethod
  612. def junit(cls, unit, flat_args, spec_args):
  613. return {cls.KEY: 'junit5.test' if unit.get('MODULE_TYPE') == 'JUNIT5' else 'junit.test'}
  614. class Size:
  615. KEY = 'SIZE'
  616. @classmethod
  617. def from_macro_args_and_unit(cls, unit, flat_args, spec_args):
  618. return {cls.KEY: ''.join(spec_args.get('SIZE', [])) or unit.get('TEST_SIZE_NAME')}
  619. @classmethod
  620. def from_unit(cls, unit, flat_args, spec_args):
  621. return {cls.KEY: unit.get('TEST_SIZE_NAME')}
  622. class SkipTest:
  623. KEY = 'SKIP_TEST'
  624. @classmethod
  625. def value(cls, unit, flat_args, spec_args):
  626. return {cls.KEY: unit.get('SKIP_TEST_VALUE')}
  627. class SourceFolderPath:
  628. KEY = 'SOURCE-FOLDER-PATH'
  629. @classmethod
  630. def normalized(cls, unit, flat_args, spec_args):
  631. return {cls.KEY: _common.get_norm_unit_path(unit)}
  632. @classmethod
  633. def test_dir(cls, unit, flat_args, spec_args):
  634. test_dir = _common.get_norm_unit_path(unit)
  635. test_files = flat_args[1:]
  636. if test_files:
  637. test_dir = os.path.dirname(test_files[0]).lstrip("$S/")
  638. return {cls.KEY: test_dir}
  639. class SplitFactor:
  640. KEY = 'SPLIT-FACTOR'
  641. @classmethod
  642. def from_macro_args_and_unit(cls, unit, flat_args, spec_args):
  643. value = ''.join(spec_args.get('SPLIT_FACTOR', [])) or unit.get('TEST_SPLIT_FACTOR')
  644. return {cls.KEY: value}
  645. @classmethod
  646. def from_unit(cls, unit, flat_args, spec_args):
  647. return {cls.KEY: unit.get('TEST_SPLIT_FACTOR')}
  648. class Tag:
  649. KEY = 'TAG'
  650. @classmethod
  651. def from_macro_args_and_unit(cls, unit, flat_args, spec_args):
  652. tags = serialize_list(sorted(_get_test_tags(unit, spec_args)))
  653. return {cls.KEY: tags}
  654. @classmethod
  655. def from_unit(cls, unit, flat_args, spec_args):
  656. tags = serialize_list(get_values_list(unit, "TEST_TAGS_VALUE"))
  657. return {cls.KEY: tags}
  658. @classmethod
  659. def from_unit_fat_external_no_retries(cls, unit, flat_args, spec_args):
  660. tags = sorted(set(["ya:fat", "ya:external", "ya:noretries"] + get_values_list(unit, "TEST_TAGS_VALUE")))
  661. return {cls.KEY: serialize_list(tags)}
  662. class TestClasspath:
  663. KEY = 'TEST_CLASSPATH'
  664. @classmethod
  665. def value(cls, unit, flat_args, spec_args):
  666. value = '${DART_CLASSPATH}'
  667. return {cls.KEY: value}
  668. class TestClasspathDeps:
  669. KEY = 'TEST_CLASSPATH_DEPS'
  670. @classmethod
  671. def value(cls, unit, flat_args, spec_args):
  672. return {cls.KEY: '${DART_CLASSPATH_DEPS}'}
  673. class TestCwd:
  674. KEY = 'TEST-CWD'
  675. @classmethod
  676. def from_unit(cls, unit, flat_args, spec_args):
  677. test_cwd = unit.get('TEST_CWD_VALUE') # TODO: validate test_cwd value
  678. return {cls.KEY: test_cwd}
  679. @classmethod
  680. def keywords_replaced(cls, unit, flat_args, spec_args):
  681. test_cwd = unit.get('TEST_CWD_VALUE') or ''
  682. if test_cwd:
  683. test_cwd = test_cwd.replace("$TEST_CWD_VALUE", "").replace('"MACRO_CALLS_DELIM"', "").strip()
  684. return {cls.KEY: test_cwd}
  685. @classmethod
  686. def moddir(cls, unit, flat_args, spec_args):
  687. return {cls.KEY: unit.get("MODDIR")}
  688. class TestData:
  689. KEY = 'TEST-DATA'
  690. @classmethod
  691. def from_macro_args_and_unit(cls, unit, flat_args, spec_args):
  692. test_data = sorted(
  693. _common.filter_out_by_keyword(
  694. spec_args.get('DATA', []) + get_norm_paths(unit, 'TEST_DATA_VALUE'), 'AUTOUPDATED'
  695. )
  696. )
  697. return {cls.KEY: serialize_list(test_data)}
  698. @classmethod
  699. def from_macro_args_and_unit_with_canonical(cls, unit, flat_args, spec_args):
  700. test_data = sorted(
  701. _common.filter_out_by_keyword(
  702. spec_args.get('DATA', []) + get_norm_paths(unit, 'TEST_DATA_VALUE'), 'AUTOUPDATED'
  703. )
  704. )
  705. data, _ = get_canonical_test_resources(unit)
  706. test_data += data
  707. value = serialize_list(sorted(test_data))
  708. return {cls.KEY: value}
  709. @classmethod
  710. def ktlint(cls, unit, flat_args, spec_args):
  711. if unit.get('_USE_KTLINT_OLD') == 'yes':
  712. extra_test_data = [KTLINT_OLD_EDITOR_CONFIG]
  713. else:
  714. data_list = [KTLINT_CURRENT_EDITOR_CONFIG]
  715. baseline_path_relative = unit.get('_KTLINT_BASELINE_FILE')
  716. if baseline_path_relative:
  717. baseline_path = unit.resolve_arc_path(baseline_path_relative).replace('$S', 'arcadia')
  718. data_list += [baseline_path]
  719. extra_test_data = data_list
  720. # XXX
  721. if unit.get('_WITH_YA_1931') != 'yes':
  722. extra_test_data += java_srcdirs_to_data(unit, 'ALL_SRCDIRS', serialize_result=False)
  723. extra_test_data = serialize_list(extra_test_data)
  724. return {cls.KEY: extra_test_data}
  725. @classmethod
  726. def java_style(cls, unit, flat_args, spec_args):
  727. return {cls.KEY: java_srcdirs_to_data(unit, 'ALL_SRCDIRS')}
  728. @classmethod
  729. def from_unit_with_canonical(cls, unit, flat_args, spec_args):
  730. test_data = get_norm_paths(unit, 'TEST_DATA_VALUE')
  731. data, _ = get_canonical_test_resources(unit)
  732. test_data += data
  733. value = serialize_list(sorted(_common.filter_out_by_keyword(test_data, 'AUTOUPDATED')))
  734. return {cls.KEY: value}
  735. @classmethod
  736. def java_test(cls, unit, flat_args, spec_args):
  737. test_data = get_norm_paths(unit, 'TEST_DATA_VALUE')
  738. test_data.append('arcadia/build/scripts/run_junit.py')
  739. test_data.append('arcadia/build/scripts/unpacking_jtest_runner.py')
  740. data, _ = get_canonical_test_resources(unit)
  741. test_data += data
  742. props, error_mgs = extract_java_system_properties(unit, get_values_list(unit, 'SYSTEM_PROPERTIES_VALUE'))
  743. if error_mgs:
  744. ymake.report_configure_error(error_mgs)
  745. raise DartValueError()
  746. for prop in props:
  747. if prop['type'] == 'file':
  748. test_data.append(prop['path'].replace('${ARCADIA_ROOT}', 'arcadia'))
  749. value = serialize_list(sorted(_common.filter_out_by_keyword(test_data, 'AUTOUPDATED')))
  750. return {cls.KEY: value}
  751. @classmethod
  752. def from_unit(cls, unit, flat_args, spec_args):
  753. return {cls.KEY: serialize_list(get_values_list(unit, "TEST_DATA_VALUE"))}
  754. class DockerImage:
  755. KEY = 'DOCKER-IMAGES'
  756. @staticmethod
  757. def _validate(images):
  758. docker_image_re = consts.DOCKER_LINK_RE
  759. for img in images:
  760. msg = None
  761. if "=" in img:
  762. link, _ = img.rsplit('=', 1)
  763. if docker_image_re.match(link) is None:
  764. msg = 'Invalid docker url format: {}. Link should be provided in format docker://<repo>@sha256:<digest>'.format(
  765. link
  766. )
  767. else:
  768. msg = 'Invalid docker image: {}. Image should be provided in format <link>=<tag>'.format(img)
  769. if msg:
  770. ymake.report_configure_error(msg)
  771. raise DartValueError(msg)
  772. @classmethod
  773. def value(cls, unit, flat_args, spec_args):
  774. raw_value = get_values_list(unit, 'DOCKER_IMAGES_VALUE')
  775. images = sorted(raw_value)
  776. if images:
  777. cls._validate(images)
  778. return {cls.KEY: serialize_list(images)}
  779. class TsConfigPath:
  780. KEY = 'TS_CONFIG_PATH'
  781. class TsStylelintConfig:
  782. KEY = 'TS_STYLELINT_CONFIG'
  783. @classmethod
  784. def value(cls, unit, flat_args, spec_args):
  785. test_config = unit.get('_TS_STYLELINT_CONFIG')
  786. abs_test_config = unit.resolve(unit.resolve_arc_path(test_config))
  787. if not abs_test_config:
  788. ymake.report_configure_error(
  789. f"Config for stylelint not found: {test_config}.\n"
  790. "Set the correct value in `TS_STYLELINT(<config_filename>)` macro in the `ya.make` file."
  791. )
  792. return {cls.KEY: test_config}
  793. class TsTestDataDirs:
  794. KEY = 'TS-TEST-DATA-DIRS'
  795. @classmethod
  796. def value(cls, unit, flat_args, spec_args):
  797. value = serialize_list(_get_ts_test_data_dirs(unit))
  798. return {cls.KEY: value}
  799. class TsTestDataDirsRename:
  800. KEY = 'TS-TEST-DATA-DIRS-RENAME'
  801. @classmethod
  802. def value(cls, unit, flat_args, spec_args):
  803. return {cls.KEY: unit.get("_TS_TEST_DATA_DIRS_RENAME_VALUE")}
  804. class TsTestForPath:
  805. KEY = 'TS-TEST-FOR-PATH'
  806. @classmethod
  807. def value(cls, unit, flat_args, spec_args):
  808. return {cls.KEY: unit.get("TS_TEST_FOR_PATH")}
  809. class TestedProjectFilename:
  810. KEY = 'TESTED-PROJECT-FILENAME'
  811. @classmethod
  812. def value(cls, unit, flat_args, spec_args):
  813. return {cls.KEY: unit.filename()}
  814. class TestedProjectName:
  815. KEY = 'TESTED-PROJECT-NAME'
  816. @classmethod
  817. def unit_name(cls, unit, flat_args, spec_args):
  818. return {cls.KEY: unit.name()}
  819. @classmethod
  820. def normalized_basename(cls, unit, flat_args, spec_args):
  821. test_dir = _common.get_norm_unit_path(unit)
  822. return {cls.KEY: os.path.basename(test_dir)}
  823. @classmethod
  824. def test_dir(cls, unit, flat_args, spec_args):
  825. test_dir = _common.get_norm_unit_path(unit)
  826. test_files = flat_args[1:]
  827. if test_files:
  828. test_dir = os.path.dirname(test_files[0]).lstrip("$S/")
  829. return {cls.KEY: os.path.basename(test_dir)}
  830. @classmethod
  831. def path_filename_basename(cls, unit, flat_args, spec_args):
  832. binary_path = os.path.join(unit.path(), unit.filename())
  833. return {cls.KEY: os.path.basename(binary_path)}
  834. @classmethod
  835. def normalized(cls, unit, flat_args, spec_args):
  836. return {cls.KEY: _common.get_norm_unit_path(unit)}
  837. @classmethod
  838. def path_filename_basename_without_pkg_ext(cls, unit, flat_args, spec_args):
  839. value = os.path.basename(os.path.join(unit.path(), unit.filename()).replace(".pkg", ""))
  840. return {cls.KEY: value}
  841. @classmethod
  842. def filename_without_ext(cls, unit, flat_args, spec_args):
  843. return {cls.KEY: os.path.splitext(unit.filename())[0]}
  844. class TestFiles:
  845. KEY = 'TEST-FILES'
  846. # TODO remove FILES, see DEVTOOLS-7052, currently it's required
  847. # https://a.yandex-team.ru/arcadia/devtools/ya/test/dartfile/__init__.py?rev=r14292146#L10
  848. KEY2 = 'FILES'
  849. @classmethod
  850. def value(cls, unit, flat_args, spec_args):
  851. data_re = re.compile(r"sbr:/?/?(\d+)=?.*")
  852. data = flat_args[1:]
  853. resources = []
  854. for f in data:
  855. matched = re.match(data_re, f)
  856. if matched:
  857. resources.append(matched.group(1))
  858. value = serialize_list(resources)
  859. return {cls.KEY: value, cls.KEY2: value}
  860. @classmethod
  861. def flat_args_wo_first(cls, unit, flat_args, spec_args):
  862. value = serialize_list(flat_args[1:])
  863. return {cls.KEY: value, cls.KEY2: value}
  864. @classmethod
  865. def java_style(cls, unit, flat_args, spec_args):
  866. test_files = flat_args[1:]
  867. check_level = flat_args[1]
  868. allowed_levels = {
  869. 'base': '/yandex_checks.xml',
  870. 'strict': '/yandex_checks_strict.xml',
  871. 'extended': '/yandex_checks_extended.xml',
  872. 'library': '/yandex_checks_library.xml',
  873. }
  874. if check_level not in allowed_levels:
  875. raise Exception("'{}' is not allowed in LINT(), use one of {}".format(check_level, allowed_levels.keys()))
  876. test_files[0] = allowed_levels[check_level]
  877. value = serialize_list(test_files)
  878. return {cls.KEY: value, cls.KEY2: value}
  879. @classmethod
  880. def normalized(cls, unit, flat_args, spec_args):
  881. value = serialize_list([_common.get_norm_unit_path(unit, unit.filename())])
  882. return {cls.KEY: value, cls.KEY2: value}
  883. @classmethod
  884. def test_srcs(cls, unit, flat_args, spec_args):
  885. test_files = get_values_list(unit, 'TEST_SRCS_VALUE')
  886. value = serialize_list(test_files)
  887. return {cls.KEY: value, cls.KEY2: value}
  888. @classmethod
  889. def ts_test_srcs(cls, unit, flat_args, spec_args):
  890. test_files = get_values_list(unit, "_TS_TEST_SRCS_VALUE")
  891. test_files = _resolve_module_files(unit, unit.get("MODDIR"), test_files)
  892. value = serialize_list(test_files)
  893. return {cls.KEY: value, cls.KEY2: value}
  894. @classmethod
  895. def ts_input_files(cls, unit, flat_args, spec_args):
  896. typecheck_files = get_values_list(unit, "TS_INPUT_FILES")
  897. test_files = [_common.resolve_common_const(f) for f in typecheck_files]
  898. value = serialize_list(test_files)
  899. return {cls.KEY: value, cls.KEY2: value}
  900. @classmethod
  901. def ts_lint_srcs(cls, unit, flat_args, spec_args):
  902. test_files = get_values_list(unit, "_TS_LINT_SRCS_VALUE")
  903. test_files = _resolve_module_files(unit, unit.get("MODDIR"), test_files)
  904. value = serialize_list(test_files)
  905. return {cls.KEY: value, cls.KEY2: value}
  906. @classmethod
  907. def stylesheets(cls, unit, flat_args, spec_args):
  908. test_files = get_values_list(unit, "_TS_STYLELINT_FILES")
  909. test_files = _resolve_module_files(unit, unit.get("MODDIR"), test_files)
  910. value = serialize_list(test_files)
  911. return {cls.KEY: value, cls.KEY2: value}
  912. @classmethod
  913. def py_linter_files(cls, unit, flat_args, spec_args):
  914. files = unit.get('PY_LINTER_FILES')
  915. if not files:
  916. raise DartValueError()
  917. files = json.loads(files)
  918. test_files = []
  919. for path in files:
  920. if path.startswith(ARCADIA_ROOT):
  921. test_files.append(path.replace(ARCADIA_ROOT, SOURCE_ROOT_SHORT, 1))
  922. elif path.startswith(SOURCE_ROOT_SHORT):
  923. test_files.append(path)
  924. if not test_files:
  925. lint_name = LintName.value(unit, flat_args, spec_args)[LintName.KEY]
  926. message = 'No files to lint for {}'.format(lint_name)
  927. raise DartValueError(message)
  928. test_files = serialize_list(test_files)
  929. return {cls.KEY: test_files, cls.KEY2: test_files}
  930. @classmethod
  931. def cpp_linter_files(cls, unit, flat_args, spec_args):
  932. files_dart = _reference_group_var("ALL_SRCS", consts.STYLE_CPP_ALL_EXTS)
  933. return {cls.KEY: files_dart, cls.KEY2: files_dart}
  934. class TestEnv:
  935. KEY = 'TEST-ENV'
  936. @classmethod
  937. def value(cls, unit, flat_args, spec_args):
  938. return {cls.KEY: prepare_env(unit.get("TEST_ENV_VALUE"))}
  939. class TestIosDeviceType:
  940. KEY = 'TEST_IOS_DEVICE_TYPE'
  941. @classmethod
  942. def value(cls, unit, flat_args, spec_args):
  943. return {cls.KEY: unit.get('TEST_IOS_DEVICE_TYPE_VALUE')}
  944. class TestIosRuntimeType:
  945. KEY = 'TEST_IOS_RUNTIME_TYPE'
  946. @classmethod
  947. def value(cls, unit, flat_args, spec_args):
  948. return {cls.KEY: unit.get('TEST_IOS_RUNTIME_TYPE_VALUE')}
  949. class TestJar:
  950. KEY = 'TEST_JAR'
  951. @classmethod
  952. def value(cls, unit, flat_args, spec_args):
  953. if unit.get('UNITTEST_DIR'):
  954. value = '${UNITTEST_MOD}'
  955. else:
  956. value = '{}/{}.jar'.format(unit.get('MODDIR'), unit.get('REALPRJNAME'))
  957. return {cls.KEY: value}
  958. class TestName:
  959. KEY = 'TEST-NAME'
  960. @classmethod
  961. def value(cls, unit, flat_args, spec_args):
  962. return {cls.KEY: flat_args[0]}
  963. @classmethod
  964. def first_flat_with_bench(cls, unit, flat_args, spec_args):
  965. return {cls.KEY: flat_args[0] + '_bench'}
  966. @classmethod
  967. def first_flat(cls, unit, flat_args, spec_args):
  968. return {cls.KEY: flat_args[0].lower()}
  969. @classmethod
  970. def filename_without_ext(cls, unit, flat_args, spec_args):
  971. test_name = os.path.basename(os.path.join(unit.path(), unit.filename()))
  972. return {cls.KEY: os.path.splitext(test_name)[0]}
  973. @classmethod
  974. def normalized_joined_dir_basename(cls, unit, flat_args, spec_args):
  975. path = _common.get_norm_unit_path(unit)
  976. value = '-'.join([os.path.basename(os.path.dirname(path)), os.path.basename(path)])
  977. return {cls.KEY: value}
  978. @classmethod
  979. def normalized_joined_dir_basename_deps(cls, unit, flat_args, spec_args):
  980. path = _common.get_norm_unit_path(unit)
  981. value = '-'.join([os.path.basename(os.path.dirname(path)), os.path.basename(path), 'dependencies']).strip('-')
  982. return {cls.KEY: value}
  983. @classmethod
  984. def filename_without_pkg_ext(cls, unit, flat_args, spec_args):
  985. test_name = os.path.basename(os.path.join(unit.path(), unit.filename()).replace(".pkg", ""))
  986. return {cls.KEY: os.path.splitext(test_name)[0]}
  987. @classmethod
  988. def name_from_macro_args(cls, unit, flat_args, spec_args):
  989. return {cls.KEY: spec_args['NAME'][0]}
  990. class TestPartition:
  991. KEY = 'TEST_PARTITION'
  992. @classmethod
  993. def value(cls, unit, flat_args, spec_args):
  994. return {cls.KEY: unit.get("TEST_PARTITION")}
  995. class TestRecipes:
  996. KEY = 'TEST-RECIPES'
  997. @classmethod
  998. def value(cls, unit, flat_args, spec_args):
  999. return {cls.KEY: prepare_recipes(unit.get("TEST_RECIPES_VALUE"))}
  1000. class TestRunnerBin:
  1001. KEY = 'TEST-RUNNER-BIN'
  1002. @classmethod
  1003. def value(cls, unit, flat_args, spec_args):
  1004. runner_bin = spec_args.get('RUNNER_BIN', [None])[0]
  1005. if runner_bin:
  1006. return {cls.KEY: runner_bin}
  1007. class TestTimeout:
  1008. KEY = 'TEST-TIMEOUT'
  1009. @classmethod
  1010. def from_macro_args_and_unit(cls, unit, flat_args, spec_args):
  1011. test_timeout = ''.join(spec_args.get('TIMEOUT', [])) or unit.get('TEST_TIMEOUT') or ''
  1012. return {cls.KEY: test_timeout}
  1013. @classmethod
  1014. def from_unit_with_default(cls, unit, flat_args, spec_args):
  1015. timeout = list(filter(None, [unit.get(["TEST_TIMEOUT"])]))
  1016. if timeout:
  1017. timeout = timeout[0]
  1018. else:
  1019. timeout = '0'
  1020. return {cls.KEY: timeout}
  1021. @classmethod
  1022. def from_unit(cls, unit, flat_args, spec_args):
  1023. return {cls.KEY: unit.get('TEST_TIMEOUT')}
  1024. class TsResources:
  1025. KEY = "{}-ROOT-VAR-NAME"
  1026. @classmethod
  1027. def value(cls, unit, flat_args, spec_args):
  1028. erm_json = spec_args['erm_json']
  1029. ret = {}
  1030. for tool in erm_json.list_npm_packages():
  1031. tool_resource_label = cls.KEY.format(tool.upper())
  1032. tool_resource_value = unit.get(tool_resource_label)
  1033. if tool_resource_value:
  1034. ret[tool_resource_label] = tool_resource_value
  1035. return ret
  1036. class JvmArgs:
  1037. KEY = 'JVM_ARGS'
  1038. @classmethod
  1039. def value(cls, unit, flat_args, spec_args):
  1040. value = serialize_list(get_values_list(unit, 'JVM_ARGS_VALUE'))
  1041. return {cls.KEY: value}
  1042. class StrictClasspathClash:
  1043. KEY = 'STRICT_CLASSPATH_CLASH'
  1044. class SystemProperties:
  1045. KEY = 'SYSTEM_PROPERTIES'
  1046. @classmethod
  1047. def value(cls, unit, flat_args, spec_args):
  1048. props, error_mgs = extract_java_system_properties(unit, get_values_list(unit, 'SYSTEM_PROPERTIES_VALUE'))
  1049. if error_mgs:
  1050. ymake.report_configure_error(error_mgs)
  1051. raise DartValueError()
  1052. props = base64.b64encode(six.ensure_binary(json.dumps(props)))
  1053. return {cls.KEY: props}
  1054. class UnittestDir:
  1055. KEY = 'UNITTEST_DIR'
  1056. @classmethod
  1057. def value(cls, unit, flat_args, spec_args):
  1058. return {cls.KEY: unit.get('UNITTEST_DIR')}
  1059. class UseArcadiaPython:
  1060. KEY = 'USE_ARCADIA_PYTHON'
  1061. @classmethod
  1062. def value(cls, unit, flat_args, spec_args):
  1063. return {cls.KEY: unit.get('USE_ARCADIA_PYTHON')}
  1064. class UseKtlintOld:
  1065. KEY = 'USE_KTLINT_OLD'
  1066. @classmethod
  1067. def value(cls, unit, flat_args, spec_args):
  1068. if unit.get('_USE_KTLINT_OLD') == 'yes':
  1069. return {cls.KEY: 'yes'}
  1070. class YtSpec:
  1071. KEY = 'YT-SPEC'
  1072. @classmethod
  1073. def from_macro_args_and_unit(cls, unit, flat_args, spec_args):
  1074. value = serialize_list(spec_args.get('YT_SPEC', []) + get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE'))
  1075. return {cls.KEY: value}
  1076. @classmethod
  1077. def from_unit(cls, unit, flat_args, spec_args):
  1078. yt_spec = get_values_list(unit, 'TEST_YT_SPEC_VALUE')
  1079. if yt_spec:
  1080. return {cls.KEY: serialize_list(yt_spec)}
  1081. @classmethod
  1082. def from_unit_list_var(cls, unit, flat_args, spec_args):
  1083. yt_spec_values = get_unit_list_variable(unit, 'TEST_YT_SPEC_VALUE')
  1084. return {cls.KEY: serialize_list(yt_spec_values)}