Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
test/run_test.py@0:01f31e923fe2, 2020-04-07 (annotated)
- Committer:
- Pawel Zarembski
- Date:
- Tue Apr 07 12:55:42 2020 +0200
- Revision:
- 0:01f31e923fe2
hani: DAPLink with reset workaround
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pawel Zarembski |
0:01f31e923fe2 | 1 | # |
Pawel Zarembski |
0:01f31e923fe2 | 2 | # DAPLink Interface Firmware |
Pawel Zarembski |
0:01f31e923fe2 | 3 | # Copyright (c) 2009-2016, ARM Limited, All Rights Reserved |
Pawel Zarembski |
0:01f31e923fe2 | 4 | # SPDX-License-Identifier: Apache-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 5 | # |
Pawel Zarembski |
0:01f31e923fe2 | 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
Pawel Zarembski |
0:01f31e923fe2 | 7 | # not use this file except in compliance with the License. |
Pawel Zarembski |
0:01f31e923fe2 | 8 | # You may obtain a copy of the License at |
Pawel Zarembski |
0:01f31e923fe2 | 9 | # |
Pawel Zarembski |
0:01f31e923fe2 | 10 | # http://www.apache.org/licenses/LICENSE-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 11 | # |
Pawel Zarembski |
0:01f31e923fe2 | 12 | # Unless required by applicable law or agreed to in writing, software |
Pawel Zarembski |
0:01f31e923fe2 | 13 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
Pawel Zarembski |
0:01f31e923fe2 | 14 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Pawel Zarembski |
0:01f31e923fe2 | 15 | # See the License for the specific language governing permissions and |
Pawel Zarembski |
0:01f31e923fe2 | 16 | # limitations under the License. |
Pawel Zarembski |
0:01f31e923fe2 | 17 | # |
Pawel Zarembski |
0:01f31e923fe2 | 18 | |
Pawel Zarembski |
0:01f31e923fe2 | 19 | """ |
Pawel Zarembski |
0:01f31e923fe2 | 20 | DAPLink validation and testing tool |
Pawel Zarembski |
0:01f31e923fe2 | 21 | |
Pawel Zarembski |
0:01f31e923fe2 | 22 | optional arguments: |
Pawel Zarembski |
0:01f31e923fe2 | 23 | -h, --help show this help message and exit |
Pawel Zarembski |
0:01f31e923fe2 | 24 | --targetdir TARGETDIR |
Pawel Zarembski |
0:01f31e923fe2 | 25 | Directory with pre-built target test images. |
Pawel Zarembski |
0:01f31e923fe2 | 26 | --user USER MBED username (required for compile-api) |
Pawel Zarembski |
0:01f31e923fe2 | 27 | --password PASSWORD MBED password (required for compile-api) |
Pawel Zarembski |
0:01f31e923fe2 | 28 | --firmwaredir FIRMWAREDIR |
Pawel Zarembski |
0:01f31e923fe2 | 29 | Directory with firmware images to test |
Pawel Zarembski |
0:01f31e923fe2 | 30 | --firmware {k20dx_k64f_if,lpc11u35_sscity_if,...} (run script with --help to see full list) |
Pawel Zarembski |
0:01f31e923fe2 | 31 | Firmware to test |
Pawel Zarembski |
0:01f31e923fe2 | 32 | --project-tool TOOL choices=['uvision', 'mbedcli'],'Tool used to compile the project', |
Pawel Zarembski |
0:01f31e923fe2 | 33 | default='uvision' |
Pawel Zarembski |
0:01f31e923fe2 | 34 | --logdir LOGDIR Directory to log test results to |
Pawel Zarembski |
0:01f31e923fe2 | 35 | --noloadif Skip load step for interface. |
Pawel Zarembski |
0:01f31e923fe2 | 36 | --notestendpt Dont test the interface USB endpoints. |
Pawel Zarembski |
0:01f31e923fe2 | 37 | --loadbl Load bootloader before test. |
Pawel Zarembski |
0:01f31e923fe2 | 38 | --testdl Run DAPLink specific tests. The DAPLink test tests |
Pawel Zarembski |
0:01f31e923fe2 | 39 | bootloader updates so use with caution |
Pawel Zarembski |
0:01f31e923fe2 | 40 | --testfirst If multiple boards of the same type are found only |
Pawel Zarembski |
0:01f31e923fe2 | 41 | test the first one. |
Pawel Zarembski |
0:01f31e923fe2 | 42 | --verbose {Minimal,Normal,Verbose,All} |
Pawel Zarembski |
0:01f31e923fe2 | 43 | Verbose output |
Pawel Zarembski |
0:01f31e923fe2 | 44 | --dryrun Print info on configurations but dont actually run |
Pawel Zarembski |
0:01f31e923fe2 | 45 | tests. |
Pawel Zarembski |
0:01f31e923fe2 | 46 | --force Try to run tests even if there are problems. Delete logs from previous run. |
Pawel Zarembski |
0:01f31e923fe2 | 47 | Example usages |
Pawel Zarembski |
0:01f31e923fe2 | 48 | ------------------------ |
Pawel Zarembski |
0:01f31e923fe2 | 49 | |
Pawel Zarembski |
0:01f31e923fe2 | 50 | Test all built projects in the repository: |
Pawel Zarembski |
0:01f31e923fe2 | 51 | test_all.py --user <username> --password <password> |
Pawel Zarembski |
0:01f31e923fe2 | 52 | |
Pawel Zarembski |
0:01f31e923fe2 | 53 | Test everything on a single project in the repository: |
Pawel Zarembski |
0:01f31e923fe2 | 54 | test_all.py --project <project> --testfirst --user <username> |
Pawel Zarembski |
0:01f31e923fe2 | 55 | --password <password> |
Pawel Zarembski |
0:01f31e923fe2 | 56 | |
Pawel Zarembski |
0:01f31e923fe2 | 57 | Verify that the USB endpoints are working correctly on |
Pawel Zarembski |
0:01f31e923fe2 | 58 | an existing board with firmware already loaded: |
Pawel Zarembski |
0:01f31e923fe2 | 59 | test_all.py --noloadif --user <username> --password <password> |
Pawel Zarembski |
0:01f31e923fe2 | 60 | """ |
Pawel Zarembski |
0:01f31e923fe2 | 61 | from __future__ import absolute_import |
Pawel Zarembski |
0:01f31e923fe2 | 62 | from __future__ import print_function |
Pawel Zarembski |
0:01f31e923fe2 | 63 | |
Pawel Zarembski |
0:01f31e923fe2 | 64 | import os |
Pawel Zarembski |
0:01f31e923fe2 | 65 | import shutil |
Pawel Zarembski |
0:01f31e923fe2 | 66 | import argparse |
Pawel Zarembski |
0:01f31e923fe2 | 67 | import subprocess |
Pawel Zarembski |
0:01f31e923fe2 | 68 | from enum import Enum |
Pawel Zarembski |
0:01f31e923fe2 | 69 | from hid_test import test_hid |
Pawel Zarembski |
0:01f31e923fe2 | 70 | from serial_test import test_serial |
Pawel Zarembski |
0:01f31e923fe2 | 71 | from msd_test import test_mass_storage |
Pawel Zarembski |
0:01f31e923fe2 | 72 | from usb_test import test_usb |
Pawel Zarembski |
0:01f31e923fe2 | 73 | from daplink_board import get_all_attached_daplink_boards |
Pawel Zarembski |
0:01f31e923fe2 | 74 | from project_generator.generate import Generator |
Pawel Zarembski |
0:01f31e923fe2 | 75 | from test_info import TestInfo |
Pawel Zarembski |
0:01f31e923fe2 | 76 | from daplink_firmware import load_bundle_from_project, load_bundle_from_release |
Pawel Zarembski |
0:01f31e923fe2 | 77 | from firmware import Firmware |
Pawel Zarembski |
0:01f31e923fe2 | 78 | from target import load_target_bundle, build_target_bundle |
Pawel Zarembski |
0:01f31e923fe2 | 79 | from test_daplink import daplink_test |
Pawel Zarembski |
0:01f31e923fe2 | 80 | import info |
Pawel Zarembski |
0:01f31e923fe2 | 81 | |
Pawel Zarembski |
0:01f31e923fe2 | 82 | DEFAULT_TEST_DIR = './test_results' |
Pawel Zarembski |
0:01f31e923fe2 | 83 | |
Pawel Zarembski |
0:01f31e923fe2 | 84 | VERB_MINIMAL = 'Minimal' # Just top level errors |
Pawel Zarembski |
0:01f31e923fe2 | 85 | VERB_NORMAL = 'Normal' # Top level errors and warnings |
Pawel Zarembski |
0:01f31e923fe2 | 86 | VERB_VERBOSE = 'Verbose' # All errors and warnings |
Pawel Zarembski |
0:01f31e923fe2 | 87 | VERB_ALL = 'All' # All errors |
Pawel Zarembski |
0:01f31e923fe2 | 88 | VERB_LEVELS = [VERB_MINIMAL, VERB_NORMAL, VERB_VERBOSE, VERB_ALL] |
Pawel Zarembski |
0:01f31e923fe2 | 89 | |
Pawel Zarembski |
0:01f31e923fe2 | 90 | |
Pawel Zarembski |
0:01f31e923fe2 | 91 | def test_endpoints(workspace, parent_test): |
Pawel Zarembski |
0:01f31e923fe2 | 92 | """Run tests to validate DAPLINK fimrware""" |
Pawel Zarembski |
0:01f31e923fe2 | 93 | test_info = parent_test.create_subtest('test_endpoints') |
Pawel Zarembski |
0:01f31e923fe2 | 94 | test_hid(workspace, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 95 | test_serial(workspace, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 96 | test_mass_storage(workspace, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 97 | test_usb(workspace, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 98 | |
Pawel Zarembski |
0:01f31e923fe2 | 99 | |
Pawel Zarembski |
0:01f31e923fe2 | 100 | class TestConfiguration(object): |
Pawel Zarembski |
0:01f31e923fe2 | 101 | """Wrap all the resources needed to run a test""" |
Pawel Zarembski |
0:01f31e923fe2 | 102 | def __init__(self, name): |
Pawel Zarembski |
0:01f31e923fe2 | 103 | self.name = name |
Pawel Zarembski |
0:01f31e923fe2 | 104 | self.board = None |
Pawel Zarembski |
0:01f31e923fe2 | 105 | self.target = None |
Pawel Zarembski |
0:01f31e923fe2 | 106 | self.if_firmware = None |
Pawel Zarembski |
0:01f31e923fe2 | 107 | self.bl_firmware = None |
Pawel Zarembski |
0:01f31e923fe2 | 108 | |
Pawel Zarembski |
0:01f31e923fe2 | 109 | def __str__(self): |
Pawel Zarembski |
0:01f31e923fe2 | 110 | name_board = '<None>' |
Pawel Zarembski |
0:01f31e923fe2 | 111 | name_target = '<None>' |
Pawel Zarembski |
0:01f31e923fe2 | 112 | name_if_firmware = '<None>' |
Pawel Zarembski |
0:01f31e923fe2 | 113 | name_bl_firmware = '<None>' |
Pawel Zarembski |
0:01f31e923fe2 | 114 | if self.board is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 115 | name_board = self.board.name |
Pawel Zarembski |
0:01f31e923fe2 | 116 | if self.target is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 117 | name_target = self.target.name |
Pawel Zarembski |
0:01f31e923fe2 | 118 | if self.if_firmware is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 119 | name_if_firmware = self.if_firmware.name |
Pawel Zarembski |
0:01f31e923fe2 | 120 | if self.bl_firmware is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 121 | name_bl_firmware = self.bl_firmware.name |
Pawel Zarembski |
0:01f31e923fe2 | 122 | return "APP=%s BL=%s Board=%s Target=%s" % (name_if_firmware, |
Pawel Zarembski |
0:01f31e923fe2 | 123 | name_bl_firmware, |
Pawel Zarembski |
0:01f31e923fe2 | 124 | name_board, name_target) |
Pawel Zarembski |
0:01f31e923fe2 | 125 | |
Pawel Zarembski |
0:01f31e923fe2 | 126 | |
Pawel Zarembski |
0:01f31e923fe2 | 127 | class TestManager(object): |
Pawel Zarembski |
0:01f31e923fe2 | 128 | """Handle tests configuration running and results""" |
Pawel Zarembski |
0:01f31e923fe2 | 129 | |
Pawel Zarembski |
0:01f31e923fe2 | 130 | class _STATE(Enum): |
Pawel Zarembski |
0:01f31e923fe2 | 131 | INIT = 0 |
Pawel Zarembski |
0:01f31e923fe2 | 132 | CONFIGURED = 1 |
Pawel Zarembski |
0:01f31e923fe2 | 133 | COMPLETE = 2 |
Pawel Zarembski |
0:01f31e923fe2 | 134 | |
Pawel Zarembski |
0:01f31e923fe2 | 135 | def __init__(self): |
Pawel Zarembski |
0:01f31e923fe2 | 136 | # By default test all configurations and boards |
Pawel Zarembski |
0:01f31e923fe2 | 137 | self._target_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 138 | self._board_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 139 | self._firmware_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 140 | self._only_test_first = False |
Pawel Zarembski |
0:01f31e923fe2 | 141 | self._load_if = True |
Pawel Zarembski |
0:01f31e923fe2 | 142 | self._load_bl = True |
Pawel Zarembski |
0:01f31e923fe2 | 143 | self._test_daplink = True |
Pawel Zarembski |
0:01f31e923fe2 | 144 | self._test_ep = True |
Pawel Zarembski |
0:01f31e923fe2 | 145 | |
Pawel Zarembski |
0:01f31e923fe2 | 146 | # Internal state |
Pawel Zarembski |
0:01f31e923fe2 | 147 | self._state = self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 148 | self._test_configuration_list = None |
Pawel Zarembski |
0:01f31e923fe2 | 149 | self._all_tests_pass = None |
Pawel Zarembski |
0:01f31e923fe2 | 150 | self._firmware_filter = None |
Pawel Zarembski |
0:01f31e923fe2 | 151 | self._untested_firmware = None |
Pawel Zarembski |
0:01f31e923fe2 | 152 | |
Pawel Zarembski |
0:01f31e923fe2 | 153 | @property |
Pawel Zarembski |
0:01f31e923fe2 | 154 | def all_tests_pass(self): |
Pawel Zarembski |
0:01f31e923fe2 | 155 | assert self._all_tests_pass is not None, 'Must call run_tests first' |
Pawel Zarembski |
0:01f31e923fe2 | 156 | return self._all_tests_pass |
Pawel Zarembski |
0:01f31e923fe2 | 157 | |
Pawel Zarembski |
0:01f31e923fe2 | 158 | def set_test_first_board_only(self, first): |
Pawel Zarembski |
0:01f31e923fe2 | 159 | """Only test one board of each type""" |
Pawel Zarembski |
0:01f31e923fe2 | 160 | assert isinstance(first, bool) |
Pawel Zarembski |
0:01f31e923fe2 | 161 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 162 | self._only_test_first = first |
Pawel Zarembski |
0:01f31e923fe2 | 163 | |
Pawel Zarembski |
0:01f31e923fe2 | 164 | def set_load_if(self, load): |
Pawel Zarembski |
0:01f31e923fe2 | 165 | """Load new interface firmware before testing""" |
Pawel Zarembski |
0:01f31e923fe2 | 166 | assert isinstance(load, bool) |
Pawel Zarembski |
0:01f31e923fe2 | 167 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 168 | self._load_if = load |
Pawel Zarembski |
0:01f31e923fe2 | 169 | |
Pawel Zarembski |
0:01f31e923fe2 | 170 | def set_load_bl(self, load): |
Pawel Zarembski |
0:01f31e923fe2 | 171 | """Load new bootloader firmware before testing""" |
Pawel Zarembski |
0:01f31e923fe2 | 172 | assert isinstance(load, bool) |
Pawel Zarembski |
0:01f31e923fe2 | 173 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 174 | self._load_bl = load |
Pawel Zarembski |
0:01f31e923fe2 | 175 | |
Pawel Zarembski |
0:01f31e923fe2 | 176 | def set_test_daplink(self, run_test): |
Pawel Zarembski |
0:01f31e923fe2 | 177 | """Run DAPLink specific tests""" |
Pawel Zarembski |
0:01f31e923fe2 | 178 | assert isinstance(run_test, bool) |
Pawel Zarembski |
0:01f31e923fe2 | 179 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 180 | self._test_daplink = run_test |
Pawel Zarembski |
0:01f31e923fe2 | 181 | |
Pawel Zarembski |
0:01f31e923fe2 | 182 | def set_test_ep(self, run_test): |
Pawel Zarembski |
0:01f31e923fe2 | 183 | """Test each endpoint - MSD, CDC, HID""" |
Pawel Zarembski |
0:01f31e923fe2 | 184 | assert isinstance(run_test, bool) |
Pawel Zarembski |
0:01f31e923fe2 | 185 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 186 | self._test_ep = run_test |
Pawel Zarembski |
0:01f31e923fe2 | 187 | |
Pawel Zarembski |
0:01f31e923fe2 | 188 | def add_firmware(self, firmware_list): |
Pawel Zarembski |
0:01f31e923fe2 | 189 | """Add firmware to be tested""" |
Pawel Zarembski |
0:01f31e923fe2 | 190 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 191 | self._firmware_list.extend(firmware_list) |
Pawel Zarembski |
0:01f31e923fe2 | 192 | |
Pawel Zarembski |
0:01f31e923fe2 | 193 | def add_boards(self, board_list): |
Pawel Zarembski |
0:01f31e923fe2 | 194 | """Add boards to be used for testing""" |
Pawel Zarembski |
0:01f31e923fe2 | 195 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 196 | self._board_list.extend(board_list) |
Pawel Zarembski |
0:01f31e923fe2 | 197 | |
Pawel Zarembski |
0:01f31e923fe2 | 198 | def add_targets(self, target_list): |
Pawel Zarembski |
0:01f31e923fe2 | 199 | """Add targets to be used for testing""" |
Pawel Zarembski |
0:01f31e923fe2 | 200 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 201 | self._target_list.extend(target_list) |
Pawel Zarembski |
0:01f31e923fe2 | 202 | |
Pawel Zarembski |
0:01f31e923fe2 | 203 | def set_firmware_filter(self, name_list): |
Pawel Zarembski |
0:01f31e923fe2 | 204 | """Test only the project names passed given""" |
Pawel Zarembski |
0:01f31e923fe2 | 205 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 206 | assert self._firmware_filter is None |
Pawel Zarembski |
0:01f31e923fe2 | 207 | self._firmware_filter = set(name_list) |
Pawel Zarembski |
0:01f31e923fe2 | 208 | |
Pawel Zarembski |
0:01f31e923fe2 | 209 | def run_tests(self): |
Pawel Zarembski |
0:01f31e923fe2 | 210 | """Run all configurations""" |
Pawel Zarembski |
0:01f31e923fe2 | 211 | # Tests can only be run once per TestManager instance |
Pawel Zarembski |
0:01f31e923fe2 | 212 | assert self._state is self._STATE.CONFIGURED |
Pawel Zarembski |
0:01f31e923fe2 | 213 | self._state = self._STATE.COMPLETE |
Pawel Zarembski |
0:01f31e923fe2 | 214 | |
Pawel Zarembski |
0:01f31e923fe2 | 215 | all_tests_pass = True |
Pawel Zarembski |
0:01f31e923fe2 | 216 | for test_configuration in self._test_configuration_list: |
Pawel Zarembski |
0:01f31e923fe2 | 217 | board = test_configuration.board |
Pawel Zarembski |
0:01f31e923fe2 | 218 | test_info = TestInfo(test_configuration.name) |
Pawel Zarembski |
0:01f31e923fe2 | 219 | test_configuration.test_info = test_info |
Pawel Zarembski |
0:01f31e923fe2 | 220 | |
Pawel Zarembski |
0:01f31e923fe2 | 221 | test_info.info("Board: %s" % test_configuration.board) |
Pawel Zarembski |
0:01f31e923fe2 | 222 | test_info.info("Application: %s" % |
Pawel Zarembski |
0:01f31e923fe2 | 223 | test_configuration.if_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 224 | test_info.info("Bootloader: %s" % |
Pawel Zarembski |
0:01f31e923fe2 | 225 | test_configuration.bl_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 226 | test_info.info("Target: %s" % test_configuration.target) |
Pawel Zarembski |
0:01f31e923fe2 | 227 | |
Pawel Zarembski |
0:01f31e923fe2 | 228 | |
Pawel Zarembski |
0:01f31e923fe2 | 229 | if self._load_if: |
Pawel Zarembski |
0:01f31e923fe2 | 230 | if_path = test_configuration.if_firmware.hex_path |
Pawel Zarembski |
0:01f31e923fe2 | 231 | board.load_interface(if_path, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 232 | |
Pawel Zarembski |
0:01f31e923fe2 | 233 | valid_bl = test_configuration.bl_firmware is not None |
Pawel Zarembski |
0:01f31e923fe2 | 234 | if self._load_bl and valid_bl: |
Pawel Zarembski |
0:01f31e923fe2 | 235 | bl_path = test_configuration.bl_firmware.hex_path |
Pawel Zarembski |
0:01f31e923fe2 | 236 | board.load_bootloader(bl_path, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 237 | |
Pawel Zarembski |
0:01f31e923fe2 | 238 | board.set_check_fs_on_remount(True) |
Pawel Zarembski |
0:01f31e923fe2 | 239 | |
Pawel Zarembski |
0:01f31e923fe2 | 240 | if self._test_daplink: |
Pawel Zarembski |
0:01f31e923fe2 | 241 | daplink_test(test_configuration, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 242 | |
Pawel Zarembski |
0:01f31e923fe2 | 243 | if self._test_ep: |
Pawel Zarembski |
0:01f31e923fe2 | 244 | test_endpoints(test_configuration, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 245 | |
Pawel Zarembski |
0:01f31e923fe2 | 246 | if test_info.get_failed(): |
Pawel Zarembski |
0:01f31e923fe2 | 247 | all_tests_pass = False |
Pawel Zarembski |
0:01f31e923fe2 | 248 | |
Pawel Zarembski |
0:01f31e923fe2 | 249 | self._all_tests_pass = all_tests_pass |
Pawel Zarembski |
0:01f31e923fe2 | 250 | |
Pawel Zarembski |
0:01f31e923fe2 | 251 | def print_results(self, info_level): |
Pawel Zarembski |
0:01f31e923fe2 | 252 | assert self._state is self._STATE.COMPLETE |
Pawel Zarembski |
0:01f31e923fe2 | 253 | # Print info for boards tested |
Pawel Zarembski |
0:01f31e923fe2 | 254 | for test_configuration in self._test_configuration_list: |
Pawel Zarembski |
0:01f31e923fe2 | 255 | print('') |
Pawel Zarembski |
0:01f31e923fe2 | 256 | test_info = test_configuration.test_info |
Pawel Zarembski |
0:01f31e923fe2 | 257 | if info_level == VERB_MINIMAL: |
Pawel Zarembski |
0:01f31e923fe2 | 258 | test_info.print_msg(TestInfo.FAILURE, 0) |
Pawel Zarembski |
0:01f31e923fe2 | 259 | elif info_level == VERB_NORMAL: |
Pawel Zarembski |
0:01f31e923fe2 | 260 | test_info.print_msg(TestInfo.WARNING, None) |
Pawel Zarembski |
0:01f31e923fe2 | 261 | elif info_level == VERB_VERBOSE: |
Pawel Zarembski |
0:01f31e923fe2 | 262 | test_info.print_msg(TestInfo.WARNING, None) |
Pawel Zarembski |
0:01f31e923fe2 | 263 | elif info_level == VERB_ALL: |
Pawel Zarembski |
0:01f31e923fe2 | 264 | test_info.print_msg(TestInfo.INFO, None) |
Pawel Zarembski |
0:01f31e923fe2 | 265 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 266 | # This should never happen |
Pawel Zarembski |
0:01f31e923fe2 | 267 | assert False |
Pawel Zarembski |
0:01f31e923fe2 | 268 | |
Pawel Zarembski |
0:01f31e923fe2 | 269 | def write_test_results(self, directory, git_sha=None, local_changes=None, |
Pawel Zarembski |
0:01f31e923fe2 | 270 | info_level=TestInfo.INFO): |
Pawel Zarembski |
0:01f31e923fe2 | 271 | assert self._state is self._STATE.COMPLETE |
Pawel Zarembski |
0:01f31e923fe2 | 272 | |
Pawel Zarembski |
0:01f31e923fe2 | 273 | assert not os.path.exists(directory) |
Pawel Zarembski |
0:01f31e923fe2 | 274 | os.mkdir(directory) |
Pawel Zarembski |
0:01f31e923fe2 | 275 | |
Pawel Zarembski |
0:01f31e923fe2 | 276 | # Write out version of tools used for test |
Pawel Zarembski |
0:01f31e923fe2 | 277 | tools_file = directory + os.sep + 'requirements.txt' |
Pawel Zarembski |
0:01f31e923fe2 | 278 | with open(tools_file, "w") as file_handle: |
Pawel Zarembski |
0:01f31e923fe2 | 279 | command = ['pip', 'freeze'] |
Pawel Zarembski |
0:01f31e923fe2 | 280 | subprocess.check_call(command, stdin=subprocess.PIPE, |
Pawel Zarembski |
0:01f31e923fe2 | 281 | stdout=file_handle, |
Pawel Zarembski |
0:01f31e923fe2 | 282 | stderr=subprocess.STDOUT) |
Pawel Zarembski |
0:01f31e923fe2 | 283 | |
Pawel Zarembski |
0:01f31e923fe2 | 284 | # Write out each test result |
Pawel Zarembski |
0:01f31e923fe2 | 285 | for test_configuration in self._test_configuration_list: |
Pawel Zarembski |
0:01f31e923fe2 | 286 | test_info = test_configuration.test_info |
Pawel Zarembski |
0:01f31e923fe2 | 287 | file_path = directory + os.sep + test_info.name + '.txt' |
Pawel Zarembski |
0:01f31e923fe2 | 288 | with open(file_path, 'w') as file_handle: |
Pawel Zarembski |
0:01f31e923fe2 | 289 | file_handle.write("Test configuration: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 290 | test_configuration) |
Pawel Zarembski |
0:01f31e923fe2 | 291 | file_handle.write("Board: %s\n" % test_configuration.board) |
Pawel Zarembski |
0:01f31e923fe2 | 292 | file_handle.write("Application: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 293 | test_configuration.if_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 294 | file_handle.write("Bootloader: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 295 | test_configuration.bl_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 296 | file_handle.write("Target: %s\n" % test_configuration.target) |
Pawel Zarembski |
0:01f31e923fe2 | 297 | file_handle.write("\n") |
Pawel Zarembski |
0:01f31e923fe2 | 298 | test_info.print_msg(info_level, None, log_file=file_handle) |
Pawel Zarembski |
0:01f31e923fe2 | 299 | |
Pawel Zarembski |
0:01f31e923fe2 | 300 | # Write out summary |
Pawel Zarembski |
0:01f31e923fe2 | 301 | summary_file = directory + os.sep + 'summary.txt' |
Pawel Zarembski |
0:01f31e923fe2 | 302 | with open(summary_file, "w") as file_handle: |
Pawel Zarembski |
0:01f31e923fe2 | 303 | # Overall result |
Pawel Zarembski |
0:01f31e923fe2 | 304 | if self.all_tests_pass: |
Pawel Zarembski |
0:01f31e923fe2 | 305 | file_handle.write("All tests pass\n\n") |
Pawel Zarembski |
0:01f31e923fe2 | 306 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 307 | file_handle.write("One or more tests have failed\n\n") |
Pawel Zarembski |
0:01f31e923fe2 | 308 | |
Pawel Zarembski |
0:01f31e923fe2 | 309 | if git_sha is not None and local_changes is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 310 | file_handle.write("Git info for test:\n") |
Pawel Zarembski |
0:01f31e923fe2 | 311 | file_handle.write(" Git SHA: %s\n" % git_sha) |
Pawel Zarembski |
0:01f31e923fe2 | 312 | file_handle.write(" Local changes: %s\n" % local_changes) |
Pawel Zarembski |
0:01f31e923fe2 | 313 | file_handle.write("\n") |
Pawel Zarembski |
0:01f31e923fe2 | 314 | |
Pawel Zarembski |
0:01f31e923fe2 | 315 | # Results for each test |
Pawel Zarembski |
0:01f31e923fe2 | 316 | file_handle.write("Test settings:\n") |
Pawel Zarembski |
0:01f31e923fe2 | 317 | file_handle.write(" Load application before test: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 318 | self._load_if) |
Pawel Zarembski |
0:01f31e923fe2 | 319 | file_handle.write(" Load bootloader before test: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 320 | self._load_bl) |
Pawel Zarembski |
0:01f31e923fe2 | 321 | file_handle.write(" Run DAPLink specific tests: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 322 | self._test_daplink) |
Pawel Zarembski |
0:01f31e923fe2 | 323 | file_handle.write(" Run endpoint tests: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 324 | self._test_ep) |
Pawel Zarembski |
0:01f31e923fe2 | 325 | file_handle.write("\n") |
Pawel Zarembski |
0:01f31e923fe2 | 326 | |
Pawel Zarembski |
0:01f31e923fe2 | 327 | # Results for each test |
Pawel Zarembski |
0:01f31e923fe2 | 328 | file_handle.write("Tested configurations:\n") |
Pawel Zarembski |
0:01f31e923fe2 | 329 | for test_configuration in self._test_configuration_list: |
Pawel Zarembski |
0:01f31e923fe2 | 330 | test_info = test_configuration.test_info |
Pawel Zarembski |
0:01f31e923fe2 | 331 | test_passed = test_info.get_failed() == 0 |
Pawel Zarembski |
0:01f31e923fe2 | 332 | result_str = 'Pass' if test_passed else 'Fail' |
Pawel Zarembski |
0:01f31e923fe2 | 333 | file_handle.write(" %s: %s\n" % |
Pawel Zarembski |
0:01f31e923fe2 | 334 | (test_configuration, result_str)) |
Pawel Zarembski |
0:01f31e923fe2 | 335 | file_handle.write("\n") |
Pawel Zarembski |
0:01f31e923fe2 | 336 | |
Pawel Zarembski |
0:01f31e923fe2 | 337 | # Untested firmware |
Pawel Zarembski |
0:01f31e923fe2 | 338 | untested_list = self.get_untested_firmware() |
Pawel Zarembski |
0:01f31e923fe2 | 339 | if len(untested_list) == 0: |
Pawel Zarembski |
0:01f31e923fe2 | 340 | file_handle.write("All firmware in package tested\n") |
Pawel Zarembski |
0:01f31e923fe2 | 341 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 342 | file_handle.write("Untested firmware:\n") |
Pawel Zarembski |
0:01f31e923fe2 | 343 | for untested_fw in self.get_untested_firmware(): |
Pawel Zarembski |
0:01f31e923fe2 | 344 | file_handle.write(" %s\n" % untested_fw.name) |
Pawel Zarembski |
0:01f31e923fe2 | 345 | file_handle.write("\n") |
Pawel Zarembski |
0:01f31e923fe2 | 346 | |
Pawel Zarembski |
0:01f31e923fe2 | 347 | # Target test images |
Pawel Zarembski |
0:01f31e923fe2 | 348 | target_dir = directory + os.sep + 'target' |
Pawel Zarembski |
0:01f31e923fe2 | 349 | os.mkdir(target_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 350 | for target in self._target_list: |
Pawel Zarembski |
0:01f31e923fe2 | 351 | new_hex = target_dir + os.sep + os.path.basename(target.hex_path) |
Pawel Zarembski |
0:01f31e923fe2 | 352 | shutil.copy(target.hex_path, new_hex) |
Pawel Zarembski |
0:01f31e923fe2 | 353 | new_bin = target_dir + os.sep + os.path.basename(target.bin_path) |
Pawel Zarembski |
0:01f31e923fe2 | 354 | shutil.copy(target.bin_path, new_bin) |
Pawel Zarembski |
0:01f31e923fe2 | 355 | |
Pawel Zarembski |
0:01f31e923fe2 | 356 | def get_test_configurations(self): |
Pawel Zarembski |
0:01f31e923fe2 | 357 | assert self._state in (self._STATE.CONFIGURED, |
Pawel Zarembski |
0:01f31e923fe2 | 358 | self._STATE.COMPLETE) |
Pawel Zarembski |
0:01f31e923fe2 | 359 | return self._test_configuration_list |
Pawel Zarembski |
0:01f31e923fe2 | 360 | |
Pawel Zarembski |
0:01f31e923fe2 | 361 | def get_untested_firmware(self): |
Pawel Zarembski |
0:01f31e923fe2 | 362 | assert self._state in (self._STATE.CONFIGURED, |
Pawel Zarembski |
0:01f31e923fe2 | 363 | self._STATE.COMPLETE) |
Pawel Zarembski |
0:01f31e923fe2 | 364 | return self._untested_firmware |
Pawel Zarembski |
0:01f31e923fe2 | 365 | |
Pawel Zarembski |
0:01f31e923fe2 | 366 | def build_test_configurations(self, parent_test): |
Pawel Zarembski |
0:01f31e923fe2 | 367 | assert self._state is self._STATE.INIT |
Pawel Zarembski |
0:01f31e923fe2 | 368 | self._state = self._STATE.CONFIGURED |
Pawel Zarembski |
0:01f31e923fe2 | 369 | test_info = parent_test.create_subtest('Build test configuration') |
Pawel Zarembski |
0:01f31e923fe2 | 370 | |
Pawel Zarembski |
0:01f31e923fe2 | 371 | # Create table mapping each board id to a list of boards with that ID |
Pawel Zarembski |
0:01f31e923fe2 | 372 | board_id_to_board_list = {} |
Pawel Zarembski |
0:01f31e923fe2 | 373 | for board in self._board_list: |
Pawel Zarembski |
0:01f31e923fe2 | 374 | board_id = board.get_board_id() |
Pawel Zarembski |
0:01f31e923fe2 | 375 | if board_id not in board_id_to_board_list: |
Pawel Zarembski |
0:01f31e923fe2 | 376 | board_id_to_board_list[board_id] = [] |
Pawel Zarembski |
0:01f31e923fe2 | 377 | board_list = board_id_to_board_list[board_id] |
Pawel Zarembski |
0:01f31e923fe2 | 378 | if self._only_test_first and len(board_list) > 1: |
Pawel Zarembski |
0:01f31e923fe2 | 379 | # Ignore this board since we already have one |
Pawel Zarembski |
0:01f31e923fe2 | 380 | test_info.info('Ignoring extra boards of type 0x%x' % |
Pawel Zarembski |
0:01f31e923fe2 | 381 | board_id) |
Pawel Zarembski |
0:01f31e923fe2 | 382 | continue |
Pawel Zarembski |
0:01f31e923fe2 | 383 | board_list.append(board) |
Pawel Zarembski |
0:01f31e923fe2 | 384 | |
Pawel Zarembski |
0:01f31e923fe2 | 385 | # Create a list for bootloader firmware and interface firmware |
Pawel Zarembski |
0:01f31e923fe2 | 386 | bootloader_firmware_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 387 | filtered_interface_firmware_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 388 | for firmware in self._firmware_list: |
Pawel Zarembski |
0:01f31e923fe2 | 389 | if firmware.type == Firmware.TYPE.BOOTLOADER: |
Pawel Zarembski |
0:01f31e923fe2 | 390 | bootloader_firmware_list.append(firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 391 | elif firmware.type == Firmware.TYPE.INTERFACE: |
Pawel Zarembski |
0:01f31e923fe2 | 392 | name = firmware.name |
Pawel Zarembski |
0:01f31e923fe2 | 393 | if ((self._firmware_filter is None) or |
Pawel Zarembski |
0:01f31e923fe2 | 394 | (name in self._firmware_filter)): |
Pawel Zarembski |
0:01f31e923fe2 | 395 | filtered_interface_firmware_list.append(firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 396 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 397 | assert False, 'Unsupported firmware type "%s"' % firmware.type |
Pawel Zarembski |
0:01f31e923fe2 | 398 | |
Pawel Zarembski |
0:01f31e923fe2 | 399 | # Create a table mapping name to object with that name |
Pawel Zarembski |
0:01f31e923fe2 | 400 | TARGET_NAME_TO_TARGET = {target.name: target for target in |
Pawel Zarembski |
0:01f31e923fe2 | 401 | self._target_list} |
Pawel Zarembski |
0:01f31e923fe2 | 402 | FIRMWARE_NAME_TO_FIRMWARE = {firmware.name: firmware for firmware in |
Pawel Zarembski |
0:01f31e923fe2 | 403 | filtered_interface_firmware_list} |
Pawel Zarembski |
0:01f31e923fe2 | 404 | BL_NAME_TO_BL = {firmware.name: firmware for firmware in |
Pawel Zarembski |
0:01f31e923fe2 | 405 | bootloader_firmware_list} |
Pawel Zarembski |
0:01f31e923fe2 | 406 | |
Pawel Zarembski |
0:01f31e923fe2 | 407 | # Explicitly specified boards must be present |
Pawel Zarembski |
0:01f31e923fe2 | 408 | fw_name_set = set(fw.name for fw in filtered_interface_firmware_list) |
Pawel Zarembski |
0:01f31e923fe2 | 409 | if self._firmware_filter is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 410 | assert self._firmware_filter == fw_name_set |
Pawel Zarembski |
0:01f31e923fe2 | 411 | |
Pawel Zarembski |
0:01f31e923fe2 | 412 | # Create test configurations for each supported configuration |
Pawel Zarembski |
0:01f31e923fe2 | 413 | test_conf_list = [] |
Pawel Zarembski |
0:01f31e923fe2 | 414 | untested_firmware = set(filtered_interface_firmware_list) |
Pawel Zarembski |
0:01f31e923fe2 | 415 | for board_id, family_id, fw_name, bl_fw_name, target_name in info.SUPPORTED_CONFIGURATIONS: |
Pawel Zarembski |
0:01f31e923fe2 | 416 | target = None |
Pawel Zarembski |
0:01f31e923fe2 | 417 | if_firmware = None |
Pawel Zarembski |
0:01f31e923fe2 | 418 | bl_firmware = None |
Pawel Zarembski |
0:01f31e923fe2 | 419 | if target_name in TARGET_NAME_TO_TARGET: |
Pawel Zarembski |
0:01f31e923fe2 | 420 | target = TARGET_NAME_TO_TARGET[target_name] |
Pawel Zarembski |
0:01f31e923fe2 | 421 | if fw_name in FIRMWARE_NAME_TO_FIRMWARE: |
Pawel Zarembski |
0:01f31e923fe2 | 422 | if_firmware = FIRMWARE_NAME_TO_FIRMWARE[fw_name] |
Pawel Zarembski |
0:01f31e923fe2 | 423 | if bl_fw_name in BL_NAME_TO_BL: |
Pawel Zarembski |
0:01f31e923fe2 | 424 | bl_firmware = BL_NAME_TO_BL[bl_fw_name] |
Pawel Zarembski |
0:01f31e923fe2 | 425 | |
Pawel Zarembski |
0:01f31e923fe2 | 426 | target_required = self._test_ep |
Pawel Zarembski |
0:01f31e923fe2 | 427 | bl_required = self._load_bl or self._test_daplink |
Pawel Zarembski |
0:01f31e923fe2 | 428 | if if_firmware is None: |
Pawel Zarembski |
0:01f31e923fe2 | 429 | # Skip configuration |
Pawel Zarembski |
0:01f31e923fe2 | 430 | continue |
Pawel Zarembski |
0:01f31e923fe2 | 431 | if target_required and target is None: |
Pawel Zarembski |
0:01f31e923fe2 | 432 | # Skip configuration |
Pawel Zarembski |
0:01f31e923fe2 | 433 | test_info.info('No target to test firmware %s' % fw_name) |
Pawel Zarembski |
0:01f31e923fe2 | 434 | continue |
Pawel Zarembski |
0:01f31e923fe2 | 435 | if bl_required and bl_firmware is None: |
Pawel Zarembski |
0:01f31e923fe2 | 436 | # Skip configuration |
Pawel Zarembski |
0:01f31e923fe2 | 437 | test_info.info('No bootloader to test firmware %s' % fw_name) |
Pawel Zarembski |
0:01f31e923fe2 | 438 | continue |
Pawel Zarembski |
0:01f31e923fe2 | 439 | # Check if there is a board to test this firmware |
Pawel Zarembski |
0:01f31e923fe2 | 440 | # and if not skip it |
Pawel Zarembski |
0:01f31e923fe2 | 441 | if board_id not in board_id_to_board_list: |
Pawel Zarembski |
0:01f31e923fe2 | 442 | test_info.info('No board to test firmware %s' % fw_name) |
Pawel Zarembski |
0:01f31e923fe2 | 443 | continue |
Pawel Zarembski |
0:01f31e923fe2 | 444 | |
Pawel Zarembski |
0:01f31e923fe2 | 445 | # Create a test configuration for each board |
Pawel Zarembski |
0:01f31e923fe2 | 446 | board_list = board_id_to_board_list[board_id] |
Pawel Zarembski |
0:01f31e923fe2 | 447 | for board in board_list: |
Pawel Zarembski |
0:01f31e923fe2 | 448 | test_conf = TestConfiguration(if_firmware.name + ' ' + |
Pawel Zarembski |
0:01f31e923fe2 | 449 | board.name) |
Pawel Zarembski |
0:01f31e923fe2 | 450 | test_conf.if_firmware = if_firmware |
Pawel Zarembski |
0:01f31e923fe2 | 451 | test_conf.bl_firmware = bl_firmware |
Pawel Zarembski |
0:01f31e923fe2 | 452 | test_conf.board = board |
Pawel Zarembski |
0:01f31e923fe2 | 453 | test_conf.target = target |
Pawel Zarembski |
0:01f31e923fe2 | 454 | test_conf_list.append(test_conf) |
Pawel Zarembski |
0:01f31e923fe2 | 455 | # remove this from the untested list |
Pawel Zarembski |
0:01f31e923fe2 | 456 | if if_firmware in untested_firmware: |
Pawel Zarembski |
0:01f31e923fe2 | 457 | untested_firmware.remove(if_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 458 | assert bl_firmware not in untested_firmware |
Pawel Zarembski |
0:01f31e923fe2 | 459 | |
Pawel Zarembski |
0:01f31e923fe2 | 460 | self._untested_firmware = list(untested_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 461 | self._test_configuration_list = test_conf_list |
Pawel Zarembski |
0:01f31e923fe2 | 462 | |
Pawel Zarembski |
0:01f31e923fe2 | 463 | |
Pawel Zarembski |
0:01f31e923fe2 | 464 | def get_firmware_names(project_dir): |
Pawel Zarembski |
0:01f31e923fe2 | 465 | |
Pawel Zarembski |
0:01f31e923fe2 | 466 | # Save current directory |
Pawel Zarembski |
0:01f31e923fe2 | 467 | cur_dir = os.getcwd() |
Pawel Zarembski |
0:01f31e923fe2 | 468 | os.chdir(project_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 469 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 470 | all_names = set() |
Pawel Zarembski |
0:01f31e923fe2 | 471 | projects = list(Generator('projects.yaml').generate()) |
Pawel Zarembski |
0:01f31e923fe2 | 472 | for project in projects: |
Pawel Zarembski |
0:01f31e923fe2 | 473 | assert project.name not in all_names |
Pawel Zarembski |
0:01f31e923fe2 | 474 | all_names.add(project.name) |
Pawel Zarembski |
0:01f31e923fe2 | 475 | finally: |
Pawel Zarembski |
0:01f31e923fe2 | 476 | # Restore the current directory |
Pawel Zarembski |
0:01f31e923fe2 | 477 | os.chdir(cur_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 478 | return list(all_names) |
Pawel Zarembski |
0:01f31e923fe2 | 479 | |
Pawel Zarembski |
0:01f31e923fe2 | 480 | |
Pawel Zarembski |
0:01f31e923fe2 | 481 | def get_git_info(project_dir): |
Pawel Zarembski |
0:01f31e923fe2 | 482 | cur_dir = os.getcwd() |
Pawel Zarembski |
0:01f31e923fe2 | 483 | os.chdir(project_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 484 | |
Pawel Zarembski |
0:01f31e923fe2 | 485 | # Get the git SHA. |
Pawel Zarembski |
0:01f31e923fe2 | 486 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 487 | git_sha = subprocess.check_output(["git", "rev-parse", |
Pawel Zarembski |
0:01f31e923fe2 | 488 | "--verify", "HEAD"]) |
Pawel Zarembski |
0:01f31e923fe2 | 489 | git_sha = git_sha.strip() |
Pawel Zarembski |
0:01f31e923fe2 | 490 | except (subprocess.CalledProcessError, WindowsError): |
Pawel Zarembski |
0:01f31e923fe2 | 491 | print("#> ERROR: Failed to get git SHA, do you " |
Pawel Zarembski |
0:01f31e923fe2 | 492 | "have git in your PATH environment variable?") |
Pawel Zarembski |
0:01f31e923fe2 | 493 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 494 | |
Pawel Zarembski |
0:01f31e923fe2 | 495 | # Check are there any local, uncommitted modifications. |
Pawel Zarembski |
0:01f31e923fe2 | 496 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 497 | subprocess.check_output(["git", "diff", "--no-ext-diff", |
Pawel Zarembski |
0:01f31e923fe2 | 498 | "--quiet", "--exit-code"]) |
Pawel Zarembski |
0:01f31e923fe2 | 499 | except subprocess.CalledProcessError: |
Pawel Zarembski |
0:01f31e923fe2 | 500 | git_has_changes = True |
Pawel Zarembski |
0:01f31e923fe2 | 501 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 502 | git_has_changes = False |
Pawel Zarembski |
0:01f31e923fe2 | 503 | |
Pawel Zarembski |
0:01f31e923fe2 | 504 | os.chdir(cur_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 505 | |
Pawel Zarembski |
0:01f31e923fe2 | 506 | return git_sha, git_has_changes |
Pawel Zarembski |
0:01f31e923fe2 | 507 | |
Pawel Zarembski |
0:01f31e923fe2 | 508 | |
Pawel Zarembski |
0:01f31e923fe2 | 509 | def main(): |
Pawel Zarembski |
0:01f31e923fe2 | 510 | self_path = os.path.abspath(__file__) |
Pawel Zarembski |
0:01f31e923fe2 | 511 | test_dir = os.path.dirname(self_path) |
Pawel Zarembski |
0:01f31e923fe2 | 512 | daplink_dir = os.path.dirname(test_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 513 | |
Pawel Zarembski |
0:01f31e923fe2 | 514 | # We make assumptions that break if user copies script file outside the test dir |
Pawel Zarembski |
0:01f31e923fe2 | 515 | if os.path.basename(test_dir) != "test": |
Pawel Zarembski |
0:01f31e923fe2 | 516 | print("Error - this script must reside in the test directory") |
Pawel Zarembski |
0:01f31e923fe2 | 517 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 518 | |
Pawel Zarembski |
0:01f31e923fe2 | 519 | git_sha, local_changes = get_git_info(daplink_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 520 | firmware_list = get_firmware_names(daplink_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 521 | firmware_choices = [firmware for firmware in firmware_list if |
Pawel Zarembski |
0:01f31e923fe2 | 522 | firmware.endswith('_if')] |
Pawel Zarembski |
0:01f31e923fe2 | 523 | |
Pawel Zarembski |
0:01f31e923fe2 | 524 | description = 'DAPLink validation and testing tool' |
Pawel Zarembski |
0:01f31e923fe2 | 525 | parser = argparse.ArgumentParser(description=description) |
Pawel Zarembski |
0:01f31e923fe2 | 526 | parser.add_argument('--targetdir', |
Pawel Zarembski |
0:01f31e923fe2 | 527 | help='Directory with pre-built target test images.', |
Pawel Zarembski |
0:01f31e923fe2 | 528 | default=None) |
Pawel Zarembski |
0:01f31e923fe2 | 529 | parser.add_argument('--user', type=str, default=None, |
Pawel Zarembski |
0:01f31e923fe2 | 530 | help='MBED username (required for compile-api)') |
Pawel Zarembski |
0:01f31e923fe2 | 531 | parser.add_argument('--password', type=str, default=None, |
Pawel Zarembski |
0:01f31e923fe2 | 532 | help='MBED password (required for compile-api)') |
Pawel Zarembski |
0:01f31e923fe2 | 533 | parser.add_argument('--firmwaredir', |
Pawel Zarembski |
0:01f31e923fe2 | 534 | help='Directory with firmware images to test', |
Pawel Zarembski |
0:01f31e923fe2 | 535 | default=None) |
Pawel Zarembski |
0:01f31e923fe2 | 536 | parser.add_argument('--project-tool', choices=['uvision', 'mbedcli'], |
Pawel Zarembski |
0:01f31e923fe2 | 537 | help='Tool used to compile the project', |
Pawel Zarembski |
0:01f31e923fe2 | 538 | default='uvision') |
Pawel Zarembski |
0:01f31e923fe2 | 539 | parser.add_argument('--firmware', help='Firmware to test', action='append', |
Pawel Zarembski |
0:01f31e923fe2 | 540 | choices=firmware_choices, default=[], required=False) |
Pawel Zarembski |
0:01f31e923fe2 | 541 | parser.add_argument('--logdir', help='Directory to log test results to', |
Pawel Zarembski |
0:01f31e923fe2 | 542 | default=DEFAULT_TEST_DIR) |
Pawel Zarembski |
0:01f31e923fe2 | 543 | parser.add_argument('--noloadif', help='Skip load step for interface.', |
Pawel Zarembski |
0:01f31e923fe2 | 544 | default=False, action='store_true') |
Pawel Zarembski |
0:01f31e923fe2 | 545 | parser.add_argument('--notestendpt', help='Dont test the interface ' |
Pawel Zarembski |
0:01f31e923fe2 | 546 | 'USB endpoints.', default=False, action='store_true') |
Pawel Zarembski |
0:01f31e923fe2 | 547 | parser.add_argument('--loadbl', help='Load bootloader before test.', |
Pawel Zarembski |
0:01f31e923fe2 | 548 | default=False, action='store_true') |
Pawel Zarembski |
0:01f31e923fe2 | 549 | parser.add_argument('--testdl', help='Run DAPLink specific tests. ' |
Pawel Zarembski |
0:01f31e923fe2 | 550 | 'The DAPLink test tests bootloader updates so use' |
Pawel Zarembski |
0:01f31e923fe2 | 551 | 'with caution', |
Pawel Zarembski |
0:01f31e923fe2 | 552 | default=False, action='store_true') |
Pawel Zarembski |
0:01f31e923fe2 | 553 | parser.add_argument('--testfirst', help='If multiple boards of the same ' |
Pawel Zarembski |
0:01f31e923fe2 | 554 | 'type are found only test the first one.', |
Pawel Zarembski |
0:01f31e923fe2 | 555 | default=False, action='store_true') |
Pawel Zarembski |
0:01f31e923fe2 | 556 | parser.add_argument('--verbose', help='Verbose output', |
Pawel Zarembski |
0:01f31e923fe2 | 557 | choices=VERB_LEVELS, default=VERB_NORMAL) |
Pawel Zarembski |
0:01f31e923fe2 | 558 | parser.add_argument('--dryrun', default=False, action='store_true', |
Pawel Zarembski |
0:01f31e923fe2 | 559 | help='Print info on configurations but dont ' |
Pawel Zarembski |
0:01f31e923fe2 | 560 | 'actually run tests.') |
Pawel Zarembski |
0:01f31e923fe2 | 561 | parser.add_argument('--force', action='store_true', default=False, |
Pawel Zarembski |
0:01f31e923fe2 | 562 | help='Try to run tests even if there are problems. Delete logs from previous run.') |
Pawel Zarembski |
0:01f31e923fe2 | 563 | args = parser.parse_args() |
Pawel Zarembski |
0:01f31e923fe2 | 564 | |
Pawel Zarembski |
0:01f31e923fe2 | 565 | use_prebuilt = args.targetdir is not None |
Pawel Zarembski |
0:01f31e923fe2 | 566 | use_compile_api = args.user is not None and args.password is not None |
Pawel Zarembski |
0:01f31e923fe2 | 567 | |
Pawel Zarembski |
0:01f31e923fe2 | 568 | test_info = TestInfo('DAPLink') |
Pawel Zarembski |
0:01f31e923fe2 | 569 | |
Pawel Zarembski |
0:01f31e923fe2 | 570 | # Validate args |
Pawel Zarembski |
0:01f31e923fe2 | 571 | |
Pawel Zarembski |
0:01f31e923fe2 | 572 | # See if user wants to test endpoints. If yes and he didn't provide |
Pawel Zarembski |
0:01f31e923fe2 | 573 | # target test binaries, use the Compile API to build them |
Pawel Zarembski |
0:01f31e923fe2 | 574 | all_targets = None |
Pawel Zarembski |
0:01f31e923fe2 | 575 | if not args.notestendpt: |
Pawel Zarembski |
0:01f31e923fe2 | 576 | if not use_prebuilt and not use_compile_api: |
Pawel Zarembski |
0:01f31e923fe2 | 577 | print("Endpoint test requires target test images.") |
Pawel Zarembski |
0:01f31e923fe2 | 578 | print(" Directory with pre-built target test images") |
Pawel Zarembski |
0:01f31e923fe2 | 579 | print(" must be specified with '--targetdir'") |
Pawel Zarembski |
0:01f31e923fe2 | 580 | print("OR") |
Pawel Zarembski |
0:01f31e923fe2 | 581 | print(" developer.mbed.org login credentials must be ") |
Pawel Zarembski |
0:01f31e923fe2 | 582 | print(" specified with '--user' and '--password' so test ") |
Pawel Zarembski |
0:01f31e923fe2 | 583 | print(" images can be built with the RESTful Compile API.") |
Pawel Zarembski |
0:01f31e923fe2 | 584 | print("NOTE: you can skip the endpoint tests altogether ") |
Pawel Zarembski |
0:01f31e923fe2 | 585 | print("with --notestendpt") |
Pawel Zarembski |
0:01f31e923fe2 | 586 | |
Pawel Zarembski |
0:01f31e923fe2 | 587 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 588 | |
Pawel Zarembski |
0:01f31e923fe2 | 589 | if args.targetdir is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 590 | target_dir = args.targetdir |
Pawel Zarembski |
0:01f31e923fe2 | 591 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 592 | target_dir = daplink_dir + os.sep + 'tmp' |
Pawel Zarembski |
0:01f31e923fe2 | 593 | build_target_bundle(target_dir, args.user, args.password, test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 594 | |
Pawel Zarembski |
0:01f31e923fe2 | 595 | target_bundle = load_target_bundle(target_dir) |
Pawel Zarembski |
0:01f31e923fe2 | 596 | all_targets = target_bundle.get_target_list() |
Pawel Zarembski |
0:01f31e923fe2 | 597 | |
Pawel Zarembski |
0:01f31e923fe2 | 598 | if os.path.exists(args.logdir): |
Pawel Zarembski |
0:01f31e923fe2 | 599 | if args.force: |
Pawel Zarembski |
0:01f31e923fe2 | 600 | shutil.rmtree(args.logdir) |
Pawel Zarembski |
0:01f31e923fe2 | 601 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 602 | print('Error - test results directory "%s" already exists' % |
Pawel Zarembski |
0:01f31e923fe2 | 603 | args.logdir) |
Pawel Zarembski |
0:01f31e923fe2 | 604 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 605 | |
Pawel Zarembski |
0:01f31e923fe2 | 606 | # Get all relevant info |
Pawel Zarembski |
0:01f31e923fe2 | 607 | if args.firmwaredir is None: |
Pawel Zarembski |
0:01f31e923fe2 | 608 | firmware_bundle = load_bundle_from_project(args.project_tool) |
Pawel Zarembski |
0:01f31e923fe2 | 609 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 610 | firmware_bundle = load_bundle_from_release(args.firmwaredir) |
Pawel Zarembski |
0:01f31e923fe2 | 611 | |
Pawel Zarembski |
0:01f31e923fe2 | 612 | all_firmware = firmware_bundle.get_firmware_list() |
Pawel Zarembski |
0:01f31e923fe2 | 613 | all_boards = get_all_attached_daplink_boards() |
Pawel Zarembski |
0:01f31e923fe2 | 614 | |
Pawel Zarembski |
0:01f31e923fe2 | 615 | for board in all_boards: |
Pawel Zarembski |
0:01f31e923fe2 | 616 | if board.get_mode() == board.MODE_BL: |
Pawel Zarembski |
0:01f31e923fe2 | 617 | print('Switching to APP mode on board: %s' % board.unique_id) |
Pawel Zarembski |
0:01f31e923fe2 | 618 | try: |
Pawel Zarembski |
0:01f31e923fe2 | 619 | board.set_mode(board.MODE_IF) |
Pawel Zarembski |
0:01f31e923fe2 | 620 | except Exception: |
Pawel Zarembski |
0:01f31e923fe2 | 621 | print('Unable to switch mode on board: %s' % board.unique_id) |
Pawel Zarembski |
0:01f31e923fe2 | 622 | |
Pawel Zarembski |
0:01f31e923fe2 | 623 | # Make sure firmware is present |
Pawel Zarembski |
0:01f31e923fe2 | 624 | firmware_explicitly_specified = len(args.firmware) != 0 |
Pawel Zarembski |
0:01f31e923fe2 | 625 | if firmware_explicitly_specified: |
Pawel Zarembski |
0:01f31e923fe2 | 626 | all_firmware_names = set(fw.name for fw in all_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 627 | firmware_missing = False |
Pawel Zarembski |
0:01f31e923fe2 | 628 | for firmware_name in args.firmware: |
Pawel Zarembski |
0:01f31e923fe2 | 629 | if firmware_name not in all_firmware_names: |
Pawel Zarembski |
0:01f31e923fe2 | 630 | firmware_missing = True |
Pawel Zarembski |
0:01f31e923fe2 | 631 | test_info.failure('Cannot find firmware %s' % firmware_name) |
Pawel Zarembski |
0:01f31e923fe2 | 632 | if firmware_missing: |
Pawel Zarembski |
0:01f31e923fe2 | 633 | test_info.failure('Firmware missing - aborting test') |
Pawel Zarembski |
0:01f31e923fe2 | 634 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 635 | |
Pawel Zarembski |
0:01f31e923fe2 | 636 | # Create manager and add resources |
Pawel Zarembski |
0:01f31e923fe2 | 637 | tester = TestManager() |
Pawel Zarembski |
0:01f31e923fe2 | 638 | tester.add_firmware(all_firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 639 | tester.add_boards(all_boards) |
Pawel Zarembski |
0:01f31e923fe2 | 640 | if all_targets is not None: |
Pawel Zarembski |
0:01f31e923fe2 | 641 | tester.add_targets(all_targets) |
Pawel Zarembski |
0:01f31e923fe2 | 642 | if firmware_explicitly_specified: |
Pawel Zarembski |
0:01f31e923fe2 | 643 | tester.set_firmware_filter(args.firmware) |
Pawel Zarembski |
0:01f31e923fe2 | 644 | |
Pawel Zarembski |
0:01f31e923fe2 | 645 | # Configure test manager |
Pawel Zarembski |
0:01f31e923fe2 | 646 | tester.set_test_first_board_only(args.testfirst) |
Pawel Zarembski |
0:01f31e923fe2 | 647 | tester.set_load_if(not args.noloadif) |
Pawel Zarembski |
0:01f31e923fe2 | 648 | tester.set_test_ep(not args.notestendpt) |
Pawel Zarembski |
0:01f31e923fe2 | 649 | tester.set_load_bl(args.loadbl) |
Pawel Zarembski |
0:01f31e923fe2 | 650 | tester.set_test_daplink(args.testdl) |
Pawel Zarembski |
0:01f31e923fe2 | 651 | |
Pawel Zarembski |
0:01f31e923fe2 | 652 | # Build test configurations |
Pawel Zarembski |
0:01f31e923fe2 | 653 | tester.build_test_configurations(test_info) |
Pawel Zarembski |
0:01f31e923fe2 | 654 | |
Pawel Zarembski |
0:01f31e923fe2 | 655 | test_config_list = tester.get_test_configurations() |
Pawel Zarembski |
0:01f31e923fe2 | 656 | if len(test_config_list) == 0: |
Pawel Zarembski |
0:01f31e923fe2 | 657 | test_info.failure("Nothing that can be tested") |
Pawel Zarembski |
0:01f31e923fe2 | 658 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 659 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 660 | test_info.info('Test configurations to be run:') |
Pawel Zarembski |
0:01f31e923fe2 | 661 | index = 0 |
Pawel Zarembski |
0:01f31e923fe2 | 662 | for test_config in test_config_list: |
Pawel Zarembski |
0:01f31e923fe2 | 663 | test_info.info(' %i: %s' % (index, test_config)) |
Pawel Zarembski |
0:01f31e923fe2 | 664 | index += 1 |
Pawel Zarembski |
0:01f31e923fe2 | 665 | test_info.info('') |
Pawel Zarembski |
0:01f31e923fe2 | 666 | |
Pawel Zarembski |
0:01f31e923fe2 | 667 | untested_list = tester.get_untested_firmware() |
Pawel Zarembski |
0:01f31e923fe2 | 668 | if len(untested_list) == 0: |
Pawel Zarembski |
0:01f31e923fe2 | 669 | test_info.info("All firmware can be tested") |
Pawel Zarembski |
0:01f31e923fe2 | 670 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 671 | test_info.info('Fimrware that will not be tested:') |
Pawel Zarembski |
0:01f31e923fe2 | 672 | for untested_firmware in untested_list: |
Pawel Zarembski |
0:01f31e923fe2 | 673 | test_info.info(' %s' % untested_firmware.name) |
Pawel Zarembski |
0:01f31e923fe2 | 674 | test_info.info('') |
Pawel Zarembski |
0:01f31e923fe2 | 675 | |
Pawel Zarembski |
0:01f31e923fe2 | 676 | if firmware_explicitly_specified and len(untested_list) != 0: |
Pawel Zarembski |
0:01f31e923fe2 | 677 | test_info.failure("Exiting because not all firmware could be tested") |
Pawel Zarembski |
0:01f31e923fe2 | 678 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 679 | |
Pawel Zarembski |
0:01f31e923fe2 | 680 | # If this is a dryrun don't run tests, just print info |
Pawel Zarembski |
0:01f31e923fe2 | 681 | if args.dryrun: |
Pawel Zarembski |
0:01f31e923fe2 | 682 | exit(0) |
Pawel Zarembski |
0:01f31e923fe2 | 683 | |
Pawel Zarembski |
0:01f31e923fe2 | 684 | # Run tests |
Pawel Zarembski |
0:01f31e923fe2 | 685 | tester.run_tests() |
Pawel Zarembski |
0:01f31e923fe2 | 686 | |
Pawel Zarembski |
0:01f31e923fe2 | 687 | # Print test results |
Pawel Zarembski |
0:01f31e923fe2 | 688 | tester.print_results(args.verbose) |
Pawel Zarembski |
0:01f31e923fe2 | 689 | tester.write_test_results(args.logdir, |
Pawel Zarembski |
0:01f31e923fe2 | 690 | git_sha=git_sha, |
Pawel Zarembski |
0:01f31e923fe2 | 691 | local_changes=local_changes) |
Pawel Zarembski |
0:01f31e923fe2 | 692 | |
Pawel Zarembski |
0:01f31e923fe2 | 693 | # Warn about untested boards |
Pawel Zarembski |
0:01f31e923fe2 | 694 | print('') |
Pawel Zarembski |
0:01f31e923fe2 | 695 | for firmware in tester.get_untested_firmware(): |
Pawel Zarembski |
0:01f31e923fe2 | 696 | print('Warning - configuration %s is untested' % firmware.name) |
Pawel Zarembski |
0:01f31e923fe2 | 697 | |
Pawel Zarembski |
0:01f31e923fe2 | 698 | if tester.all_tests_pass: |
Pawel Zarembski |
0:01f31e923fe2 | 699 | print("All boards passed") |
Pawel Zarembski |
0:01f31e923fe2 | 700 | exit(0) |
Pawel Zarembski |
0:01f31e923fe2 | 701 | else: |
Pawel Zarembski |
0:01f31e923fe2 | 702 | print("Test Failed") |
Pawel Zarembski |
0:01f31e923fe2 | 703 | exit(-1) |
Pawel Zarembski |
0:01f31e923fe2 | 704 | |
Pawel Zarembski |
0:01f31e923fe2 | 705 | |
Pawel Zarembski |
0:01f31e923fe2 | 706 | if __name__ == "__main__": |
Pawel Zarembski |
0:01f31e923fe2 | 707 | main() |