Skip to content

Commit 33052ac

Browse files
committed
add DataRouter logging robustness integration tests
1 parent 1683b90 commit 33052ac

8 files changed

Lines changed: 149 additions & 6 deletions

File tree

.github/workflows/component_tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,5 @@ jobs:
6262
--test_output=errors \
6363
//score/test/component/datarouter:test_datarouter_filters \
6464
//score/test/component/mw_log:test_mw_log \
65-
//score/test/component/mw_log:test_mw_log_filters
65+
//score/test/component/mw_log:test_mw_log_filters \
66+
//score/test/integration/datarouter:test_datarouter_scenarios

.github/workflows/component_tests_nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,4 @@ jobs:
6161
bazel test --lockfile_mode=error --config x86_64-linux \
6262
--test_tag_filters=integration \
6363
--test_output=errors \
64-
//score/test/component/...
64+
//score/test/...

score/test/component/BUILD

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pkg_tar(
2424
"@score_itf//third_party/dlt:dlt-receive",
2525
],
2626
target_compatible_with = ["@platforms//os:linux"],
27-
visibility = ["//score/test/component:__subpackages__"],
27+
visibility = ["//score/test:__subpackages__"],
2828
)
2929

3030
pkg_tar(
@@ -45,7 +45,7 @@ pkg_tar(
4545
pkg_tar(
4646
name = "datarouter_pkg",
4747
target_compatible_with = ["@platforms//os:linux"],
48-
visibility = ["//score/test/component:__subpackages__"],
48+
visibility = ["//score/test:__subpackages__"],
4949
deps = [
5050
":datarouter_bin_pkg",
5151
":datarouter_conf_pkg",
@@ -71,5 +71,5 @@ py_itf_plugin(
7171
],
7272
py_library = ":logging_plugin_lib",
7373
target_compatible_with = ["@platforms//os:linux"],
74-
visibility = ["//score/test/component:__subpackages__"],
74+
visibility = ["//score/test:__subpackages__"],
7575
)

score/test/component/dlt_generator_app/BUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pkg_tar(
4646

4747
pkg_tar(
4848
name = "dlt_generator_filesystem",
49-
visibility = ["//score/test/component:__subpackages__"],
49+
visibility = ["//score/test:__subpackages__"],
5050
deps = [
5151
":dlt_generator_bin_pkg",
5252
":dlt_generator_config_pkg",

score/test/component/logging_plugin.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,38 @@ def _wait_for_datarouter(target, timeout=_DATAROUTER_READY_TIMEOUT):
5454
raise TimeoutError(f"Datarouter socket not found within {timeout}s")
5555

5656

57+
class _DatarouterManager:
58+
"""Gives tests explicit start/stop control over DataRouter."""
59+
60+
def __init__(self, target):
61+
self._target = target
62+
self._proc = None
63+
64+
def start(self):
65+
"""Start DataRouter and wait until it is ready."""
66+
self._proc = self._target.execute_async(
67+
"/opt/datarouter/bin/datarouter",
68+
args=["--no_adaptive_runtime"],
69+
cwd="/opt/datarouter",
70+
)
71+
_wait_for_datarouter(self._target)
72+
73+
def stop(self):
74+
"""Stop DataRouter. Safe to call even if start() was never called."""
75+
if self._proc is not None and self._proc.is_running():
76+
self._proc.stop()
77+
78+
79+
@pytest.fixture(scope="function")
80+
def datarouter_manager(target):
81+
"""Like datarouter_on_target but DataRouter is NOT started automatically."""
82+
manager = _DatarouterManager(target)
83+
try:
84+
yield manager
85+
finally:
86+
manager.stop()
87+
88+
5789
def download_dlt(target, remote_path):
5890
"""Download a .dlt file from the target and return a DltLogRecord for querying.
5991

score/test/integration/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
load("//score/test/component:defs.bzl", "py_logging_itf_test")
15+
16+
py_logging_itf_test(
17+
name = "test_datarouter_scenarios",
18+
srcs = ["test_datarouter_scenarios.py"],
19+
filesystem = "//score/test/component/dlt_generator_app:dlt_generator_filesystem",
20+
)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
"""DataRouter robustness tests: detached-app logging and delayed DR start."""
15+
16+
import logging
17+
import time
18+
19+
from logging_plugin import download_dlt
20+
21+
LOGGER = logging.getLogger(__name__)
22+
23+
APP_ID = "LGGG"
24+
DEFAULT_MESSAGE = "default message text for example log generating application"
25+
26+
_DETACHED_FLUSH_WAIT_S = 5
27+
_DR_START_DELAY_S = 2
28+
_DR_FLUSH_WAIT_S = 5
29+
_APP_HOLD_AFTER_LOG_MS = 8000
30+
31+
32+
def test_logging_detached_logs(target, datarouter_on_target, dlt_capture):
33+
"""DataRouter must recover logs from an app that exits before DR syncs."""
34+
with dlt_capture() as receiver:
35+
target.execute(
36+
"cd /opt/test_apps/dlt_generator && ./bin/dlt_generator"
37+
" -i 10 -s 0 -f true -w 0"
38+
)
39+
time.sleep(_DETACHED_FLUSH_WAIT_S)
40+
41+
record = download_dlt(target, receiver.dlt_file)
42+
messages = record.find(query=dict(apid=APP_ID))
43+
LOGGER.info("Received %d messages from detached app", len(messages))
44+
45+
assert len(messages) > 0, "DataRouter failed to recover detached app logs"
46+
payloads = "\n".join(str(m.payload) for m in messages)
47+
assert DEFAULT_MESSAGE in payloads, "Expected log content not found"
48+
49+
50+
def test_logging_after_delayed_dr_start(target, datarouter_manager, dlt_capture):
51+
"""Messages buffered in shared memory must not be lost when DR starts late."""
52+
with dlt_capture() as receiver:
53+
proc = target.execute_async(
54+
"/opt/test_apps/dlt_generator/bin/dlt_generator",
55+
args=[
56+
"-i",
57+
"10",
58+
"-s",
59+
"0",
60+
"-f",
61+
"true",
62+
"-w",
63+
str(_APP_HOLD_AFTER_LOG_MS),
64+
],
65+
cwd="/opt/test_apps/dlt_generator",
66+
)
67+
time.sleep(_DR_START_DELAY_S)
68+
datarouter_manager.start()
69+
proc.wait(timeout_s=30)
70+
time.sleep(_DR_FLUSH_WAIT_S)
71+
72+
record = download_dlt(target, receiver.dlt_file)
73+
messages = record.find(query=dict(apid=APP_ID))
74+
LOGGER.info("Received %d messages after delayed DR start", len(messages))
75+
76+
assert len(messages) > 0, "Messages logged before DR started were lost"
77+
payloads = "\n".join(str(m.payload) for m in messages)
78+
assert DEFAULT_MESSAGE in payloads, "Expected log content not found"

0 commit comments

Comments
 (0)