utils.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Apache-2.0
  3. import logging
  4. import os
  5. import typing as t
  6. from xml.etree import ElementTree as ET
  7. from .constants import TARGET_MARKERS
  8. def format_case_id(target: t.Optional[str], config: t.Optional[str], case: str, is_qemu: bool = False) -> str:
  9. parts = []
  10. if target:
  11. parts.append((str(target) + '_qemu') if is_qemu else str(target))
  12. if config:
  13. parts.append(str(config))
  14. parts.append(case)
  15. return '.'.join(parts)
  16. def get_target_marker_from_expr(markexpr: str) -> str:
  17. candidates = set()
  18. # we use `-m "esp32 and generic"` in our CI to filter the test cases
  19. # this doesn't cover all use cases, but fit what we do in CI.
  20. for marker in markexpr.split('and'):
  21. marker = marker.strip()
  22. if marker in TARGET_MARKERS:
  23. candidates.add(marker)
  24. if len(candidates) > 1:
  25. raise ValueError(f'Specified more than one target markers: {candidates}. Please specify no more than one.')
  26. elif len(candidates) == 1:
  27. return candidates.pop()
  28. else:
  29. raise ValueError('Please specify one target marker via "--target [TARGET]" or via "-m [TARGET]"')
  30. def merge_junit_files(junit_files: t.List[str], target_path: str) -> None:
  31. if len(junit_files) <= 1:
  32. return
  33. merged_testsuite: ET.Element = ET.Element('testsuite')
  34. testcases: t.Dict[str, ET.Element] = {}
  35. for junit in junit_files:
  36. logging.info(f'Merging {junit} to {target_path}')
  37. tree: ET.ElementTree = ET.parse(junit)
  38. testsuite: ET.Element = tree.getroot()
  39. for testcase in testsuite.findall('testcase'):
  40. name: str = testcase.get('name') if testcase.get('name') else '' # type: ignore
  41. if name not in testcases:
  42. testcases[name] = testcase
  43. merged_testsuite.append(testcase)
  44. continue
  45. existing_testcase = testcases[name]
  46. for element_name in ['failure', 'error']:
  47. for element in testcase.findall(element_name):
  48. existing_element = existing_testcase.find(element_name)
  49. if existing_element is None:
  50. existing_testcase.append(element)
  51. else:
  52. existing_element.attrib.setdefault('message', '') # type: ignore
  53. existing_element.attrib['message'] += '. ' + element.get('message', '') # type: ignore
  54. os.remove(junit)
  55. merged_testsuite.set('tests', str(len(merged_testsuite.findall('testcase'))))
  56. merged_testsuite.set('failures', str(len(merged_testsuite.findall('.//testcase/failure'))))
  57. merged_testsuite.set('errors', str(len(merged_testsuite.findall('.//testcase/error'))))
  58. merged_testsuite.set('skipped', str(len(merged_testsuite.findall('.//testcase/skipped'))))
  59. with open(target_path, 'wb') as fw:
  60. fw.write(ET.tostring(merged_testsuite))