Files
slocker-lite/tests/support/fixtures.h
T
ceamac 4dd0f462a5 Wire -c/--config-file's effective config into the self-test suite
run_self_tests() now takes the same effective AppConfig any other command
gets and stashes it into a new g_test_app_config global (tests/support/
fixtures.h) before Catch2 runs anything. test_rootless_run.cpp's own
run_in_fixture() reads a copy of it instead of a hardcoded default
AppConfig{}, so -c actually reaches that test's container creation.

Verified: a config with every unshare-*/with-* key set to false, used via
-c <file> -t -- "[integration][net]~[root]", flips all 3 of that file's
container-creating tests to failing -- including the nohup-straggler
regression test, since with neither a pid namespace nor a cgroup nothing
reaps the backgrounded process -- while [unit] and non-networking
[integration] tests are completely unaffected, as expected.
2026-09-05 10:02:12 +00:00

93 lines
4.0 KiB
C++

// Copyright (C) 2026 Viorel Munteanu
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#pragma once
#include <filesystem>
#include <optional>
#include <string>
#include "config_file.h"
// The effective AppConfig for the current -t/--test run -- set once by
// run_self_tests() (self_test.cpp) from whatever main() resolved (respecting
// -c/--config-file, same as any other command), before Catch2 ever runs a
// TEST_CASE. Test code that creates a real container (test_rootless_run.cpp's
// own run_in_fixture()) reads this instead of hardcoding a fresh, default
// AppConfig{}, so e.g. `-c <all-unshare-off.yaml> -t -- "[integration][net]"`
// actually exercises what happens with pid/cgroup isolation disabled. Plain
// default-constructed AppConfig{} otherwise (matching every test's prior,
// unconditional behavior) -- a bare `-t` with no `-c` and no real config file
// changes nothing.
extern AppConfig g_test_app_config;
// Path to a real, runnable OCI Image Layout tar (something with an actual
// /bin/sh, unlike tests/gen_fixture.py's minimal single-file fixture used
// by the plain mount/unmount smoke test) for [integration][net] tests that
// need to actually run a command inside a container. Searches
// images/busybox.tar relative to the current working directory -- this
// project's own established manual-testing convention (see images/ at the
// repo root, gitignored). nullopt if not found; callers should SKIP()
// rather than fail, since fetching one is optional -- see
// tests/setup-tests.py.
std::optional<std::filesystem::path> find_busybox_fixture();
// RAII scratch XDG_CONFIG_HOME/XDG_STATE_HOME: for its lifetime, both env
// vars point at a fresh throwaway directory under /tmp, so
// config_file_path()/xdg_state_dir() (config_file.cpp/pid_file.cpp)
// resolve entirely under it instead of the real developer's own $HOME --
// integration tests that actually mount/run something must never touch
// real config/state. Restores whatever the two env vars were before (unset
// if they were unset) and removes the scratch directory on destruction.
class ScratchXdgDirs {
public:
ScratchXdgDirs();
~ScratchXdgDirs();
ScratchXdgDirs(const ScratchXdgDirs&) = delete;
ScratchXdgDirs& operator=(const ScratchXdgDirs&) = delete;
const std::filesystem::path& path() const { return path_; }
private:
std::filesystem::path path_;
std::optional<std::string> previous_config_home_;
std::optional<std::string> previous_state_home_;
};
// RAII stdout capture: for its lifetime, this process's own fd 1 (and
// anything a forked/exec'd child -- e.g. the real bwrap-sandboxed command,
// via dispatch_command()'s ordinary fork/exec chain -- inherits from it) is
// redirected to a throwaway temp file instead of the real terminal/pipe.
// contents() flushes C stdio first (so any of *this* process's own
// buffered writes land in the file before being read back) and returns
// everything captured so far; the destructor restores the original fd 1
// and removes the temp file. Kept narrowly scoped around just the call
// under test, so Catch2's own console reporter output is never captured
// by mistake.
class CapturedStdout {
public:
CapturedStdout();
~CapturedStdout();
CapturedStdout(const CapturedStdout&) = delete;
CapturedStdout& operator=(const CapturedStdout&) = delete;
std::string contents();
private:
int saved_fd_ = -1;
std::filesystem::path temp_path_;
};