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
3 changes: 1 addition & 2 deletions Cargo.lock

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

3 changes: 1 addition & 2 deletions crates/comenqd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ figment = { version = "0.10", default-features = false, features = ["env", "toml
rstest = { workspace = true }
tempfile = { workspace = true } # latest 3.x at time of writing; update as new patch versions release
serial_test = "2"
test-support = { path = "../../test-support" }
test-utils = { path = "../test-utils" }
wiremock = "0.6"
53 changes: 44 additions & 9 deletions crates/comenqd/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const DEFAULT_QUEUE_PATH: &str = "/var/lib/comenq/queue";
const DEFAULT_COOLDOWN: u64 = 960;

/// Runtime configuration for the daemon.
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
pub struct Config {
/// GitHub Personal Access Token.
pub github_token: String,
Expand Down Expand Up @@ -119,17 +119,52 @@ mod tests {
use tempfile::tempdir;

mod env_guard {
include!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../tests/support/env_guard.rs"
));
}
//! Test helpers for managing environment variables.

#[derive(Debug)]
pub struct EnvVarGuard {
key: String,
original: Option<String>,
}

impl EnvVarGuard {
/// Set an environment variable for the lifetime of the returned guard.
pub fn set(key: &str, value: &str) -> Self {
let original = std::env::var(key).ok();
set_env_var(key, value);
Self {
key: key.to_string(),
original,
}
}
}

pub mod support {
pub use super::env_guard::{EnvVarGuard, remove_env_var, set_env_var};
impl Drop for EnvVarGuard {
fn drop(&mut self) {
match &self.original {
Some(v) => set_env_var(&self.key, v),
None => remove_env_var(&self.key),
}
}
}

/// Set an environment variable for tests.
///
/// The nightly compiler marks `std::env::set_var` as `unsafe`.
/// Tests run serially so using it is acceptable here.
pub fn set_env_var(key: &str, value: &str) {
unsafe { std::env::set_var(key, value) };
}

/// Remove an environment variable for tests.
///
/// `std::env::remove_var` is also `unsafe` on nightly.
pub fn remove_env_var(key: &str) {
unsafe { std::env::remove_var(key) };
}
}

use support::{EnvVarGuard, remove_env_var};
use env_guard::{EnvVarGuard, remove_env_var};

#[rstest]
#[serial_test::serial]
Expand Down
44 changes: 39 additions & 5 deletions crates/comenqd/src/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,22 +281,56 @@ pub async fn run_worker(
mod tests {
//! Tests for the daemon tasks.
use super::*;
use tempfile::tempdir;
use test_support::wait_for_file;
use test_utils::{octocrab_for, temp_config};
use octocrab::Octocrab;
use std::fs as stdfs;
use std::path::Path;
use std::sync::Arc;
use tempfile::{TempDir, tempdir};
use tokio::io::AsyncWriteExt;
use tokio::net::{UnixListener, UnixStream};
use tokio::net::UnixStream;
use tokio::sync::{mpsc, watch};
use tokio::time::{Duration, sleep};
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
use yaque::Receiver;
fn temp_config(tmp: &TempDir) -> Config {
Config {
github_token: String::from("t"),
socket_path: tmp.path().join("sock"),
queue_path: tmp.path().join("q"),
cooldown_period_seconds: 1,
}
}

fn cfg_with_cooldown(dir: &TempDir, secs: u64) -> Config {
Config {
cooldown_period_seconds: secs,
..temp_config(dir)
}
}

#[expect(clippy::expect_used, reason = "simplify test helper setup")]
fn octocrab_for(server: &MockServer) -> Arc<Octocrab> {
Arc::new(
Octocrab::builder()
.personal_token("t".to_string())
.base_uri(server.uri())
.expect("base_uri")
.build()
.expect("build octocrab"),
)
}

async fn wait_for_file(path: &Path, tries: u32, delay: Duration) -> bool {
for _ in 0..tries {
if path.exists() {
return true;
}
sleep(delay).await;
}
path.exists()
}

async fn setup_run_worker(status: u16) -> (MockServer, Arc<Config>, Receiver, Arc<Octocrab>) {
let dir = tempdir().expect("tempdir");
let cfg = Arc::new(Config {
Expand Down Expand Up @@ -364,7 +398,7 @@ mod tests {
let dir = tempdir().expect("tempdir");
let queue_path = dir.path().join("q");
let (sender, mut receiver) = channel(&queue_path).expect("channel");
let (client_tx, mut writer_rx) = mpsc::unbounded_channel();
let (client_tx, writer_rx) = mpsc::unbounded_channel();
let writer = tokio::spawn(queue_writer(sender, writer_rx));

let (mut client, server) = UnixStream::pair().expect("pair");
Expand Down
3 changes: 1 addition & 2 deletions crates/comenqd/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ where
fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_writer(writer)
.json()
.init();
}

Expand Down Expand Up @@ -66,7 +65,7 @@ mod tests {
#[test]
fn init_logging() {
let buf = Arc::new(Mutex::new(Vec::new()));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Using unsafe for std::env::set_var may be unnecessary on stable Rust.

If targeting stable Rust, remove the unnecessary unsafe block or use a cfg attribute to conditionally include it only when required.

Suggested change
let buf = Arc::new(Mutex::new(Vec::new()));
std::env::set_var("RUST_LOG", "info");

std::env::set_var("RUST_LOG", "info");
unsafe { std::env::set_var("RUST_LOG", "info") };
init_with_writer(BufMakeWriter { buf: buf.clone() });
info!("captured");
let output = String::from_utf8(buf.lock().expect("Failed to lock log buffer").clone())
Expand Down