Skip to content

Commit 0d740d0

Browse files
tcarmelveilleuxcecillerestyled-commits
authoredJul 15, 2024··
Add a mandatory fence to CI tests config and improve Python testing docs (#34319)
* Update docs and introduce fences for CI test metadata * Add fences to all tests * Update docs/testing/python.md Co-authored-by: C Freeman <cecille@google.com> * Restyled by prettier-markdown * Restyled by autopep8 * Restyled by isort --------- Co-authored-by: C Freeman <cecille@google.com> Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 049f5b2 commit 0d740d0

File tree

85 files changed

+651
-185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+651
-185
lines changed
 

‎docs/testing/python.md

+180-159
Large diffs are not rendered by default.

‎scripts/tests/py/metadata.py

+55-24
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@
1414
# limitations under the License.
1515

1616
import re
17+
import sys
1718
from dataclasses import dataclass
1819
from typing import Any, Dict, List
1920

2021
import yaml
2122

2223

24+
def bool_from_str(value: str) -> bool:
25+
"""Convert True/true/False/false strings to bool."""
26+
return value.strip().lower() == "true"
27+
28+
2329
@dataclass
2430
class Metadata:
2531
py_script_path: str
@@ -58,16 +64,59 @@ def copy_from_dict(self, attr_dict: Dict[str, Any]) -> None:
5864
self.py_script_path = attr_dict["py_script_path"]
5965

6066
if "factoryreset" in attr_dict:
61-
self.factoryreset = bool(attr_dict["factoryreset"])
67+
self.factoryreset = bool_from_str(attr_dict["factoryreset"])
6268

6369
if "factoryreset_app_only" in attr_dict:
64-
self.factoryreset_app_only = bool(attr_dict["factoryreset_app_only"])
70+
self.factoryreset_app_only = bool_from_str(attr_dict["factoryreset_app_only"])
6571

6672
if "script_gdb" in attr_dict:
67-
self.script_gdb = bool(attr_dict["script_gdb"])
73+
self.script_gdb = bool_from_str(attr_dict["script_gdb"])
6874

6975
if "quiet" in attr_dict:
70-
self.quiet = bool(attr_dict["quiet"])
76+
self.quiet = bool_from_str(attr_dict["quiet"])
77+
78+
79+
def extract_runs_arg_lines(py_script_path: str) -> Dict[str, Dict[str, str]]:
80+
"""Extract the run arguments from the CI test arguments blocks."""
81+
82+
found_ci_args_section = False
83+
done_ci_args_section = False
84+
85+
runs_def_ptrn = re.compile(r'^\s*#\s*test-runner-runs:\s*(?P<run_id>.*)$')
86+
arg_def_ptrn = re.compile(
87+
r'^\s*#\s*test-runner-run/(?P<run_id>[a-zA-Z0-9_]+)/(?P<arg_name>[a-zA-Z0-9_\-]+):\s*(?P<arg_val>.*)$')
88+
89+
runs_arg_lines: Dict[str, Dict[str, str]] = {}
90+
91+
with open(py_script_path, 'r', encoding='utf8') as py_script:
92+
for line_idx, line in enumerate(py_script.readlines()):
93+
line = line.strip()
94+
line_num = line_idx + 1
95+
96+
# Detect the single CI args section, to skip the lines otherwise.
97+
if not done_ci_args_section and line.startswith("# === BEGIN CI TEST ARGUMENTS ==="):
98+
found_ci_args_section = True
99+
elif found_ci_args_section and line.startswith("# === END CI TEST ARGUMENTS ==="):
100+
done_ci_args_section = True
101+
found_ci_args_section = False
102+
103+
runs_match = runs_def_ptrn.match(line)
104+
args_match = arg_def_ptrn.match(line)
105+
106+
if not found_ci_args_section and (runs_match or args_match):
107+
print(f"WARNING: {py_script_path}:{line_num}: Found CI args outside of CI TEST ARGUMENTS block!", file=sys.stderr)
108+
continue
109+
110+
if runs_match:
111+
for run in runs_match.group("run_id").strip().split():
112+
runs_arg_lines[run] = {}
113+
runs_arg_lines[run]['run'] = run
114+
runs_arg_lines[run]['py_script_path'] = py_script_path
115+
116+
elif args_match:
117+
runs_arg_lines[args_match.group("run_id")][args_match.group("arg_name")] = args_match.group("arg_val")
118+
119+
return runs_arg_lines
71120

72121

73122
class MetadataReader:
@@ -126,33 +175,15 @@ def parse_script(self, py_script_path: str) -> List[Metadata]:
126175
the run arguments associated with a particular run defined in
127176
the script file.
128177
"""
129-
130-
runs_def_ptrn = re.compile(r'^\s*#\s*test-runner-runs:\s*(.*)$')
131-
arg_def_ptrn = re.compile(r'^\s*#\s*test-runner-run/([a-zA-Z0-9_]+)/([a-zA-Z0-9_\-]+):\s*(.*)$')
132-
133-
runs_arg_lines: Dict[str, Dict[str, str]] = {}
134178
runs_metadata: List[Metadata] = []
135-
136-
with open(py_script_path, 'r', encoding='utf8') as py_script:
137-
for line in py_script.readlines():
138-
runs_match = runs_def_ptrn.match(line.strip())
139-
args_match = arg_def_ptrn.match(line.strip())
140-
141-
if runs_match:
142-
for run in runs_match.group(1).strip().split():
143-
runs_arg_lines[run] = {}
144-
runs_arg_lines[run]['run'] = run
145-
runs_arg_lines[run]['py_script_path'] = py_script_path
146-
147-
elif args_match:
148-
runs_arg_lines[args_match.group(1)][args_match.group(2)] = args_match.group(3)
179+
runs_arg_lines = extract_runs_arg_lines(py_script_path)
149180

150181
for run, attr in runs_arg_lines.items():
151182
self.__resolve_env_vals__(attr)
152183

153184
metadata = Metadata(
154185
py_script_path=attr.get("py_script_path", ""),
155-
run=attr.get("run", ""),
186+
run=run,
156187
app=attr.get("app", ""),
157188
app_args=attr.get("app_args", ""),
158189
script_args=attr.get("script_args", ""),

0 commit comments

Comments
 (0)
Please sign in to comment.