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