Merge branch 'test/enhanced_unit_test_config_dependency' into 'master'

test: enhanced config dependency support for CI

See merge request idf/esp-idf!3383
This commit is contained in:
Angus Gratton
2018-10-05 09:21:30 +08:00

View File

@@ -4,7 +4,6 @@ import os
import re import re
import shutil import shutil
import subprocess import subprocess
import hashlib
from copy import deepcopy from copy import deepcopy
import CreateSectionTable import CreateSectionTable
@@ -31,6 +30,7 @@ class Parser(object):
TAG_PATTERN = re.compile("([^=]+)(=)?(.+)?") TAG_PATTERN = re.compile("([^=]+)(=)?(.+)?")
DESCRIPTION_PATTERN = re.compile("\[([^]\[]+)\]") DESCRIPTION_PATTERN = re.compile("\[([^]\[]+)\]")
CONFIG_PATTERN = re.compile(r"{([^}]+)}")
# file path (relative to idf path) # file path (relative to idf path)
TAG_DEF_FILE = os.path.join("tools", "unit-test-app", "tools", "TagDefinition.yml") TAG_DEF_FILE = os.path.join("tools", "unit-test-app", "tools", "TagDefinition.yml")
@@ -49,7 +49,7 @@ class Parser(object):
self.idf_path = idf_path self.idf_path = idf_path
self.tag_def = yaml.load(open(os.path.join(idf_path, self.TAG_DEF_FILE), "r")) self.tag_def = yaml.load(open(os.path.join(idf_path, self.TAG_DEF_FILE), "r"))
self.module_map = yaml.load(open(os.path.join(idf_path, self.MODULE_DEF_FILE), "r")) self.module_map = yaml.load(open(os.path.join(idf_path, self.MODULE_DEF_FILE), "r"))
self.config_dependency = yaml.load(open(os.path.join(idf_path, self.CONFIG_DEPENDENCY_FILE), "r")) self.config_dependencies = yaml.load(open(os.path.join(idf_path, self.CONFIG_DEPENDENCY_FILE), "r"))
# used to check if duplicated test case names # used to check if duplicated test case names
self.test_case_names = set() self.test_case_names = set()
self.parsing_errors = [] self.parsing_errors = []
@@ -150,23 +150,56 @@ class Parser(object):
pass pass
return p return p
@staticmethod
def parse_tags_internal(sdkconfig, config_dependencies, config_pattern):
required_tags = []
def compare_config(config):
return config in sdkconfig
def process_condition(condition):
matches = config_pattern.findall(condition)
if matches:
for config in matches:
compare_result = compare_config(config)
# replace all configs in condition with True or False according to compare result
condition = re.sub(config_pattern, str(compare_result), condition, count=1)
# Now the condition is a python condition, we can use eval to compute its value
ret = eval(condition)
else:
# didn't use complex condition. only defined one condition for the tag
ret = compare_config(condition)
return ret
for tag in config_dependencies:
if process_condition(config_dependencies[tag]):
required_tags.append(tag)
return required_tags
def parse_tags(self, sdkconfig_file): def parse_tags(self, sdkconfig_file):
""" """
Some test configs could requires different DUTs. Some test configs could requires different DUTs.
For example, if CONFIG_SPIRAM_SUPPORT is enabled, we need WROVER-Kit to run test. For example, if CONFIG_SPIRAM_SUPPORT is enabled, we need WROVER-Kit to run test.
This method will get tags for runners according to ConfigDependency.yml(maps tags to sdkconfig). This method will get tags for runners according to ConfigDependency.yml(maps tags to sdkconfig).
We support to the following syntax::
# define the config which requires the tag
'tag_a': 'config_a="value_a"'
# define the condition for the tag
'tag_b': '{config A} and (not {config B} or (not {config C} and {config D}))'
:param sdkconfig_file: sdk config file of the unit test config :param sdkconfig_file: sdk config file of the unit test config
:return: required tags for runners :return: required tags for runners
""" """
required_tags = []
with open(sdkconfig_file, "r") as f: with open(sdkconfig_file, "r") as f:
configs_raw_data = f.read() configs_raw_data = f.read()
configs = configs_raw_data.splitlines(False) configs = configs_raw_data.splitlines(False)
for tag in self.config_dependency:
if self.config_dependency[tag] in configs: return self.parse_tags_internal(configs, self.config_dependencies, self.CONFIG_PATTERN)
required_tags.append(tag)
return required_tags
def parse_one_test_case(self, name, description, file_name, config_name, tags): def parse_one_test_case(self, name, description, file_name, config_name, tags):
""" """
@@ -254,6 +287,18 @@ def test_parser():
prop = parser.parse_case_properities("[esp32][[ignore=b]][]][test_env=AAA]]") prop = parser.parse_case_properities("[esp32][[ignore=b]][]][test_env=AAA]]")
assert prop["module"] == "esp32" and prop["ignore"] == "b" and prop["test_env"] == "AAA" assert prop["module"] == "esp32" and prop["ignore"] == "b" and prop["test_env"] == "AAA"
config_dependency = {
'a': '123',
'b': '456',
'c': 'not {123}',
'd': '{123} and not {456}',
'e': '{123} and not {789}',
'f': '({123} and {456}) or ({123} and {789})'
}
sdkconfig = ["123", "789"]
tags = parser.parse_tags_internal(sdkconfig, config_dependency, parser.CONFIG_PATTERN)
assert tags == ['a', 'd', 'f']
def main(): def main():
test_parser() test_parser()