Skip to content
Merged
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
11 changes: 11 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# .config/nextest.toml
[profile.default]
# Kill any test once it crosses 60s.
slow-timeout = { period = "60s", terminate-after = 1, grace-period = "5s" }

# Put a hard ceiling on the whole run.
global-timeout = "10m"

# Exclude cucumber BDD tests (they don't support nextest's --list command).
# Run cucumber tests separately with `cargo test`.
default-filter = "not binary(cucumber)"
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ jobs:
- uses: actions/checkout@v5
- name: Setup Rust
uses: leynos/shared-actions/.github/actions/setup-rust@f9f1c863c8a5bef64aa6779caa746e1a4a6c1ad4
- name: Install nextest
uses: taiki-e/install-action@db22c42b5af88356329b9a8056bb2c2f026d5a10
with:
tool: nextest@0.9.114
- name: Format
run: make check-fmt
- name: Lint
Expand Down
18 changes: 14 additions & 4 deletions .markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
{
"config": {
"MD004": { "style": "dash" },
"MD010": { "code_blocks": false },
"MD013": {
"line_length": 80,
"code_block_line_length": 120,
"tables": false
"tables": false,
"headings": false
},
"MD029": { "style": "ordered" },
"MD040": { "code_blocks": true }
}
"MD029": { "style": "ordered" }
},
"ignores": [
"**/.venv/**",
"**/node_modules/**",
"**/target/**",
"**/.terraform/**",
"**/.uv-cache/**",
"CRUSH.md"
]
}
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 10 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
APP ?= comenq
CARGO ?= cargo
BUILD_JOBS ?=
CLIPPY_FLAGS ?= --all-targets --all-features -- -D warnings
MDLINT ?= markdownlint
CLIPPY_FLAGS ?= --workspace --all-targets --all-features -- -D warnings
MDLINT ?= markdownlint-cli2
NIXIE ?= nixie
COV_MIN ?= 0 # Minimum line coverage percentage for coverage targets

Expand Down Expand Up @@ -34,16 +34,19 @@ clean: ## Remove build artefacts
rm -rf coverage

test: ## Run tests with warnings treated as errors
RUSTFLAGS="-D warnings" $(CARGO) test --all-targets --all-features $(BUILD_JOBS)
RUSTFLAGS="-D warnings" $(CARGO) nextest run --workspace --all-targets --all-features $(BUILD_JOBS)
RUSTFLAGS="-D warnings" $(CARGO) test --workspace --all-features --test cucumber $(BUILD_JOBS)

test-cov: ## Run workspace-wide tests with coverage; set COV_MIN to enforce a threshold
$(CHECK_CARGO_LLVM_COV)
RUSTFLAGS="-D warnings" $(CARGO) llvm-cov --workspace --all-features --doctests --summary-only --text --fail-under-lines $(COV_MIN) $(BUILD_JOBS)
RUSTFLAGS="-D warnings" $(CARGO) llvm-cov nextest --workspace --all-features --summary-only --text --fail-under-lines $(COV_MIN) $(BUILD_JOBS)
RUSTFLAGS="-D warnings" $(CARGO) llvm-cov --no-clean --workspace --all-features --test cucumber --summary-only --text --fail-under-lines $(COV_MIN) $(BUILD_JOBS)

test-cov-lcov: ## Run workspace-wide tests with coverage and write LCOV to coverage/lcov.info
$(CHECK_CARGO_LLVM_COV)
mkdir -p coverage
RUSTFLAGS="-D warnings" $(CARGO) llvm-cov --workspace --all-features --doctests --lcov --output-path coverage/lcov.info --fail-under-lines $(COV_MIN) $(BUILD_JOBS)
RUSTFLAGS="-D warnings" $(CARGO) llvm-cov nextest --workspace --all-features --lcov --output-path coverage/lcov.info --fail-under-lines $(COV_MIN) $(BUILD_JOBS)
RUSTFLAGS="-D warnings" $(CARGO) llvm-cov --no-clean --workspace --all-features --test cucumber --lcov --output-path coverage/lcov-cucumber.info --fail-under-lines $(COV_MIN) $(BUILD_JOBS)

target/%/$(APP): ## Build binary in debug or release mode
$(CARGO) build $(BUILD_JOBS) $(if $(findstring release,$(@)),--release) --bin $(APP)
Expand All @@ -59,10 +62,10 @@ check-fmt: ## Verify formatting
$(CARGO) fmt --all -- --check

markdownlint: ## Lint Markdown files
find . -type f -name '*.md' -not -path './target/*' -print0 | xargs -0 $(MDLINT)
$(MDLINT) "**/*.md"
Comment thread
leynos marked this conversation as resolved.

nixie: ## Validate Mermaid diagrams
find . -type f -name '*.md' -not -path './target/*' -print0 | xargs -0 $(NIXIE)
$(NIXIE) --no-sandbox "**/*.md"

help: ## Show available targets
@grep -E '^[a-zA-Z_-]+:.*?##' $(MAKEFILE_LIST) | \
Expand Down
6 changes: 3 additions & 3 deletions crates/comenqd/src/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::supervisor::backoff;
/// # Examples
///
/// ```rust,no_run
/// use comenqd::listener::prepare_listener;
/// use comenqd::daemon::listener::prepare_listener;
/// use tempfile::tempdir;
/// let dir = tempdir().expect("create tempdir");
/// let sock = dir.path().join("sock");
Expand Down Expand Up @@ -169,8 +169,8 @@ mod tests {
use std::thread;
use tempfile::tempdir;

#[test]
fn prepare_listener_prevents_pre_bind_race() {
#[tokio::test]
async fn prepare_listener_prevents_pre_bind_race() {
let dir = tempdir().expect("create tempdir");
let sock = dir.path().join("sock");
let stop = Arc::new(AtomicBool::new(false));
Expand Down
29 changes: 13 additions & 16 deletions crates/comenqd/src/logging.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
//! Logging utilities for the daemon.
//!
//! Initializes structured logging using `tracing` and
//! Initialises structured logging using `tracing` and
//! `tracing-subscriber`, reading filter settings from the `RUST_LOG`
//! environment variable.

use tracing_subscriber::fmt::MakeWriter;
use tracing_subscriber::{EnvFilter, fmt};

/// Initialize the global tracing subscriber.
/// Initialise the global tracing subscriber.
///
/// Call `init` before any logging statements to avoid missing logs.
///
/// # Examples
///
/// ```rust,no_run
/// use crate::logging::init;
/// use comenqd::logging::init;
///
/// fn main() {
/// // Initialize logging as early as possible.
/// init();
/// tracing::info!("Logging is initialized!");
/// }
/// // Initialise logging as early as possible.
/// init();
/// tracing::info!("Logging is initialised!");
/// ```
pub fn init() {
init_with_writer(fmt::writer::BoxMakeWriter::new(std::io::stdout));
}

/// Initialize logging with a custom writer.
/// Initialise logging with a custom writer.
///
/// # Examples
///
/// ```rust,no_run
/// use crate::logging::init_with_writer;
/// use comenqd::logging::init_with_writer;
/// use tracing_subscriber::fmt;
///
/// fn main() {
/// init_with_writer(fmt::writer::BoxMakeWriter::new(std::io::stdout));
/// }
/// init_with_writer(fmt::writer::BoxMakeWriter::new(std::io::stdout));
/// ```
pub fn init_with_writer<W>(writer: W)
where
Expand All @@ -50,9 +46,10 @@ where

#[cfg(test)]
mod tests {
use super::*;
use std::sync::{Arc, Mutex};
use test_support::logging::init_with_writer_and_filter;
use tracing::info;
use tracing_subscriber::fmt::MakeWriter;

#[derive(Clone)]
struct BufMakeWriter {
Expand Down Expand Up @@ -90,8 +87,8 @@ mod tests {
#[test]
fn init_logging() {
let buf = Arc::new(Mutex::new(Vec::new()));
unsafe { std::env::set_var("RUST_LOG", "info") };
init_with_writer(BufMakeWriter { buf: buf.clone() });
// Use explicit filter to avoid environment mutation (forbidden per coding guidelines)
init_with_writer_and_filter(BufMakeWriter { buf: buf.clone() }, "info");
info!("captured");
let output = String::from_utf8(buf.lock().expect("Failed to lock log buffer").clone())
.expect("Captured output is not valid UTF-8");
Expand Down
5 changes: 4 additions & 1 deletion crates/comenqd/src/supervisor/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ fn create_cancelled_join_error() -> JoinError {
tokio::runtime::Runtime::new()
.expect("create runtime")
.block_on(async {
let handle = tokio::spawn(async {});
// Use yield_now to ensure task doesn't complete before abort() is called
let handle = tokio::spawn(async {
tokio::task::yield_now().await;
});
handle.abort();
handle.await.unwrap_err()
})
Expand Down
27 changes: 26 additions & 1 deletion crates/comenqd/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::ffi::OsStr;
/// Names of files storing queue metadata.
///
/// Extend this list when new metadata files are introduced.
pub(crate) const METADATA_FILE_NAMES: [&str; 2] = ["version", "recv.lock"];
pub(crate) const METADATA_FILE_NAMES: [&str; 3] = ["version", "recv.lock", "send.lock"];

/// Returns whether a file name represents queue metadata.
///
Expand All @@ -23,3 +23,28 @@ pub fn is_metadata_file(name: impl AsRef<OsStr>) -> bool {
let name = name.as_ref();
METADATA_FILE_NAMES.iter().any(|m| OsStr::new(m) == name)
}

#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;

#[rstest]
#[case::version("version")]
#[case::recv_lock("recv.lock")]
#[case::send_lock("send.lock")]
fn is_metadata_file_recognises_metadata(#[case] name: &str) {
assert!(is_metadata_file(name));
}

#[rstest]
#[case::segment_0000("0000")]
#[case::segment_0001("0001")]
#[case::segment_9999("9999")]
#[case::data_json("data.json")]
#[case::lock("lock")]
#[case::empty("")]
fn is_metadata_file_rejects_non_metadata(#[case] name: &str) {
assert!(!is_metadata_file(name));
}
}
Loading
Loading