Skip to content

Commit cd6a17e

Browse files
System test execution setup
- Local execution - Launching LM daemon with a config - GTEST processes launched by LM with test results parsed - Test timeout - Scaffolding for platform independent python scripts - Running LM without root - setgroups() is not attempted if there are no supplementary group ids - Minor cleanup in ProcessGroupManager::initialize()
1 parent f3ae1bc commit cd6a17e

22 files changed

Lines changed: 882 additions & 22 deletions

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
],
3030
// Add your personal customizations
3131
"onCreateCommand": {
32-
"update certificates & install dependencies": "sudo apt update && sudo apt install -y --no-install-recommends ca-certificates-java openjdk-17-jre-headless libacl1-dev tmux && sudo update-ca-certificates",
32+
"update certificates & install dependencies": "sudo apt update && sudo apt install -y --no-install-recommends ca-certificates-java openjdk-17-jre-headless libacl1-dev tmux fakechroot && sudo update-ca-certificates",
3333
"bazel use system trust store": "echo 'startup --host_jvm_args=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit' | sudo tee --append /etc/bazel.bazelrc"
3434
},
3535

.github/workflows/tests.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ on:
1919
types: [checks_requested]
2020
jobs:
2121
test:
22-
name: "Run tests"
23-
uses: eclipse-score/cicd-workflows/.github/workflows/tests.yml@main
24-
permissions:
25-
contents: read
26-
pull-requests: read
27-
with:
28-
bazel-target: 'test //src/...'
22+
steps:
23+
- name: Install fakechroot
24+
run: sudo apt install -y fakechroot
25+
- name: Run tests
26+
uses: eclipse-score/cicd-workflows/.github/workflows/tests.yml@main
27+
permissions:
28+
contents: read
29+
pull-requests: read
30+
with:
31+
bazel-target: 'test //src/... //tests/integration/...'

MODULE.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ python.toolchain(
9999
)
100100
use_repo(python)
101101

102+
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip", dev_dependency = True)
103+
pip.parse(
104+
hub_name = "pip_score_venv_test",
105+
python_version = PYTHON_VERSION,
106+
requirements_lock = "//tests/integration:requirements.lock",
107+
)
108+
use_repo(pip, "pip_score_venv_test")
109+
102110
use_repo(toolchains_qnx, "toolchains_qnx_sdp")
103111
use_repo(toolchains_qnx, "toolchains_qnx_qcc")
104112
use_repo(toolchains_qnx, "toolchains_qnx_ifs")

config/flatbuffers_rules.bzl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
def _flatbuffer_json_to_bin_impl(ctx):
2+
flatc = ctx.executable.flatc
3+
json = ctx.file.json
4+
schema = ctx.file.schema
5+
6+
# flatc will name the file the same as the json (can't be changed)
7+
out_name = json.basename[:-len(".json")] + ".bin"
8+
out = ctx.actions.declare_file(out_name, sibling = json)
9+
10+
# flatc args ---------------------------------
11+
flatc_args = [
12+
"-b",
13+
"-o",
14+
out.dirname,
15+
]
16+
17+
for inc in ctx.attr.includes:
18+
flatc_args.extend(["-I", inc.path])
19+
20+
if ctx.attr.strict_json:
21+
flatc_args.append("--strict-json")
22+
23+
flatc_args.extend([schema.path, json.path])
24+
# --------------------------------------------
25+
26+
ctx.actions.run(
27+
inputs = [json, schema] + list(ctx.files.includes),
28+
outputs = [out],
29+
executable = flatc,
30+
arguments = flatc_args,
31+
progress_message = "flatc generation {}".format(json.short_path),
32+
mnemonic = "FlatcGeneration",
33+
)
34+
35+
rf = ctx.runfiles(
36+
files = [out],
37+
root_symlinks = {
38+
("_main/" + ctx.attr.out_dir + "/" + out_name): out,
39+
},
40+
)
41+
42+
return DefaultInfo(files = depset([out]), runfiles = rf)
43+
44+
flatbuffer_json_to_bin = rule(
45+
implementation = _flatbuffer_json_to_bin_impl,
46+
attrs = {
47+
"json": attr.label(
48+
allow_single_file = [".json"],
49+
mandatory = True,
50+
doc = "Json file to convert. Note that the binary file will have the same name as the json (minus the suffix)",
51+
),
52+
"schema": attr.label(
53+
allow_single_file = [".fbs"],
54+
mandatory = True,
55+
doc = "FBS file to use",
56+
),
57+
"out_dir": attr.string(
58+
default = "etc",
59+
doc = "Directory to copy the generated file to, sibling to 'src' and 'tests' dirs. Do not include a trailing '/'",
60+
),
61+
"flatc": attr.label(
62+
default = Label("@flatbuffers//:flatc"),
63+
executable = True,
64+
cfg = "exec",
65+
doc = "Reference to the flatc binary",
66+
),
67+
# flatc arguments
68+
"includes": attr.label_list(
69+
allow_files = True,
70+
doc = "Flatc include paths",
71+
),
72+
"strict_json": attr.bool(
73+
default = False,
74+
doc = "Require strict JSON (no trailing commas etc)",
75+
),
76+
},
77+
)

src/launch_manager_daemon/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
load("//config:common_cc.bzl", "cc_binary_with_common_opts", "cc_library_with_common_opts")
1414

1515
package(default_visibility = ["//tests:__subpackages__"])
16+
exports_files(["config/lm_flatcfg.fbs"])
1617

1718
cc_library(
1819
name = "config",

src/launch_manager_daemon/health_monitor_lib/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
load("//config:common_cc.bzl", "cc_binary_with_common_opts", "cc_library_with_common_opts")
1414

1515
# flatcfg configuration
16+
exports_files(["config/hm_flatcfg.fbs"])
17+
1618
cc_library(
1719
name = "config",
1820
hdrs = [

src/launch_manager_daemon/src/process_group_manager/health_monitor_thread.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ bool HealthMonitorThread::start() {
3737

3838
waitForInitializationCompleted(init_status);
3939

40-
return (init_status == score::lcm::saf::daemon::EInitCode::kNoError);
40+
return init_status == saf::daemon::EInitCode::kNoError;
4141
}
4242

4343
void HealthMonitorThread::stop() {

src/launch_manager_daemon/src/process_group_manager/processgroupmanager.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ void ProcessGroupManager::setLaunchManagerConfiguration(const OsProcess* launch_
6565
}
6666

6767
bool ProcessGroupManager::initialize() {
68-
bool success = false;
69-
7068
// setup signal handler
7169
em_cancelled.store(false);
7270
// RULECHECKER_comment(1, 1, check_union_object, "Union type defined in external library is used.", true)
@@ -86,22 +84,24 @@ bool ProcessGroupManager::initialize() {
8684
sigaction(SIGUSR2, &action, NULL);
8785
sigaction(SIGVTALRM, &action, NULL);
8886

89-
success = initializeControlClientHandler() && initializeProcessGroups();
87+
if (!initializeControlClientHandler() || !initializeProcessGroups()) {
88+
return false;
89+
}
9090

91-
if (success) {
92-
LM_LOG_DEBUG() << "Process Group initialization done";
93-
createProcessComponentsObjects();
94-
initializeGraphNodes();
95-
//success = ucm_polling_thread_.startPolling();
96-
success = health_monitor_thread_->start();
91+
LM_LOG_DEBUG() << "Process Group initialization done";
92+
createProcessComponentsObjects();
93+
initializeGraphNodes();
94+
if (!health_monitor_thread_->start()) {
95+
LM_LOG_ERROR() << "Health monitor thread failed to start";
96+
return false;
9797
}
9898

99-
if (success && launch_manager_config_ &&
99+
if (launch_manager_config_ &&
100100
OsalReturnType::kFail == IProcess::setSchedulingAndSecurity(launch_manager_config_->startup_config_)) {
101-
success = false;
101+
return false;
102102
}
103103

104-
return success;
104+
return true;
105105
}
106106

107107
void ProcessGroupManager::deinitialize() {

src/launch_manager_daemon/src/process_group_manager/processlauncher.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ OsalReturnType IProcess::setSchedulingAndSecurity(const OsalConfig& config) {
334334
size_t supplementary_gids_number = config.supplementary_gids_.size();
335335

336336
// Note: the type of the first parameter of setgroups() differs in Linux and QNX, so we use osal
337-
if (-1 == osal::setgroups(supplementary_gids_number, config.supplementary_gids_.data())) {
337+
if (supplementary_gids_number > 0 && -1 == osal::setgroups(supplementary_gids_number, config.supplementary_gids_.data())) {
338338
LM_LOG_ERROR() << "setgroups() failed:" << std::strerror(errno);
339339
retval = OsalReturnType::kFail;
340340
}
@@ -354,6 +354,7 @@ inline void IProcess::handleChildProcess(ChildProcessConfig& param) {
354354
if (OsalReturnType::kSuccess != setSchedulingAndSecurity(*param.config)) {
355355
sysexit(EXIT_FAILURE);
356356
}
357+
357358
changeCurrentWorkingDirectory(*param.config);
358359
implementMemoryResourceLimits(*param.config);
359360
changeSecurityPolicy(*param.config);

tests/integration/BUILD

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 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+
load("@pip_score_venv_test//:requirements.bzl", "all_requirements")
14+
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
15+
load("@score_tooling//python_basics:defs.bzl", "score_py_pytest", "score_virtualenv")
16+
17+
# In order to update the requirements, change the `requirements.txt` file and run:
18+
# `bazel run //tests/integration:requirements.update`.
19+
# This will update the `requirements.lock` file.
20+
# To upgrade all dependencies to their latest versions, run:
21+
# `bazel run //tests/integration:requirements.update -- --upgrade`.
22+
compile_pip_requirements(
23+
name = "requirements",
24+
srcs = [
25+
"requirements.txt",
26+
"@score_tooling//python_basics:requirements.txt",
27+
],
28+
extra_args = [
29+
"--no-annotate",
30+
],
31+
requirements_txt = "requirements.lock",
32+
tags = [
33+
"manual",
34+
],
35+
)
36+
37+
score_virtualenv(
38+
name = "python_tc_venv",
39+
reqs = all_requirements,
40+
venv_name = ".python_tc_venv",
41+
)
42+
43+
cc_library(
44+
name = "test_helper",
45+
hdrs = ["test_helper.hpp"],
46+
visibility = ["//tests:__subpackages__"],
47+
deps = [
48+
"@googletest//:gtest_main",
49+
],
50+
)
51+
52+
py_library(
53+
name = "control_interface",
54+
srcs = ["control_interface.py"],
55+
visibility = ["//tests:__subpackages__"],
56+
)
57+
58+
py_library(
59+
name = "testing_utils",
60+
srcs = ["testing_utils.py"],
61+
visibility = ["//tests:__subpackages__"],
62+
deps = [":control_interface"],
63+
)

0 commit comments

Comments
 (0)