1#!/usr/bin/env python3
2# Copyright (c) 2023 Intel Corporation
3#
4# SPDX-License-Identifier: Apache-2.0
5"""
6Tests for quarantine.py classes' methods
7"""
8
9import os
10import textwrap
11from unittest import mock
12
13import pytest
14from twisterlib.quarantine import QuarantineData, QuarantineElement, QuarantineException
15
16TESTDATA_1 = [
17    (
18        ['dummy scenario', 'another scenario'],
19        ['dummy platform', 'another platform'],
20        ['dummy architecture', 'another architecture'],
21        ['dummy simulation', 'another simulation'],
22        None,
23        []
24    ),
25    (
26        ['all'],
27        ['dummy platform', 'another platform'],
28        ['dummy architecture', 'another architecture'],
29        ['dummy simulation', 'another simulation'],
30        None,
31        ['scenarios']
32    ),
33    (
34        ['dummy scenario', 'another scenario'],
35        ['dummy platform', 'all'],
36        ['all', 'another architecture'],
37        ['dummy simulation', 'another simulation'],
38        None,
39        ['platforms', 'architectures']
40    ),
41    (
42        ['all', 'another scenario'],
43        [],
44        [],
45        ['all', 'all'],
46        QuarantineException,
47        ['scenarios', 'platforms', 'architectures', 'simulations']
48    ),
49]
50
51
52@pytest.mark.parametrize(
53    'scenarios, platforms, architectures, ' \
54    'simulations, expected_exception, empty_filter_attrs',
55    TESTDATA_1,
56    ids=[
57        'no empties',
58        'all scenarios',
59        'all platforms and architectures',
60        'exception'
61    ]
62)
63def test_quarantineelement_post_init(
64    scenarios,
65    platforms,
66    architectures,
67    simulations,
68    expected_exception,
69    empty_filter_attrs
70):
71    if expected_exception:
72        with pytest.raises(expected_exception):
73            quarantine_element = QuarantineElement(
74                scenarios=scenarios,
75                platforms=platforms,
76                architectures=architectures,
77                simulations=simulations
78            )
79    else:
80        quarantine_element = QuarantineElement(
81            scenarios=scenarios,
82            platforms=platforms,
83            architectures=architectures,
84            simulations=simulations
85        )
86
87        for attr in ['scenarios', 'platforms', 'architectures', 'simulations']:
88            if attr in empty_filter_attrs:
89                assert getattr(quarantine_element, attr) == []
90            else:
91                assert getattr(quarantine_element, attr) != []
92
93
94def test_quarantinedata_post_init():
95    quarantine_element_dict = {
96        'scenarios': ['all'],
97        'platforms': ['dummy platform'],
98        'architectures': [],
99        'simulations': ['dummy simulation', 'another simulation']
100    }
101
102    quarantine_element = QuarantineElement(
103        platforms=['dummy platform'],
104        architectures=[],
105        simulations=['dummy simulation', 'another simulation']
106    )
107
108    quarantine_data_qlist = [quarantine_element, quarantine_element_dict]
109
110    quarantine_data = QuarantineData(quarantine_data_qlist)
111
112    assert quarantine_data.qlist[0] == quarantine_data.qlist[1]
113
114
115TESTDATA_2 = [
116    (
117        '',
118        QuarantineData()
119    ),
120    (
121        textwrap.dedent("""
122        [
123            {
124                \"scenarios\": [\"all\"],
125                \"platforms\": [\"dummy platform\"],
126                \"architectures\": [],
127                \"simulations\": [\"dummy simulation\", \"another simulation\"]
128            }
129        ]
130        """),
131        QuarantineData(
132            [
133                QuarantineElement(
134                    scenarios=[],
135                    platforms=['dummy platform'],
136                    architectures=[],
137                    simulations=['dummy simulation', 'another simulation']
138                )
139            ]
140        )
141    ),
142    (
143        textwrap.dedent("""
144        [
145            {
146                \"I\": [\"am\"],
147                \"not\": \"a\",
148                \"valid\": [],
149                \"JSON\": [\"for\", \"this\"]
150            }
151        ]
152        """),
153        QuarantineException
154    )
155]
156
157
158@pytest.mark.parametrize(
159    'file_contents, expected',
160    TESTDATA_2,
161    ids=['empty', 'valid', 'not valid']
162)
163def test_quarantinedata_load_data_from_yaml(file_contents, expected):
164    with mock.patch('builtins.open', mock.mock_open(read_data=file_contents)):
165        if isinstance(expected, type) and issubclass(expected, Exception):
166            with pytest.raises(expected):
167                res = QuarantineData.load_data_from_yaml(
168                    os.path.join('dummy', 'path')
169                )
170        else:
171            res = QuarantineData.load_data_from_yaml(
172                os.path.join('dummy', 'path')
173            )
174
175            assert res == expected
176
177
178TESTDATA_3 = [
179    (
180        'good scenario',
181        'good platform',
182        'good arch',
183        'good sim',
184        None
185    ),
186    (
187        'good scenario',
188        'very bad dummy platform',
189        'good arch',
190        'good sim',
191        0
192    ),
193    (
194        'bad scenario 1',
195        'good platform',
196        'good arch',
197        'bad sim',
198        1
199    ),
200    (
201        'bad scenario 1',
202        'good platform',
203        'good arch',
204        'sim for scenario 1',
205        None
206    ),
207    (
208        'good scenario',
209        'good platform',
210        'unsupported arch 1',
211        'good sim',
212        2
213    )
214]
215
216
217@pytest.mark.parametrize(
218    'scenario, platform, architecture, simulation, expected_idx',
219    TESTDATA_3,
220    ids=[
221        'not quarantined',
222        'quarantined platform',
223        'quarantined scenario with sim',
224        'not quarantined with bad scenario',
225        'quarantined arch'
226    ]
227)
228def test_quarantinedata_get_matched_quarantine(
229    scenario,
230    platform,
231    architecture,
232    simulation,
233    expected_idx
234):
235    qlist = [
236        QuarantineElement(
237            scenarios=['all'],
238            platforms=['very bad dummy platform'],
239            architectures=['all'],
240            simulations=['all']
241        ),
242        QuarantineElement(
243            scenarios=['bad scenario 1', 'bad scenario 2'],
244            platforms=['all'],
245            architectures=['all'],
246            simulations=['bad sim']
247        ),
248        QuarantineElement(
249            scenarios=['all'],
250            platforms=['all'],
251            architectures=['unsupported arch 1'],
252            simulations=['all']
253        ),
254    ]
255
256    quarantine_data = QuarantineData(qlist)
257
258    if expected_idx is None:
259        assert quarantine_data.get_matched_quarantine(
260            scenario=scenario,
261            platform=platform,
262            architecture=architecture,
263            simulator_name=simulation
264        ) is None
265    else:
266        assert quarantine_data.get_matched_quarantine(
267            scenario=scenario,
268            platform=platform,
269            architecture=architecture,
270            simulator_name=simulation
271        ) == qlist[expected_idx]
272