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