• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2024-2025 Huawei Device Co., Ltd.
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18import glob
19import logging
20import os
21import pathlib
22import typing
23import jinja2
24import yaml
25import runner.logger as LOG
26import runner.plugins.ets.utils.constants
27import runner.utils
28
29
30class EtsFuncTestsCodeGenerator:
31    _TEST_SEPARATOR = "---"
32    _TEMPLATE_PATTERN = '/*.ets.j2'
33
34
35    def __init__(self, template_root_path: pathlib.Path):
36        self._logger = logging.getLogger("runner.generators.ets_func_tests")
37        self._jinja_env = jinja2.Environment(
38            loader=jinja2.FileSystemLoader(str(template_root_path)),
39            autoescape=jinja2.select_autoescape(),
40            variable_start_string=runner.plugins.ets.utils.constants.VARIABLE_START_STRING
41        )
42
43    @staticmethod
44    def __get_true_file_basename(path:str) -> str:
45        base_fname = os.path.basename(path)
46        while '.' in base_fname:
47            base_fname, _ = os.path.splitext(base_fname)
48        return base_fname
49
50    @staticmethod
51    def __save_artefact_of_generator(test: str, template_fname: str, template_config_fname: str) -> str:
52        test = f"/* Template name : {template_fname}*/\n" + test
53        test = f"/* Config name : {template_config_fname}*/\n\n" + test
54        return test
55
56    def render_and_write_templates(self,
57                                   template_root_path: pathlib.Path,
58                                   current_dir: pathlib.Path,
59                                   outpath: pathlib.Path) -> typing.List[str]:
60        os.makedirs(outpath, exist_ok=True)
61        generated_test_list = []
62        templates_fname_list = self.__find_all_templates(current_dir)
63        for template_fname in templates_fname_list:
64            generated_test_list.extend(self.__render_template(template_fname, template_root_path, outpath))
65        return generated_test_list
66
67    def __find_all_templates(self, current_dir: pathlib.Path) -> typing.List[str]:
68        LOG.Log.summary(self._logger, f"Start searching in : {current_dir}")
69        LOG.Log.summary(self._logger, f"{str(current_dir) + self._TEMPLATE_PATTERN}")
70        templates_fname_list = glob.glob(str(current_dir) + self._TEMPLATE_PATTERN, recursive=False)
71        LOG.Log.summary(self._logger, f"Found {len(templates_fname_list)} templates")
72        return templates_fname_list
73
74    def __build_template_config_file_name(self, template_path_fname: str) -> str:
75        path_parser = pathlib.Path(template_path_fname)
76        template_base_fname = self.__get_true_file_basename(template_path_fname)
77        template_path = path_parser.parent
78        config_fname = "config-" + template_base_fname + ".yaml"
79        LOG.Log.summary(self._logger, f"Config path {config_fname}")
80        result = os.path.join(template_path, config_fname)
81        return result
82
83    def __render_template(self,
84                          template_fname: str,
85                          template_root_path: pathlib.Path,
86                          outpath: pathlib.Path) -> typing.List[str]:
87        generated_tests_list = []
88        template_config_name = self.__build_template_config_file_name(template_fname)
89        path_parser = pathlib.Path(template_fname)
90        template_relative_path = os.path.relpath(path_parser.parent, template_root_path)
91        template_relative_fname = os.path.join(template_relative_path, path_parser.name)
92        LOG.Log.summary(self._logger, f"Load template from {template_relative_fname}")
93        template = self._jinja_env.get_template(template_relative_fname)
94        params = self.__load_parameters(template_config_name)
95        content = template.render(**params)
96        content = content.strip()
97        content_list = self.__split_tests(content)
98        test_idx = 1
99        path_parser = pathlib.Path(template_fname)
100        fname = self.__get_true_file_basename(template_fname)
101
102        for test in content_list:
103            test = self.__save_artefact_of_generator(test, template_fname, template_config_name)
104            output_fname = "test-" + fname + "-" + str(test_idx).zfill(4) + ".ets"
105            outpath_final = outpath / output_fname
106            generated_tests_list.append(str(outpath))
107            runner.utils.write_2_file(outpath_final, test)
108            test_idx += 1
109        return generated_tests_list
110
111    def __load_parameters(self, config_file_path : str) -> typing.Any:
112        with os.fdopen(os.open(config_file_path, os.O_RDONLY, 0o755), "r", encoding='utf8') as f_handle:
113            text = f_handle.read()
114        try:
115            params = yaml.safe_load(text)
116            LOG.Log.summary(self._logger, params)
117        except Exception as common_exp:
118            raise Exception(f"Could not load YAML: {str(common_exp)} filepath={config_file_path}") from common_exp
119        return params
120
121    def __split_tests(self, content : str) -> typing.List[str]:
122        content = content.rstrip(self._TEST_SEPARATOR)
123        content_list = content.split("---")
124        LOG.Log.summary(self._logger, f"size : {len(content_list)}")
125        return content_list
126