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