blob: 37b60ae1417ed6e64e906e7cd9470f4c50426dd9 [file] [log] [blame]
Aastha Grover5948ab62020-05-11 15:38:37 -07001#!/usr/bin/env python3
2# Copyright (c) 2020 Intel Corporation
3#
4# SPDX-License-Identifier: Apache-2.0
Aastha Grovercf72fe82020-06-01 16:08:20 -07005
Aastha Grover5948ab62020-05-11 15:38:37 -07006'''
Anas Nashif9318e6c2020-12-07 12:29:36 -05007This test file contains testcases for Testsuite class of twister
Aastha Grover5948ab62020-05-11 15:38:37 -07008'''
9import sys
10import os
Aastha Grovercf72fe82020-06-01 16:08:20 -070011import csv
Aastha Grover27435ce2020-05-26 11:23:46 -070012import pytest
Aastha Grovercf72fe82020-06-01 16:08:20 -070013from mock import call, patch, MagicMock
Aastha Grover5948ab62020-05-11 15:38:37 -070014
15ZEPHYR_BASE = os.getenv("ZEPHYR_BASE")
Anas Nashif9318e6c2020-12-07 12:29:36 -050016sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister"))
Aastha Grover5948ab62020-05-11 15:38:37 -070017
Anas Nashif9318e6c2020-12-07 12:29:36 -050018from twisterlib import TestCase, TestSuite, TestInstance, Platform
Aastha Grover5948ab62020-05-11 15:38:37 -070019
20def test_testsuite_add_testcases(class_testsuite):
Anas Nashif9318e6c2020-12-07 12:29:36 -050021 """ Testing add_testcase function of Testsuite class in twister """
Aastha Grover5948ab62020-05-11 15:38:37 -070022 # Test 1: Check the list of testcases after calling add testcases function is as expected
23 class_testsuite.SAMPLE_FILENAME = 'test_sample_app.yaml'
24 class_testsuite.TESTCASE_FILENAME = 'test_data.yaml'
25 class_testsuite.add_testcases()
Anas Nashif9318e6c2020-12-07 12:29:36 -050026 tests_rel_dir = 'scripts/tests/twister/test_data/testcases/tests/'
Aastha Grover5948ab62020-05-11 15:38:37 -070027 expected_testcases = ['test_b.check_1',
28 'test_b.check_2',
29 'test_c.check_1',
30 'test_c.check_2',
31 'test_a.check_1',
32 'test_a.check_2',
33 'sample_test.app']
34 testcase_list = []
35 for key in sorted(class_testsuite.testcases.keys()):
36 testcase_list.append(os.path.basename(os.path.normpath(key)))
37 assert sorted(testcase_list) == sorted(expected_testcases)
38
Aastha Grovercf72fe82020-06-01 16:08:20 -070039 # Test 2 : Assert Testcase name is expected & all testcases values are testcase class objects
Aastha Grover5948ab62020-05-11 15:38:37 -070040 testcase = class_testsuite.testcases.get(tests_rel_dir + 'test_a/test_a.check_1')
41 assert testcase.name == tests_rel_dir + 'test_a/test_a.check_1'
42 assert all(isinstance(n, TestCase) for n in class_testsuite.testcases.values())
Aastha Grover27435ce2020-05-26 11:23:46 -070043
44@pytest.mark.parametrize("board_root_dir", [("board_config_file_not_exist"), ("board_config")])
45def test_add_configurations(test_data, class_testsuite, board_root_dir):
Anas Nashif45943702020-12-11 17:55:15 -050046 """ Testing add_configurations function of TestSuite class in Twister
Aastha Grover27435ce2020-05-26 11:23:46 -070047 Test : Asserting on default platforms list
48 """
49 class_testsuite.board_roots = os.path.abspath(test_data + board_root_dir)
50 suite = TestSuite(class_testsuite.board_roots, class_testsuite.roots, class_testsuite.outdir)
51 if board_root_dir == "board_config":
52 suite.add_configurations()
53 assert sorted(suite.default_platforms) == sorted(['demo_board_1', 'demo_board_3'])
54 elif board_root_dir == "board_config_file_not_exist":
55 suite.add_configurations()
56 assert sorted(suite.default_platforms) != sorted(['demo_board_1'])
57
58def test_get_all_testcases(class_testsuite, all_testcases_dict):
Anas Nashif45943702020-12-11 17:55:15 -050059 """ Testing get_all_testcases function of TestSuite class in Twister """
Aastha Grover27435ce2020-05-26 11:23:46 -070060 class_testsuite.testcases = all_testcases_dict
Spoorthy Priya Yerabolu473ed342020-06-25 03:02:13 -070061 expected_tests = ['sample_test.app', 'test_a.check_1.1a', 'test_a.check_1.1c',
62 'test_a.check_1.2a', 'test_a.check_1.2b', 'test_a.check_1.Unit_1c', 'test_a.check_1.unit_1a', 'test_a.check_1.unit_1b', 'test_a.check_2.1a', 'test_a.check_2.1c', 'test_a.check_2.2a', 'test_a.check_2.2b', 'test_a.check_2.Unit_1c', 'test_a.check_2.unit_1a', 'test_a.check_2.unit_1b', 'test_b.check_1', 'test_b.check_2', 'test_c.check_1', 'test_c.check_2']
63 assert len(class_testsuite.get_all_tests()) == 19
Aastha Grover27435ce2020-05-26 11:23:46 -070064 assert sorted(class_testsuite.get_all_tests()) == sorted(expected_tests)
65
66def test_get_toolchain(class_testsuite, monkeypatch, capsys):
Anas Nashif45943702020-12-11 17:55:15 -050067 """ Testing get_toolchain function of TestSuite class in Twister
Aastha Grover27435ce2020-05-26 11:23:46 -070068 Test 1 : Test toolchain returned by get_toolchain function is same as in the environment.
69 Test 2 : Monkeypatch to delete the ZEPHYR_TOOLCHAIN_VARIANT env var
70 and check if appropriate error is raised"""
71 monkeypatch.setenv("ZEPHYR_TOOLCHAIN_VARIANT", "zephyr")
72 toolchain = class_testsuite.get_toolchain()
73 assert toolchain in ["zephyr"]
74
75 monkeypatch.delenv("ZEPHYR_TOOLCHAIN_VARIANT", raising=False)
76 with pytest.raises(SystemExit):
77 class_testsuite.get_toolchain()
78 out, _ = capsys.readouterr()
79 assert out == "E: Variable ZEPHYR_TOOLCHAIN_VARIANT is not defined\n"
80
81def test_get_platforms(class_testsuite, platforms_list):
Anas Nashif45943702020-12-11 17:55:15 -050082 """ Testing get_platforms function of TestSuite class in Twister """
Aastha Grover27435ce2020-05-26 11:23:46 -070083 class_testsuite.platforms = platforms_list
84 platform = class_testsuite.get_platform("demo_board_1")
85 assert isinstance(platform, Platform)
86 assert platform.name == "demo_board_1"
Aastha Grovercf72fe82020-06-01 16:08:20 -070087
88def test_load_from_file(test_data, class_testsuite,
89 platforms_list, all_testcases_dict, caplog, tmpdir_factory):
Anas Nashif45943702020-12-11 17:55:15 -050090 """ Testing load_from_file function of TestSuite class in Twister """
Aastha Grovercf72fe82020-06-01 16:08:20 -070091 # Scenario 1 : Validating the error raised if file to load from doesn't exist
92 with pytest.raises(SystemExit):
Anas Nashif9318e6c2020-12-07 12:29:36 -050093 class_testsuite.load_from_file(test_data +"twister_test.csv")
Aastha Grovercf72fe82020-06-01 16:08:20 -070094 assert "Couldn't find input file with list of tests." in caplog.text
95
96 # Scenario 2: Testing if the 'instances' dictionary in Testsuite class contains
97 # the expected values after execution of load_from_file function
98 # Note: tmp_dir is the temporary directory created so that the contents
99 # get deleted after invocation of this testcase.
100 tmp_dir = tmpdir_factory.mktemp("tmp")
101 class_testsuite.outdir = tmp_dir
102 class_testsuite.platforms = platforms_list
103 class_testsuite.testcases = all_testcases_dict
104 instance_name_list = []
105 failed_platform_list = []
Anas Nashif9318e6c2020-12-07 12:29:36 -0500106 with open(os.path.join(test_data, "twister.csv"), "r") as filepath:
Aastha Grovercf72fe82020-06-01 16:08:20 -0700107 for row in csv.DictReader(filepath):
108 testcase_root = os.path.join(ZEPHYR_BASE,
Anas Nashif9318e6c2020-12-07 12:29:36 -0500109 "scripts/tests/twister/test_data/testcases")
Aastha Grovercf72fe82020-06-01 16:08:20 -0700110 workdir = row['test'].split('/')[-3] + "/" + row['test'].split('/')[-2]
111 test_name = os.path.basename(os.path.normpath(row['test']))
112 testcase = TestCase(testcase_root, workdir, test_name)
113 testcase.build_only = False
114 instance_name = row["platform"] + "/" + row["test"]
115 instance_name_list.append(instance_name)
Anas Nashif9318e6c2020-12-07 12:29:36 -0500116 class_testsuite.load_from_file(test_data + "twister.csv")
Aastha Grovercf72fe82020-06-01 16:08:20 -0700117 assert list(class_testsuite.instances.keys()) == instance_name_list
118
119 #Scenario 3 : Assert the number of times mock method (get_platform) is called,
120 # equals to the number of testcases failed
121 failed_platform_list = [row["platform"]
122 for row in csv.DictReader(filepath)
123 if row["status"] == "failed"]
124 for row in failed_platform_list:
125 with patch.object(TestSuite, 'get_platform') as mock_method:
Anas Nashif9318e6c2020-12-07 12:29:36 -0500126 class_testsuite.load_from_file(class_testsuite.outdir + "twister.csv",
Aastha Grovercf72fe82020-06-01 16:08:20 -0700127 filter_status=["Skipped", "Passed"])
128 calls = [call(row)]
129 mock_method.assert_has_calls(calls, any_order=True)
130 assert mock_method.call_count == len(failed_platform_list)
131
132 # Scenario 4 : Assert add_instances function is called from load_from_file function
133 class_testsuite.add_instances = MagicMock(side_effect=class_testsuite.add_instances)
Anas Nashif9318e6c2020-12-07 12:29:36 -0500134 class_testsuite.load_from_file(test_data + "twister.csv")
Aastha Grovercf72fe82020-06-01 16:08:20 -0700135 class_testsuite.add_instances.assert_called()
136
137 # Scenario 5 : Validate if the Keyerror is raised in case if a header expected is missing
138 with pytest.raises(SystemExit):
Anas Nashif9318e6c2020-12-07 12:29:36 -0500139 class_testsuite.load_from_file(test_data + "twister_keyerror.csv")
Aastha Grovercf72fe82020-06-01 16:08:20 -0700140 assert "Key error while parsing tests file.('status')" in caplog.text
141
142TESTDATA_PART1 = [
Anas Nashifdca317c2020-08-26 11:28:25 -0400143 ("toolchain_allow", ['gcc'], None, None, "Not in testcase toolchain allow list"),
144 ("platform_allow", ['demo_board_1'], None, None, "Not in testcase platform allow list"),
Aastha Grovercf72fe82020-06-01 16:08:20 -0700145 ("toolchain_exclude", ['zephyr'], None, None, "In test case toolchain exclude"),
146 ("platform_exclude", ['demo_board_2'], None, None, "In test case platform exclude"),
147 ("arch_exclude", ['x86_demo'], None, None, "In test case arch exclude"),
Anas Nashifdca317c2020-08-26 11:28:25 -0400148 ("arch_allow", ['arm'], None, None, "Not in test case arch allow list"),
Aastha Grovercf72fe82020-06-01 16:08:20 -0700149 ("skip", True, None, None, "Skip filter"),
Anas Nashife8e367a2020-07-16 16:27:04 -0400150 ("tags", set(['sensor', 'bluetooth']), "ignore_tags", ['bluetooth'], "Excluded tags per platform (exclude_tags)"),
Aastha Grovercf72fe82020-06-01 16:08:20 -0700151 ("min_flash", "2024", "flash", "1024", "Not enough FLASH"),
152 ("min_ram", "500", "ram", "256", "Not enough RAM"),
153 ("None", "None", "env", ['BSIM_OUT_PATH', 'demo_env'], "Environment (BSIM_OUT_PATH, demo_env) not satisfied"),
154 ("build_on_all", True, None, None, "Platform is excluded on command line."),
155 (None, None, "supported_toolchains", ['gcc'], "Not supported by the toolchain"),
Aastha Grovercf72fe82020-06-01 16:08:20 -0700156]
157
158
159@pytest.mark.parametrize("tc_attribute, tc_value, plat_attribute, plat_value, expected_discards",
160 TESTDATA_PART1)
161def test_apply_filters_part1(class_testsuite, all_testcases_dict, platforms_list,
162 tc_attribute, tc_value, plat_attribute, plat_value, expected_discards):
Anas Nashif45943702020-12-11 17:55:15 -0500163 """ Testing apply_filters function of TestSuite class in Twister
Aastha Grovercf72fe82020-06-01 16:08:20 -0700164 Part 1: Response of apply_filters function (discard dictionary) have
Aastha Grover8213a152020-06-16 12:15:47 -0700165 appropriate values according to the filters
Aastha Grovercf72fe82020-06-01 16:08:20 -0700166 """
167 if tc_attribute is None and plat_attribute is None:
168 discards = class_testsuite.apply_filters()
169 assert not discards
170
171 class_testsuite.platforms = platforms_list
172 class_testsuite.testcases = all_testcases_dict
173 for plat in class_testsuite.platforms:
174 if plat_attribute == "ignore_tags":
175 plat.ignore_tags = plat_value
176 if plat_attribute == "flash":
177 plat.flash = plat_value
178 if plat_attribute == "ram":
179 plat.ram = plat_value
180 if plat_attribute == "env":
181 plat.env = plat_value
182 plat.env_satisfied = False
183 if plat_attribute == "supported_toolchains":
184 plat.supported_toolchains = plat_value
185 for _, testcase in class_testsuite.testcases.items():
Anas Nashifdca317c2020-08-26 11:28:25 -0400186 if tc_attribute == "toolchain_allow":
187 testcase.toolchain_allow = tc_value
188 if tc_attribute == "platform_allow":
189 testcase.platform_allow = tc_value
Aastha Grovercf72fe82020-06-01 16:08:20 -0700190 if tc_attribute == "toolchain_exclude":
191 testcase.toolchain_exclude = tc_value
192 if tc_attribute == "platform_exclude":
193 testcase.platform_exclude = tc_value
194 if tc_attribute == "arch_exclude":
195 testcase.arch_exclude = tc_value
Anas Nashifdca317c2020-08-26 11:28:25 -0400196 if tc_attribute == "arch_allow":
197 testcase.arch_allow = tc_value
Aastha Grovercf72fe82020-06-01 16:08:20 -0700198 if tc_attribute == "skip":
199 testcase.skip = tc_value
200 if tc_attribute == "tags":
201 testcase.tags = tc_value
202 if tc_attribute == "min_flash":
203 testcase.min_flash = tc_value
204 if tc_attribute == "min_ram":
205 testcase.min_ram = tc_value
206
207 if tc_attribute == "build_on_all":
208 for _, testcase in class_testsuite.testcases.items():
209 testcase.build_on_all = tc_value
210 discards = class_testsuite.apply_filters(exclude_platform=['demo_board_1'])
211 elif plat_attribute == "supported_toolchains":
212 discards = class_testsuite.apply_filters(force_toolchain=False,
213 exclude_platform=['demo_board_1'],
214 platform=['demo_board_2'])
215 elif tc_attribute is None and plat_attribute is None:
216 discards = class_testsuite.apply_filters()
217 else:
218 discards = class_testsuite.apply_filters(exclude_platform=['demo_board_1'],
219 platform=['demo_board_2'])
Anas Nashifa44268f2020-11-26 10:51:10 -0500220
221 for x in [expected_discards]:
222 assert x in discards.values()
Aastha Grovercf72fe82020-06-01 16:08:20 -0700223
224TESTDATA_PART2 = [
Anas Nashif994bd5b2020-07-29 08:24:24 -0400225 ("runnable", "True", "Not runnable on device"),
Aastha Grovercf72fe82020-06-01 16:08:20 -0700226 ("exclude_tag", ['test_a'], "Command line testcase exclude filter"),
Anas Nashif9318e6c2020-12-07 12:29:36 -0500227 ("run_individual_tests", ['scripts/tests/twister/test_data/testcases/tests/test_a/test_a.check_1'], "Testcase name filter"),
Aastha Grovercf72fe82020-06-01 16:08:20 -0700228 ("arch", ['arm_test'], "Command line testcase arch filter"),
229 ("tag", ['test_d'], "Command line testcase tag filter")
230 ]
231
232
233@pytest.mark.parametrize("extra_filter, extra_filter_value, expected_discards", TESTDATA_PART2)
234def test_apply_filters_part2(class_testsuite, all_testcases_dict,
235 platforms_list, extra_filter, extra_filter_value, expected_discards):
Anas Nashif45943702020-12-11 17:55:15 -0500236 """ Testing apply_filters function of TestSuite class in Twister
Aastha Grovercf72fe82020-06-01 16:08:20 -0700237 Part 2 : Response of apply_filters function (discard dictionary) have
Aastha Grover8213a152020-06-16 12:15:47 -0700238 appropriate values according to the filters
Aastha Grovercf72fe82020-06-01 16:08:20 -0700239 """
Anas Nashif994bd5b2020-07-29 08:24:24 -0400240
Aastha Grovercf72fe82020-06-01 16:08:20 -0700241 class_testsuite.platforms = platforms_list
242 class_testsuite.testcases = all_testcases_dict
Anas Nashif994bd5b2020-07-29 08:24:24 -0400243 kwargs = {
244 extra_filter : extra_filter_value,
245 "exclude_platform" : [
246 'demo_board_1'
247 ],
248 "platform" : [
249 'demo_board_2'
250 ]
251 }
Aastha Grovercf72fe82020-06-01 16:08:20 -0700252 discards = class_testsuite.apply_filters(**kwargs)
Anas Nashif994bd5b2020-07-29 08:24:24 -0400253 assert discards
254 for d in discards.values():
255 assert d == expected_discards
Aastha Grovercf72fe82020-06-01 16:08:20 -0700256
257
258TESTDATA_PART3 = [
259 (20, 20, -1, 0),
260 (-2, -1, 10, 20),
261 (0, 0, 0, 0)
262 ]
263
264@pytest.mark.parametrize("tc_min_flash, plat_flash, tc_min_ram, plat_ram",
265 TESTDATA_PART3)
266def test_apply_filters_part3(class_testsuite, all_testcases_dict, platforms_list,
267 tc_min_flash, plat_flash, tc_min_ram, plat_ram):
Anas Nashif45943702020-12-11 17:55:15 -0500268 """ Testing apply_filters function of TestSuite class in Twister
Aastha Grovercf72fe82020-06-01 16:08:20 -0700269 Part 3 : Testing edge cases for ram and flash values of platforms & testcases
270 """
271 class_testsuite.platforms = platforms_list
272 class_testsuite.testcases = all_testcases_dict
273
274 for plat in class_testsuite.platforms:
275 plat.flash = plat_flash
276 plat.ram = plat_ram
277 for _, testcase in class_testsuite.testcases.items():
278 testcase.min_ram = tc_min_ram
279 testcase.min_flash = tc_min_flash
280 discards = class_testsuite.apply_filters(exclude_platform=['demo_board_1'],
281 platform=['demo_board_2'])
282 assert not discards
Aastha Grover8213a152020-06-16 12:15:47 -0700283
284def test_add_instances(test_data, class_testsuite, all_testcases_dict, platforms_list):
Anas Nashif45943702020-12-11 17:55:15 -0500285 """ Testing add_instances() function of TestSuite class in Twister
Aastha Grover8213a152020-06-16 12:15:47 -0700286 Test 1: instances dictionary keys have expected values (Platform Name + Testcase Name)
287 Test 2: Values of 'instances' dictionary in Testsuite class are an
288 instance of 'TestInstance' class
289 Test 3: Values of 'instances' dictionary have expected values.
290 """
291 class_testsuite.outdir = test_data
292 class_testsuite.platforms = platforms_list
293 platform = class_testsuite.get_platform("demo_board_2")
294 instance_list = []
295 for _, testcase in all_testcases_dict.items():
296 instance = TestInstance(testcase, platform, class_testsuite.outdir)
297 instance_list.append(instance)
298 class_testsuite.add_instances(instance_list)
299 assert list(class_testsuite.instances.keys()) == \
300 [platform.name + '/' + s for s in list(all_testcases_dict.keys())]
301 assert all(isinstance(n, TestInstance) for n in list(class_testsuite.instances.values()))
302 assert list(class_testsuite.instances.values()) == instance_list