Skip to content

Commit 6fd08a0

Browse files
XToripuruandy31415arkq
authored
[Tizen] Add code coverage for tests on QEMU (project-chip#36245)
* Add -coverage target * Allow to specify runner * Fix the .gcda files output location * Allow runner in interactive mode * Remove wrap * Fix expected test output * Collect common lcov args * Update scripts/build/builders/tizen.py Co-authored-by: Arkadiusz Bokowy <arkadiusz.bokowy@gmail.com> --------- Co-authored-by: Andrei Litvin <andy314@gmail.com> Co-authored-by: Arkadiusz Bokowy <arkadiusz.bokowy@gmail.com>
1 parent a10fc1f commit 6fd08a0

File tree

9 files changed

+82
-9
lines changed

9 files changed

+82
-9
lines changed

scripts/build/build/targets.py

+2
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,8 @@ def BuildTizenTarget():
692692
target.AppendModifier("no-wifi", enable_wifi=False)
693693
target.AppendModifier("asan", use_asan=True)
694694
target.AppendModifier("ubsan", use_ubsan=True)
695+
target.AppendModifier('coverage', use_coverage=True).OnlyIfRe(
696+
'-tests')
695697
target.AppendModifier('with-ui', with_ui=True)
696698

697699
return target

scripts/build/builders/tizen.py

+51
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ def __init__(self,
8989
use_asan: bool = False,
9090
use_tsan: bool = False,
9191
use_ubsan: bool = False,
92+
use_coverage: bool = False,
9293
with_ui: bool = False,
9394
):
9495
super(TizenBuilder, self).__init__(
@@ -130,9 +131,59 @@ def __init__(self,
130131
raise Exception("TSAN sanitizer not supported by Tizen toolchain")
131132
if use_ubsan:
132133
self.extra_gn_options.append('is_ubsan=true')
134+
self.use_coverage = use_coverage
135+
if use_coverage:
136+
self.extra_gn_options.append('use_coverage=true')
133137
if with_ui:
134138
self.extra_gn_options.append('chip_examples_enable_ui=true')
135139

140+
def generate(self):
141+
super(TizenBuilder, self).generate()
142+
if self.app == TizenApp.TESTS and self.use_coverage:
143+
self.coverage_dir = os.path.join(self.output_dir, 'coverage')
144+
self._Execute(['mkdir', '-p', self.coverage_dir], title="Create coverage output location")
145+
146+
def lcov_args(self):
147+
gcov = os.path.join(os.environ['TIZEN_SDK_TOOLCHAIN'], 'bin/arm-linux-gnueabi-gcov')
148+
return [
149+
'lcov', '--gcov-tool', gcov, '--ignore-errors', 'unused,mismatch', '--capture', '--directory', os.path.join(
150+
self.output_dir, 'obj'),
151+
'--exclude', '**/src/controller/*',
152+
'--exclude', '**/connectedhomeip/zzz_generated/*',
153+
'--exclude', '**/connectedhomeip/third_party/*',
154+
'--exclude', '/opt/*',
155+
]
156+
157+
def PreBuildCommand(self):
158+
if self.app == TizenApp.TESTS and self.use_coverage:
159+
cmd = ['ninja', '-C', self.output_dir]
160+
161+
if self.ninja_jobs is not None:
162+
cmd.append('-j' + str(self.ninja_jobs))
163+
164+
cmd.append('Tizen')
165+
166+
self._Execute(cmd, title="Build-only")
167+
168+
self._Execute(self.lcov_args() + [
169+
'--initial',
170+
'--output-file', os.path.join(self.coverage_dir, 'lcov_base.info')
171+
], title="Initial coverage baseline")
172+
173+
def PostBuildCommand(self):
174+
if self.app == TizenApp.TESTS and self.use_coverage:
175+
176+
self._Execute(self.lcov_args() + ['--output-file', os.path.join(self.coverage_dir,
177+
'lcov_test.info')], title="Update coverage")
178+
179+
gcov = os.path.join(os.environ['TIZEN_SDK_TOOLCHAIN'], 'bin/arm-linux-gnueabi-gcov')
180+
self._Execute(['lcov', '--gcov-tool', gcov, '--add-tracefile', os.path.join(self.coverage_dir, 'lcov_base.info'),
181+
'--add-tracefile', os.path.join(self.coverage_dir, 'lcov_test.info'),
182+
'--output-file', os.path.join(self.coverage_dir, 'lcov_final.info')
183+
], title="Final coverage info")
184+
self._Execute(['genhtml', os.path.join(self.coverage_dir, 'lcov_final.info'), '--output-directory',
185+
os.path.join(self.coverage_dir, 'html')], title="HTML coverage")
186+
136187
def GnBuildArgs(self):
137188
# Make sure that required ENV variables are defined
138189
for env in ('TIZEN_SDK_ROOT', 'TIZEN_SDK_SYSROOT'):

scripts/build/testdata/all_targets_linux_x64.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ nrf-native-posix-64-tests
2121
nuttx-x64-light
2222
qpg-qpg6105-{lock,light,shell,persistent-storage,light-switch,thermostat}[-updateimage][-data-model-disabled][-data-model-enabled]
2323
stm32-stm32wb5mm-dk-light
24-
tizen-arm-{all-clusters,chip-tool,light,tests}[-no-ble][-no-thread][-no-wifi][-asan][-ubsan][-with-ui]
24+
tizen-arm-{all-clusters,chip-tool,light,tests}[-no-ble][-no-thread][-no-wifi][-asan][-ubsan][-coverage][-with-ui]
2525
telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-data-model-disabled][-data-model-enabled]
2626
openiotsdk-{shell,lock}[-mbedtls][-psa]

src/test_driver/tizen/chip_tests/BUILD.gn

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ tizen_qemu_run("chip-tests") {
2424
virtio_net = true
2525

2626
# Share tests directory.
27-
share = "${root_out_dir}/tests"
27+
share = "${root_out_dir}"
28+
29+
# Runner script file name.
30+
runner = "runner-${target_name}.sh"
2831

2932
# Copy runner script to shared directory.
3033
copy("${target_name}:runner") {
3134
sources = [ "runner.sh" ]
32-
outputs = [ share + "/runner.sh" ]
35+
outputs = [ share + "/" + runner ]
3336
}
3437

3538
# Build CHIP unit tests.

src/test_driver/tizen/chip_tests/runner.sh

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ set -e
2121
# Print CHIP logs on stdout
2222
dlogutil CHIP &
2323

24+
# Set the correct path for .gcda files
25+
export GCOV_PREFIX=/mnt/chip
26+
export GCOV_PREFIX_STRIP=5
27+
2428
FAILED=()
2529
STATUS=0
2630

@@ -43,7 +47,7 @@ while IFS= read -r TEST; do
4347
echo -e "DONE: \e[31mFAIL\e[0m"
4448
fi
4549

46-
done < <(find /mnt/chip -type f -executable ! -name runner.sh)
50+
done < <(find /mnt/chip/tests -type f -executable ! -name runner.sh)
4751

4852
if [ ! "$STATUS" -eq 0 ]; then
4953
echo

src/test_driver/tizen/integration_tests/lighting-app/BUILD.gn

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ tizen_qemu_run("lighting-app") {
2626
# Share output directory.
2727
share = "${root_out_dir}"
2828

29+
# Runner script file name.
30+
runner = "runner-${target_name}.sh"
31+
2932
# Copy runner script to shared directory.
3033
copy("${target_name}:runner") {
3134
sources = [ "runner.sh" ]
32-
outputs = [ share + "/runner.sh" ]
35+
outputs = [ share + "/" + runner ]
3336
}
3437

3538
# Build applications used in the test.

src/test_driver/tizen/integration_tests/lighting-app/runner.sh

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ set -e
2121
# Print CHIP logs on stdout
2222
dlogutil CHIP &
2323

24+
# Set the correct path for .gcda files
25+
export GCOV_PREFIX=/mnt/chip
26+
export GCOV_PREFIX_STRIP=5
27+
2428
# Install lighting Matter app
2529
pkgcmd -i -t tpk -p /mnt/chip/org.tizen.matter.*/out/org.tizen.matter.*.tpk
2630
# Launch lighting Matter app

third_party/tizen/tizen_qemu.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@
6666
"default: $TIZEN_SDK_ROOT/iot-sysdata.img"))
6767
parser.add_argument(
6868
'--share', type=str,
69-
help=("host directory to share with the guest; if file named 'runner.sh' "
70-
"is present at the root of that directory, it will be executed "
71-
"automatically after boot"))
69+
help=("host directory to share with the guest"))
70+
parser.add_argument(
71+
'--runner', type=str,
72+
help=("path to the runner script which will run automatically after boot. path should be relative to shared directory"))
7273
parser.add_argument(
7374
'--output', metavar='FILE', default="/dev/null",
7475
help="store the QEMU output in a FILE")
@@ -136,6 +137,9 @@ def whereis(binary_name):
136137
# Run root shell instead of the runner script.
137138
kernel_args += " rootshell"
138139

140+
if args.runner:
141+
kernel_args += " runner=/mnt/chip/%s" % args.runner
142+
139143
qemu_args += [
140144
'-kernel', args.kernel,
141145
'-append', kernel_args,
@@ -153,7 +157,7 @@ def whereis(binary_name):
153157
for line in iter(proc.stdout.readline, b''):
154158

155159
# Forward the output to the stdout and the log file.
156-
sys.stdout.write(line.decode(sys.stdout.encoding))
160+
sys.stdout.write(line.decode(sys.stdout.encoding, errors='ignore'))
157161
sys.stdout.flush()
158162
output.write(line)
159163

third_party/tizen/tizen_sdk.gni

+2
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ template("tizen_qemu_run") {
175175
testonly = true
176176

177177
assert(defined(invoker.share), "It is required to specify path to share.")
178+
assert(defined(invoker.runner), "It is required to specify runner script.")
178179

179180
# Store QEMU output in a dedicated log file.
180181
output_log_file = "${root_out_dir}/tizen-qemu-" + target_name + ".log"
@@ -186,6 +187,7 @@ template("tizen_qemu_run") {
186187

187188
args = [
188189
"--share=" + invoker.share,
190+
"--runner=" + invoker.runner,
189191
"--output=" + rebase_path(output_log_file),
190192
]
191193
if (defined(invoker.virtio_net) && invoker.virtio_net) {

0 commit comments

Comments
 (0)