Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
],
// Add your personal customizations
"onCreateCommand": {
"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",
"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",
"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"
},

Expand Down
17 changes: 10 additions & 7 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ on:
types: [checks_requested]
jobs:
test:
name: "Run tests"
uses: eclipse-score/cicd-workflows/.github/workflows/tests.yml@main
permissions:
contents: read
pull-requests: read
with:
bazel-target: 'test //src/...'
steps:
- name: Install fakechroot
run: sudo apt install -y fakechroot
- name: Run tests
uses: eclipse-score/cicd-workflows/.github/workflows/tests.yml@main
permissions:
contents: read
pull-requests: read
with:
bazel-target: 'test //src/... //tests/integration/...'
8 changes: 8 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ python.toolchain(
)
use_repo(python)

pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip", dev_dependency = True)
pip.parse(
hub_name = "pip_score_venv_test",
python_version = PYTHON_VERSION,
requirements_lock = "//tests/integration:requirements.lock",
)
use_repo(pip, "pip_score_venv_test")

use_repo(toolchains_qnx, "toolchains_qnx_sdp")
use_repo(toolchains_qnx, "toolchains_qnx_qcc")
use_repo(toolchains_qnx, "toolchains_qnx_ifs")
Expand Down
77 changes: 77 additions & 0 deletions config/flatbuffers_rules.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
def _flatbuffer_json_to_bin_impl(ctx):
flatc = ctx.executable.flatc
json = ctx.file.json
schema = ctx.file.schema

# flatc will name the file the same as the json (can't be changed)
out_name = json.basename[:-len(".json")] + ".bin"
out = ctx.actions.declare_file(out_name, sibling = json)

# flatc args ---------------------------------
flatc_args = [
"-b",
"-o",
out.dirname,
]

for inc in ctx.attr.includes:
flatc_args.extend(["-I", inc.path])

if ctx.attr.strict_json:
flatc_args.append("--strict-json")

flatc_args.extend([schema.path, json.path])
# --------------------------------------------

ctx.actions.run(
inputs = [json, schema] + list(ctx.files.includes),
outputs = [out],
executable = flatc,
arguments = flatc_args,
progress_message = "flatc generation {}".format(json.short_path),
mnemonic = "FlatcGeneration",
)

rf = ctx.runfiles(
files = [out],
root_symlinks = {
("_main/" + ctx.attr.out_dir + "/" + out_name): out,
},
)

return DefaultInfo(files = depset([out]), runfiles = rf)

flatbuffer_json_to_bin = rule(
implementation = _flatbuffer_json_to_bin_impl,
attrs = {
"json": attr.label(
allow_single_file = [".json"],
mandatory = True,
doc = "Json file to convert. Note that the binary file will have the same name as the json (minus the suffix)",
),
"schema": attr.label(
allow_single_file = [".fbs"],
mandatory = True,
doc = "FBS file to use",
),
"out_dir": attr.string(
default = "etc",
doc = "Directory to copy the generated file to, sibling to 'src' and 'tests' dirs. Do not include a trailing '/'",
),
"flatc": attr.label(
default = Label("@flatbuffers//:flatc"),
executable = True,
cfg = "exec",
doc = "Reference to the flatc binary",
),
# flatc arguments
"includes": attr.label_list(
allow_files = True,
doc = "Flatc include paths",
),
"strict_json": attr.bool(
default = False,
doc = "Require strict JSON (no trailing commas etc)",
),
},
)
2 changes: 2 additions & 0 deletions src/launch_manager_daemon/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# *******************************************************************************
load("//config:common_cc.bzl", "cc_binary_with_common_opts", "cc_library_with_common_opts")

exports_files(["config/lm_flatcfg.fbs"])

cc_library(
name = "config",
hdrs = ["config/lm_flatcfg_generated.h"],
Expand Down
2 changes: 2 additions & 0 deletions src/launch_manager_daemon/health_monitor_lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
load("//config:common_cc.bzl", "cc_binary_with_common_opts", "cc_library_with_common_opts")

# flatcfg configuration
exports_files(["config/hm_flatcfg.fbs"])

cc_library(
name = "config",
hdrs = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ bool HealthMonitorThread::start() {

waitForInitializationCompleted(init_status);

return (init_status == score::lcm::saf::daemon::EInitCode::kNoError);
return init_status == saf::daemon::EInitCode::kNoError;
}

void HealthMonitorThread::stop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ void ProcessGroupManager::setLaunchManagerConfiguration(const OsProcess* launch_
}

bool ProcessGroupManager::initialize() {
bool success = false;

// setup signal handler
em_cancelled.store(false);
// RULECHECKER_comment(1, 1, check_union_object, "Union type defined in external library is used.", true)
Expand All @@ -86,22 +84,24 @@ bool ProcessGroupManager::initialize() {
sigaction(SIGUSR2, &action, NULL);
sigaction(SIGVTALRM, &action, NULL);

success = initializeControlClientHandler() && initializeProcessGroups();
if (!initializeControlClientHandler() || !initializeProcessGroups()) {
return false;
}

if (success) {
LM_LOG_DEBUG() << "Process Group initialization done";
createProcessComponentsObjects();
initializeGraphNodes();
//success = ucm_polling_thread_.startPolling();
success = health_monitor_thread_->start();
LM_LOG_DEBUG() << "Process Group initialization done";
createProcessComponentsObjects();
initializeGraphNodes();
if (!health_monitor_thread_->start()) {
LM_LOG_ERROR() << "Health monitor thread failed to start";
return false;
}

if (success && launch_manager_config_ &&
if (launch_manager_config_ &&
OsalReturnType::kFail == IProcess::setSchedulingAndSecurity(launch_manager_config_->startup_config_)) {
success = false;
return false;
}

return success;
return true;
}

void ProcessGroupManager::deinitialize() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ OsalReturnType IProcess::setSchedulingAndSecurity(const OsalConfig& config) {
size_t supplementary_gids_number = config.supplementary_gids_.size();

// Note: the type of the first parameter of setgroups() differs in Linux and QNX, so we use osal
if (-1 == osal::setgroups(supplementary_gids_number, config.supplementary_gids_.data())) {
if (supplementary_gids_number > 0 && -1 == osal::setgroups(supplementary_gids_number, config.supplementary_gids_.data())) {
LM_LOG_ERROR() << "setgroups() failed:" << std::strerror(errno);
retval = OsalReturnType::kFail;
}
Expand All @@ -354,6 +354,7 @@ inline void IProcess::handleChildProcess(ChildProcessConfig& param) {
if (OsalReturnType::kSuccess != setSchedulingAndSecurity(*param.config)) {
sysexit(EXIT_FAILURE);
}

changeCurrentWorkingDirectory(*param.config);
implementMemoryResourceLimits(*param.config);
changeSecurityPolicy(*param.config);
Expand Down
63 changes: 63 additions & 0 deletions tests/integration/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
load("@pip_score_venv_test//:requirements.bzl", "all_requirements")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("@score_tooling//python_basics:defs.bzl", "score_py_pytest", "score_virtualenv")

# In order to update the requirements, change the `requirements.txt` file and run:
# `bazel run //tests/integration:requirements.update`.
# This will update the `requirements.lock` file.
# To upgrade all dependencies to their latest versions, run:
# `bazel run //tests/integration:requirements.update -- --upgrade`.
compile_pip_requirements(
name = "requirements",
srcs = [
"requirements.txt",
"@score_tooling//python_basics:requirements.txt",
],
extra_args = [
"--no-annotate",
],
requirements_txt = "requirements.lock",
tags = [
"manual",
],
)

score_virtualenv(
name = "python_tc_venv",
reqs = all_requirements,
venv_name = ".python_tc_venv",
)

cc_library(
name = "test_helper",
hdrs = ["test_helper.hpp"],
visibility = ["//tests:__subpackages__"],
deps = [
"@googletest//:gtest_main",
],
)

py_library(
name = "control_interface",
srcs = ["control_interface.py"],
visibility = ["//tests:__subpackages__"],
)

py_library(
name = "testing_utils",
srcs = ["testing_utils.py"],
visibility = ["//tests:__subpackages__"],
deps = [":control_interface"],
)
58 changes: 58 additions & 0 deletions tests/integration/control_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
from typing import Tuple
from pathlib import Path
from abc import ABC, abstractmethod


class ControlInterface(ABC):
"""Platform independent interface to execute commands on the target"""

@abstractmethod
def exec_command_blocking(
*args: str, timeout=1, **env: str
) -> Tuple[int, str, str]:
"""Execute a command on the target

Args:
*args (str): Command to run with arguments
timeout (int): Time in seconds to exit after, returning status -1
**env (str): Environment vars to set

Returns:
(int, str, str): exit_status, stdout, stderr
"""
raise NotImplementedError()

@abstractmethod
def run_until_file_deployed(
*args,
timeout=1,
file_path=Path("tests/integration/test_end"),
poll_interval=0.05,
**env,
) -> Tuple[int, str, str]:
"""Launch a process and terminate it once a given file has been deployed

Args:

*args (str): Command to run with arguments
timeout (int): Time in seconds to exit after, returning status -1
file_path (Path): File to wait for
poll_interval (float): How often, in seconds, to check if we should terminate the process
**env (str): Environment vars to set

Returns:
(int, str, str): exit_status, stdout, stderr
"""
raise NotImplementedError()
12 changes: 12 additions & 0 deletions tests/integration/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Local integration testing

## Prerequisites
- fakechroot must be installed to run these tests
- `sudo apt install fakechroot`

## Running the tests

To run all tests, simply run `bazel test //tests/integration/...`

## Running a single test
You can run a single integration test locally using `bazel test //tests/integration/<test name>`
31 changes: 31 additions & 0 deletions tests/integration/requirements.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# bazel run //tests/integration:requirements.update
#
basedpyright==1.29.2 \
--hash=sha256:12c49186003b9f69a028615da883ef97035ea2119a9e3f93a00091b3a27088a6 \
--hash=sha256:f389e2997de33d038c5065fd85bff351fbdc62fa6d6371c7b947fc3bce8d437d
iniconfig==2.1.0 \
--hash=sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7 \
--hash=sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760
nodejs-wheel-binaries==22.16.0 \
--hash=sha256:2728972d336d436d39ee45988978d8b5d963509e06f063e80fe41b203ee80b28 \
--hash=sha256:2fffb4bf1066fb5f660da20819d754f1b424bca1b234ba0f4fa901c52e3975fb \
--hash=sha256:447ad796850eb52ca20356ad39b2d296ed8fef3f214921f84a1ccdad49f2eba1 \
--hash=sha256:4ae3cf22138891cb44c3ee952862a257ce082b098b29024d7175684a9a77b0c0 \
--hash=sha256:71f2de4dc0b64ae43e146897ce811f80ac4f9acfbae6ccf814226282bf4ef174 \
--hash=sha256:7f526ca6a132b0caf633566a2a78c6985fe92857e7bfdb37380f76205a10b808 \
--hash=sha256:986b715a96ed703f8ce0c15712f76fc42895cf09067d72b6ef29e8b334eccf64 \
--hash=sha256:d695832f026df3a0cf9a089d222225939de9d1b67f8f0a353b79f015aabbe7e2 \
--hash=sha256:dbfccbcd558d2f142ccf66d8c3a098022bf4436db9525b5b8d32169ce185d99e
packaging==25.0 \
--hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \
--hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f
pluggy==1.6.0 \
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
pytest==8.3.5 \
--hash=sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820 \
--hash=sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845
1 change: 1 addition & 0 deletions tests/integration/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest
Loading
Loading