winIDEA SDK
cumulative_module_coverage.py
1# This script is licensed under BSD License, see file LICENSE.txt.
2#
3# (c) TASKING Germany GmbH, 2023
4
5import isystem.connect as ic
6import isystem.itest as it
7
8
9winidea_id = ''
10
11
12MODULE_NAME = "utils.cpp"
13
14
15class Monitor:
16 def __init__(self, no_of_sub_tasks):
17 self.no_of_sub_tasks = no_of_sub_tasks
18 self.test_count = 0
19
20 def isCanceled(self):
21 pass
22
23 def subTask(self, taskDesc):
24 print(taskDesc)
25
26 def worked(self, count):
27 self.test_count += count
28 print('#' * self.test_count + '-' * (self.no_of_sub_tasks - self.test_count))
29
30
31def init_target() -> ic.ConnectionMgr:
32 cmgr = ic.ConnectionMgr()
33
34 cmgr.connect(ic.CConnectionConfig().instanceId(winidea_id))
35
36 debug_ctrl = ic.CDebugFacade(cmgr)
37
38 debug_ctrl.download()
39
40 debug_ctrl.runUntilFunction('main')
41 debug_ctrl.waitUntilStopped()
42
43 return cmgr
44
45
46def run_test(connection_mgr: ic.ConnectionMgr) -> ic.CCoverageController2:
47 test_case = it.PTestCase(connection_mgr)
48
49 test_case.reset() # just in case there's something left from previous run
50
51 print("Target initialized, configuring coverage...")
52
53 # Perform coverage initialization with isystem.connect calls.
54
55 coverage_ctrl = ic.CCoverageController2(connection_mgr, "moduleCoverage.trd", 'w')
56
57 trigger_idx = coverage_ctrl.getActiveTriggerIndex()
58
59 coverage_ctrl.setScope(trigger_idx, ic.CCoverageController2.EScopeCustom)
60 coverage_ctrl.setProvideAssemblerInfo(trigger_idx, True)
61
62 # We want to get coverage of a complete source file
63 coverage_ctrl.addArea(trigger_idx, ic.CCoverageController2.EAreaModule, MODULE_NAME)
64
65 coverage_ctrl.start()
66
67 print("Coverage configured and started!")
68
69 # Test specification uses the existing code coverage document.
70 testSpec = ic.CTestSpecification.parseTestSpec(
71 """
72 # abstract base specification defines coverage for all derived tests.
73 run: false # this is an abstract base test
74 analyzer:
75 runMode: start
76 document: moduleCoverage.trd # document initialized above
77 openMode: a # 'append' mode keeps previous coverage data
78 coverage:
79 isActive: true
80 tests: # derived tests execute the function for several parameters to get full coverage
81 - func: [fibonacci, [0], rv]
82 assert:
83 expressions: [rv == 0]
84 - func: [get_random]
85 - func: [fibonacci, [2], rv]
86 assert:
87 expressions: [rv = 2]
88 """)
89
90 monitor = Monitor(testSpec.getNoOfTests(True))
91 test_case.runDerivedTests(testSpec, None, monitor)
92
93 return coverage_ctrl
94
95
96def print_coverage(coverage_ctrl: ic.CCoverageController2):
97 # tests have executed, we have to check it the coverage
98 coverage_data = ic.CCoverageData2.createInstance(coverage_ctrl,
99 'testCvrg.xml',
100 True) # load data to memory
101
102 # always check for parser warnings
103 warnings = coverage_data.getParserWarnings()
104 if warnings:
105 print('WARNING(S): ', warnings)
106
107 coverage_data.closeParser() # releases memory and closes XML file
108
109 stat = coverage_data.getStatistic(ic.CCoverageStatistic2.EModule, MODULE_NAME)
110
111 bytes_all = stat.getBytesAll()
112 bytes_executed = stat.getBytesExecuted()
113 conditions_all = stat.getConditionsAll()
114 conditions_executed = stat.getConditionsExecuted()
115 conditions_taken = stat.getConditionsTrue()
116 conditions_not_taken = stat.getConditionsFalse()
117 conditions_both = stat.getConditionsBoth()
118
119 print('code coverage:', 100. * bytes_executed / bytes_all, '%')
120 print('conditions executed', 100. * conditions_executed / conditions_all, '%')
121 print('conditions taken', 100. * conditions_taken / conditions_all, '%')
122 print('conditions not taken', 100. * conditions_not_taken / conditions_all, '%')
123 print('conditions both', 100. * conditions_both / conditions_all, '%')
124
125
126if __name__ == '__main__':
127 cmgr = init_target()
128 cvrg_ctrl = run_test(cmgr)
129 print_coverage(cvrg_ctrl)