1#!/usr/bin/env python3
2# Copyright (c) 2024 Intel Corporation
3#
4# SPDX-License-Identifier: Apache-2.0
5"""
6Blackbox tests for twister's command line functions related to disable features.
7"""
8
9import importlib
10import pytest
11import mock
12import os
13import sys
14import re
15
16from conftest import ZEPHYR_BASE, TEST_DATA, testsuite_filename_mock
17from twisterlib.testplan import TestPlan
18
19
20@mock.patch.object(TestPlan, 'TESTSUITE_FILENAME', testsuite_filename_mock)
21class TestDisable:
22    TESTDATA_1 = [
23        (
24            os.path.join(TEST_DATA, 'tests', 'dummy', 'agnostic'),
25            ['qemu_x86'],
26            '--disable-suite-name-check',
27            [r"Expected suite names:\[['\w+'\[,\s]*\]", r"Detected suite names:\[['\w+'\[,\s]*\]"],
28            True
29        ),
30        (
31            os.path.join(TEST_DATA, 'tests', 'dummy', 'agnostic'),
32            ['qemu_x86'],
33            '-v',
34            [r"Expected suite names:\[['(\w+)'[, ]*]+", r"Detected suite names:\[['(\w+)'[, ]*]+"],
35            False
36        ),
37    ]
38    TESTDATA_2 = [
39        (
40            os.path.join(TEST_DATA, 'tests', 'always_warning'),
41            ['qemu_x86'],
42            '--disable-warnings-as-errors',
43            '0'
44        ),
45        (
46            os.path.join(TEST_DATA, 'tests', 'always_warning'),
47            ['qemu_x86'],
48            '-v',
49            '1'
50        ),
51    ]
52
53
54    @classmethod
55    def setup_class(cls):
56        apath = os.path.join(ZEPHYR_BASE, 'scripts', 'twister')
57        cls.loader = importlib.machinery.SourceFileLoader('__main__', apath)
58        cls.spec = importlib.util.spec_from_loader(cls.loader.name, cls.loader)
59        cls.twister_module = importlib.util.module_from_spec(cls.spec)
60
61
62    @classmethod
63    def teardown_class(cls):
64        pass
65
66
67    @pytest.mark.parametrize(
68        'test_path, test_platforms, flag, expected, expected_none',
69        TESTDATA_1,
70        ids=[
71            'disable-suite-name-check',
72            'suite-name-check'
73        ],
74    )
75
76    def test_disable_suite_name_check(self, capfd, out_path, test_path, test_platforms, flag, expected, expected_none):
77        args = ['-i', '--outdir', out_path, '-T', test_path] + \
78               [flag] + \
79               ['-vv', '-ll', 'DEBUG'] + \
80               [val for pair in zip(
81                   ['-p'] * len(test_platforms), test_platforms
82               ) for val in pair]
83
84        with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \
85            pytest.raises(SystemExit) as sys_exit:
86            self.loader.exec_module(self.twister_module)
87
88        out, err = capfd.readouterr()
89        sys.stdout.write(out)
90        sys.stderr.write(err)
91
92        assert str(sys_exit.value) == '0'
93        if expected_none:
94            assert re.search(expected[0], err) is None, f"Not expected string in log: {expected[0]}"
95            assert re.search(expected[1], err) is None, f"Not expected: {expected[1]}"
96        else:
97            assert re.search(expected[0], err) is not None, f"Expected string in log: {expected[0]}"
98            assert re.search(expected[1], err) is not None, f"Expected string in log: {expected[1]}"
99
100
101    @pytest.mark.parametrize(
102        'test_path, test_platforms, flag, expected_exit_code',
103        TESTDATA_2,
104        ids=[
105            'disable-warnings-as-errors',
106            'warnings-as-errors'
107        ],
108    )
109
110    def test_disable_warnings_as_errors(self, capfd, out_path, test_path, test_platforms, flag, expected_exit_code):
111        args = ['-i', '--outdir', out_path, '-T', test_path] + \
112               [flag] + \
113               ['-vv'] + \
114               ['--build-only'] + \
115               [val for pair in zip(
116                   ['-p'] * len(test_platforms), test_platforms
117               ) for val in pair]
118
119        with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \
120            pytest.raises(SystemExit) as sys_exit:
121            self.loader.exec_module(self.twister_module)
122
123        out, err = capfd.readouterr()
124        sys.stdout.write(out)
125        sys.stderr.write(err)
126
127        assert str(sys_exit.value) == expected_exit_code, \
128            f"Twister return not expected ({expected_exit_code}) exit code: ({sys_exit.value})"
129