1#!/usr/bin/env python 2# 3# Copyright (c) 2020, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29""" 30parse_topofile.py 31----------------- 32This script is used to parse TopologyConfig.txt file to list vendor device info 33when preparing for the Thread Certification testbed 34 35usage: parse_topofile.py [-h] [-f TOPO_FILE] [-c CASE_LIST [CASE_LIST ...]] 36 37 parse TopologyConfig file and list all devices by case 38 39 optional arguments: 40 -h, --help show this help message and exit 41 -f TOPO_FILE Topology config file (default: C:/GRL/Thread1.1/Thread 42 _Harness/TestScripts/TopologyConfig.txt) 43 -c CASE_LIST [CASE_LIST ...] 44 Test case list (e.g. 5.1.1 9.2.1, default: all) 45 46Examples: 47 1. Get case 5.1.1 vendor info 48 cmd: python parse_topofile.py -f TopologyConfig.txt -c 5.1.1 49 output: 50 case 5.1.1: 51 role-vendor pair: [('Leader', 'ARM'), ('Router_1', 'ARM')] 52 vendor devices : {'ARM': 2} 53 54 Testbed needed vendor devices:{'ARM': 2} 55 56 2. Get case 5.1.1 and 5.2.1 vendor info 57 cmd: python parse_topofile.py -f TopologyConfig.txt -c 5.1.1 5.2.1 58 output: 59 case 5.1.1: 60 role-vendor pair: [('Leader', 'ARM'), ('Router_1', 'ARM')] 61 vendor devices : {'ARM': 2} 62 case 5.2.1: 63 role-vendor pair: [('Leader', 'OpenThread'), ('REED_1', 'Kirale'), ('MED_1', 'SiLabs')] 64 vendor devices : {'OpenThread': 1, 'Kirale': 1, 'SiLabs': 1} 65 66 Testbed needed vendor devices:{'ARM': 2, 'OpenThread': 1, 'Kirale': 1, 'SiLabs': 1} 67 68 3. Get all cases vendor info 69 cmd: python parse_topofile.py -f TopologyConfig.txt 70 output: 71 ... ... ... 72 73 Testbed needed vendor devices:{'ARM': 4, 'NXP': 5, 'OpenThread': 5, 'Kirale': 6, 'SiLabs': 5, 'Any': 7} 74 75Notes: 76 The result is just for reference, the exact requirement per vendor may be equal or less than what is generated by the script. 77 78""" 79 80import argparse 81import logging 82import re 83from collections import Counter 84 85logging.basicConfig(format='%(message)s', level=logging.DEBUG) 86MAX_VENDOR_DEVICE = 32 87 88 89def device_calculate(topo_file, case_list): 90 testbed_vendor_dict = Counter() 91 with open(topo_file, 'r') as f: 92 for line in f: 93 94 case_vendor_dict = Counter() 95 96 if not line: 97 break 98 line = line.strip() 99 100 # line example : 101 # 5.5.1-Leader:Kirale,Router_1:OpenThread 102 try: 103 if re.match(r'\s*#.*', line): 104 continue 105 106 matched_case = re.match(r'(.*)-(.*)', line, re.M | re.I) 107 108 if 'all' not in case_list and matched_case.group(1) not in case_list: 109 continue 110 111 logging.info('case %s:' % matched_case.group(1)) 112 if 'all' not in case_list: 113 case_list.remove(matched_case.group(1)) 114 role_vendor_str = matched_case.group(2) 115 role_vendor_raw_list = re.split(',', role_vendor_str) 116 role_vendor_list = [] 117 118 for device_pair in role_vendor_raw_list: 119 device_pair = re.split(':', device_pair) 120 role_vendor_list.append(tuple(device_pair)) 121 logging.info('\trole-vendor pair: %s' % role_vendor_list) 122 except Exception as e: 123 logging.info('Unrecognized format: %s\n%s' % (line, format(e))) 124 raise 125 126 for _, vendor in role_vendor_list: 127 case_vendor_dict[vendor] += 1 128 testbed_vendor_dict[vendor] = max(testbed_vendor_dict[vendor], case_vendor_dict[vendor]) 129 130 logging.info('\tvendor devices : %s' % dict(case_vendor_dict)) 131 132 if case_list and 'all' not in case_list: 133 logging.info('Case %s not found' % str(case_list)[1:-1]) 134 135 # vendor 'Any' stands for any other vendors 136 # override 'Any' counter when overlapping with other vendors 137 count_any = MAX_VENDOR_DEVICE 138 for key in testbed_vendor_dict: 139 if key != 'Any': 140 count_any -= testbed_vendor_dict[key] 141 if 'Any' in testbed_vendor_dict: 142 testbed_vendor_dict['Any'] = count_any 143 144 logging.info('\nTestbed needed vendor devices:%s' % dict(testbed_vendor_dict)) 145 146 147def main(): 148 parser = argparse.ArgumentParser(description='parse TopologyConfig file and list all devices by case') 149 parser.add_argument( 150 '-f', 151 dest='topo_file', 152 default='C:/GRL/Thread1.1/Thread_Harness/TestScripts/TopologyConfig.txt', 153 help='Topology config file (default: C:/GRL/Thread1.1/Thread_Harness/TestScripts/TopologyConfig.txt)', 154 ) 155 156 parser.add_argument('-c', 157 dest='case_list', 158 nargs='+', 159 default=['all'], 160 help='Test case list (e.g. 5.1.1 9.2.1, default: all) ') 161 args = parser.parse_args() 162 device_calculate(args.topo_file, args.case_list) 163 164 165if __name__ == '__main__': 166 main() 167