1#!/usr/bin/env python3
2# Copyright (c) 2023 Intel Corporation
3#
4# SPDX-License-Identifier: Apache-2.0
5"""
6Tests for domains.py classes
7"""
8
9import mock
10import os
11import pytest
12import sys
13
14ZEPHYR_BASE = os.getenv("ZEPHYR_BASE")
15sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/build_helpers"))
16
17import domains
18
19from contextlib import nullcontext
20
21
22TESTDATA_1 = [
23    ('', False, 1, ['domains.yaml file not found: domains.yaml']),
24    (
25"""
26default: None
27build_dir: some/dir
28domains: []
29""",
30        True, None, []
31    ),
32]
33
34@pytest.mark.parametrize(
35    'f_contents, f_exists, exit_code, expected_logs',
36    TESTDATA_1,
37    ids=['no file', 'valid']
38)
39def test_from_file(caplog, f_contents, f_exists, exit_code, expected_logs):
40    def mock_open(*args, **kwargs):
41        if f_exists:
42            return mock.mock_open(read_data=f_contents)(args, kwargs)
43        raise FileNotFoundError(f'domains.yaml not found.')
44
45    init_mock = mock.Mock(return_value=None)
46
47    with mock.patch('domains.Domains.__init__', init_mock), \
48         mock.patch('builtins.open', mock_open), \
49         pytest.raises(SystemExit) if exit_code else nullcontext() as s_exit:
50        result = domains.Domains.from_file('domains.yaml')
51
52    if exit_code:
53        assert str(s_exit.value) == str(exit_code)
54    else:
55        init_mock.assert_called_once()
56        assert result is not None
57
58    assert all([log in caplog.text for log in expected_logs])
59
60
61TESTDATA_2 = [
62    (
63"""
64default: some default
65build_dir: my/dir
66domains:
67- name: some default
68  build_dir: dir/2
69- name: another
70  build_dir: dir/3
71flash_order: I don\'t think this is correct
72""",
73        1, None, None, None, None
74    ),
75    (
76"""
77build_dir: build/dir
78domains:
79- name: a domain
80  build_dir: dir/1
81- name: default_domain
82  build_dir: dir/2
83default: default_domain
84flash_order:
85- default_domain
86- a domain
87""",
88        None,
89        'build/dir',
90        [('default_domain', 'dir/2'), ('a domain', 'dir/1')],
91        ('default_domain', 'dir/2'),
92        {'a domain': ('a domain', 'dir/1'),
93         'default_domain': ('default_domain', 'dir/2')}
94    ),
95]
96
97@pytest.mark.parametrize(
98    'data, exit_code, expected_build_dir, expected_flash_order,' \
99    ' expected_default, expected_domains',
100    TESTDATA_2,
101    ids=['invalid', 'valid']
102)
103def test_from_yaml(
104    caplog,
105    data,
106    exit_code,
107    expected_build_dir,
108    expected_flash_order,
109    expected_default,
110    expected_domains
111):
112    def mock_domain(name, build_dir, *args, **kwargs):
113        return name, build_dir
114
115    with mock.patch('domains.Domain', side_effect=mock_domain), \
116         pytest.raises(SystemExit) if exit_code else nullcontext() as exit_st:
117        doms = domains.Domains.from_yaml(data)
118
119    if exit_code:
120        assert str(exit_st.value) == str(exit_code)
121        return
122
123    assert doms.get_default_domain() == expected_default
124    assert doms.get_top_build_dir() == expected_build_dir
125
126    assert doms._domains == expected_domains
127
128    assert all([d in expected_flash_order for d in doms._flash_order])
129    assert all([d in doms._flash_order for d in expected_flash_order])
130
131
132TESTDATA_3 = [
133    (
134        None,
135        True,
136        [('some', os.path.join('dir', '2')),
137         ('order', os.path.join('dir', '1'))]
138    ),
139    (
140        None,
141        False,
142        [('order', os.path.join('dir', '1')),
143         ('some', os.path.join('dir', '2'))]
144    ),
145    (
146        ['some'],
147        False,
148        [('some', os.path.join('dir', '2'))]
149    ),
150]
151
152@pytest.mark.parametrize(
153    'names, default_flash_order, expected_result',
154    TESTDATA_3,
155    ids=['order only', 'no parameters', 'valid']
156)
157def test_get_domains(
158    caplog,
159    names,
160    default_flash_order,
161    expected_result
162):
163    doms = domains.Domains(
164"""
165domains:
166- name: dummy
167  build_dir: dummy
168default: dummy
169build_dir: dummy
170"""
171    )
172    doms._flash_order = [
173        ('some', os.path.join('dir', '2')),
174        ('order', os.path.join('dir', '1'))
175    ]
176    doms._domains = {
177        'order': ('order', os.path.join('dir', '1')),
178        'some': ('some', os.path.join('dir', '2'))
179    }
180
181    result = doms.get_domains(names, default_flash_order)
182
183    assert result == expected_result
184
185
186
187TESTDATA_3 = [
188    (
189        'other',
190        1,
191        ['domain "other" not found, valid domains are: order, some'],
192        None
193    ),
194    (
195        'some',
196        None,
197        [],
198        ('some', os.path.join('dir', '2'))
199    ),
200]
201
202@pytest.mark.parametrize(
203    'name, exit_code, expected_logs, expected_result',
204    TESTDATA_3,
205    ids=['domain not found', 'valid']
206)
207def test_get_domain(
208    caplog,
209    name,
210    exit_code,
211    expected_logs,
212    expected_result
213):
214    doms = domains.Domains(
215"""
216domains:
217- name: dummy
218  build_dir: dummy
219default: dummy
220build_dir: dummy
221"""
222    )
223    doms._flash_order = [
224        ('some', os.path.join('dir', '2')),
225        ('order', os.path.join('dir', '1'))
226    ]
227    doms._domains = {
228        'order': ('order', os.path.join('dir', '1')),
229        'some': ('some', os.path.join('dir', '2'))
230    }
231
232    with pytest.raises(SystemExit) if exit_code else nullcontext() as s_exit:
233        result = doms.get_domain(name)
234
235    assert all([log in caplog.text for log in expected_logs])
236
237    if exit_code:
238        assert str(s_exit.value) == str(exit_code)
239    else:
240        assert result == expected_result
241
242
243def test_domain():
244    name = 'Domain Name'
245    build_dir = 'build/dir'
246
247    domain = domains.Domain(name, build_dir)
248
249    assert domain.name == name
250    assert domain.build_dir == build_dir
251
252    domain.name = 'New Name'
253    domain.build_dir = 'new/dir'
254
255    assert domain.name == 'New Name'
256    assert domain.build_dir == 'new/dir'
257