• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2021-2024 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
18# This file defines the CTS test metadata format
19# The entrypoint is the 'find_all_metas' function
20
21import re
22from unittest import TestCase
23from typing import Tuple, List, Dict
24
25import yaml
26
27from runner.plugins.ets.utils.constants import META_END_PATTERN, META_END_STRING, META_START_PATTERN, META_START_STRING
28
29ParsedMeta = Dict
30MetaInText = Tuple[int, int, ParsedMeta]
31
32
33class InvalidMetaException(Exception):
34    def __init__(self, msg: str) -> None:
35        super().__init__()
36        self.message = msg
37
38
39def find_all_metas(text: str) -> List[MetaInText]:
40    """
41    Given a text of the whole test, this function:
42    1) Find all metas in this text
43    2) Parses each meta and verifies its correctness
44    Returns a list of tuples (start: int, end: int, meta: ParsedMeta),
45    where 'start' and 'end' are indices in 'text' such that text[start:end] == "/*---" + strMeta + "---*/"
46    and 'meta' is the parsed meta
47
48    Raised: InvalidMetaException
49    """
50    result = []
51
52    start_indices = [m.start() for m in re.finditer(META_START_PATTERN, text)]
53    end_indices = [m.end() for m in re.finditer(META_END_PATTERN, text)]
54
55    if len(start_indices) != len(end_indices) or len(start_indices) == 0:
56        raise InvalidMetaException("Invalid meta or meta doesn't exist")
57
58    meta_bounds = list(zip(start_indices, end_indices))
59
60    # verify meta bounds
61    for i in range(1, len(meta_bounds)):
62        prev_start, prev_end = meta_bounds[i - 1]
63        start, end = meta_bounds[i]
64        if not prev_start < prev_end < start < end:
65            raise InvalidMetaException("Invalid meta")
66
67    for start, end in meta_bounds:
68        meta = __parse_meta(text[start:end])
69        result.append((start, end, meta))
70
71    return result
72
73
74def __parse_meta(meta: str) -> Dict:
75    """
76    Given a meta, a string that starts with '/*---', ends with '---*/' and contains a valid YAML in between,
77    this function parses that meta and validating it.
78    """
79    test = TestCase()
80    test.assertTrue(len(meta) > len(META_START_STRING) + len(META_END_STRING))
81    test.assertTrue(meta.startswith(META_START_STRING) and meta.endswith(META_END_STRING))
82
83    yaml_string = meta[len(META_START_STRING):-len(META_END_STRING)]
84    try:
85        data = yaml.safe_load(yaml_string)
86        if isinstance(data, dict):
87            return data
88        test.assertTrue(isinstance(data, dict), "Invalid data format")
89        return {}
90    except Exception as common_exp:
91        raise InvalidMetaException(str(common_exp)) from common_exp
92