mirror of
https://github.com/espressif/openthread.git
synced 2026-08-10 04:37:47 +00:00
[harness-automation] add a parser tool for TopologyConfig file (#4975)
- parse TopologyConfig file in Thread Certification Test Harness - list multi-vendor device numbers by case - list needed vendor device numbers for the whole certification testbed
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
"""
|
||||
parse_topofile.py
|
||||
-----------------
|
||||
This script is used to parse TopologyConfig.txt file to list vendor device info
|
||||
when preparing for the Thread Certification testbed
|
||||
|
||||
usage: parse_topofile.py [-h] [-f TOPO_FILE] [-c CASE_LIST [CASE_LIST ...]]
|
||||
|
||||
parse TopologyConfig file and list all devices by case
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-f TOPO_FILE Topology config file (default: C:/GRL/Thread1.1/Thread
|
||||
_Harness/TestScripts/TopologyConfig.txt)
|
||||
-c CASE_LIST [CASE_LIST ...]
|
||||
Test case list (e.g. 5.1.1 9.2.1, default: all)
|
||||
|
||||
Examples:
|
||||
1. Get case 5.1.1 vendor info
|
||||
cmd: python parse_topofile.py -f TopologyConfig.txt -c 5.1.1
|
||||
output:
|
||||
case 5.1.1:
|
||||
role-vendor pair: [('Leader', 'ARM'), ('Router_1', 'ARM')]
|
||||
vendor devices : {'ARM': 2}
|
||||
|
||||
Testbed needed vendor devices:{'ARM': 2}
|
||||
|
||||
2. Get case 5.1.1 and 5.2.1 vendor info
|
||||
cmd: python parse_topofile.py -f TopologyConfig.txt -c 5.1.1 5.2.1
|
||||
output:
|
||||
case 5.1.1:
|
||||
role-vendor pair: [('Leader', 'ARM'), ('Router_1', 'ARM')]
|
||||
vendor devices : {'ARM': 2}
|
||||
case 5.2.1:
|
||||
role-vendor pair: [('Leader', 'OpenThread'), ('REED_1', 'Kirale'), ('MED_1', 'SiLabs')]
|
||||
vendor devices : {'OpenThread': 1, 'Kirale': 1, 'SiLabs': 1}
|
||||
|
||||
Testbed needed vendor devices:{'ARM': 2, 'OpenThread': 1, 'Kirale': 1, 'SiLabs': 1}
|
||||
|
||||
3. Get all cases vendor info
|
||||
cmd: python parse_topofile.py -f TopologyConfig.txt
|
||||
output:
|
||||
... ... ...
|
||||
|
||||
Testbed needed vendor devices:{'ARM': 4, 'NXP': 5, 'OpenThread': 5, 'Kirale': 6, 'SiLabs': 5, 'Any': 7}
|
||||
|
||||
Notes:
|
||||
The result is just for reference, the exact requirement per vendor may be equal or less than what is generated by the script.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import re
|
||||
from collections import Counter
|
||||
|
||||
logging.basicConfig(format='%(message)s', level=logging.DEBUG)
|
||||
MAX_VENDOR_DEVICE = 32
|
||||
|
||||
|
||||
def device_calculate(topo_file, case_list):
|
||||
testbed_vendor_dict = Counter()
|
||||
with open(topo_file, 'r') as f:
|
||||
for line in f:
|
||||
|
||||
case_vendor_dict = Counter()
|
||||
|
||||
if not line:
|
||||
break
|
||||
line = line.strip()
|
||||
|
||||
# line example :
|
||||
# 5.5.1-Leader:Kirale,Router_1:OpenThread
|
||||
try:
|
||||
if re.match(r'\s*#.*', line):
|
||||
continue
|
||||
|
||||
matched_case = re.match(r'(.*)-(.*)', line, re.M | re.I)
|
||||
|
||||
if 'all' not in case_list and matched_case.group(
|
||||
1) not in case_list:
|
||||
continue
|
||||
|
||||
logging.info('case %s:' % matched_case.group(1))
|
||||
if 'all' not in case_list:
|
||||
case_list.remove(matched_case.group(1))
|
||||
role_vendor_str = matched_case.group(2)
|
||||
role_vendor_raw_list = re.split(',', role_vendor_str)
|
||||
role_vendor_list = []
|
||||
|
||||
for device_pair in role_vendor_raw_list:
|
||||
device_pair = re.split(':', device_pair)
|
||||
role_vendor_list.append(tuple(device_pair))
|
||||
logging.info('\trole-vendor pair: %s' % role_vendor_list)
|
||||
except Exception as e:
|
||||
logging.info('Unrecognized format: %s\n%s' % (line, format(e)))
|
||||
raise
|
||||
|
||||
for _, vendor in role_vendor_list:
|
||||
case_vendor_dict[vendor] += 1
|
||||
testbed_vendor_dict[vendor] = max(testbed_vendor_dict[vendor],
|
||||
case_vendor_dict[vendor])
|
||||
|
||||
logging.info('\tvendor devices : %s' % dict(case_vendor_dict))
|
||||
|
||||
if case_list and 'all' not in case_list:
|
||||
logging.info('Case %s not found' % str(case_list)[1:-1])
|
||||
|
||||
# vendor 'Any' stands for any other vendors
|
||||
# override 'Any' counter when overlapping with other vendors
|
||||
count_any = MAX_VENDOR_DEVICE
|
||||
for key in testbed_vendor_dict:
|
||||
if key != 'Any':
|
||||
count_any -= testbed_vendor_dict[key]
|
||||
if 'Any' in testbed_vendor_dict:
|
||||
testbed_vendor_dict['Any'] = count_any
|
||||
|
||||
logging.info('\nTestbed needed vendor devices:%s' %
|
||||
dict(testbed_vendor_dict))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='parse TopologyConfig file and list all devices by case')
|
||||
parser.add_argument(
|
||||
'-f',
|
||||
dest='topo_file',
|
||||
default='C:/GRL/Thread1.1/Thread_Harness/TestScripts/TopologyConfig.txt',
|
||||
help=
|
||||
'Topology config file (default: C:/GRL/Thread1.1/Thread_Harness/TestScripts/TopologyConfig.txt)',
|
||||
)
|
||||
|
||||
parser.add_argument('-c',
|
||||
dest='case_list',
|
||||
nargs='+',
|
||||
default=['all'],
|
||||
help='Test case list (e.g. 5.1.1 9.2.1, default: all) ')
|
||||
args = parser.parse_args()
|
||||
device_calculate(args.topo_file, args.case_list)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user