mod common;
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use common::{drain_to_buffer, send_term, spawn_camel_run, wait_exit_bounded, wait_for_marker};
fn write_camel_toml(dir: &Path, body: &str) {
std::fs::write(dir.join("Camel.toml"), body).expect("write Camel.toml");
}
fn write_routes_file(dir: &Path, name: &str, body: &str) {
let routes_dir = dir.join("routes");
std::fs::create_dir_all(&routes_dir).expect("create routes/");
std::fs::write(routes_dir.join(name), body).expect("write routes file");
}
#[test]
fn watch_reload_test_doc_save_is_noop() {
let dir = tempfile::tempdir().expect("tempdir");
write_camel_toml(
dir.path(),
r#"[default]
routes = ["routes/*.yaml"]
log_level = "INFO"
watch = true
"#,
);
write_routes_file(
dir.path(),
"demo.yaml",
r#"routes:
- id: "demo"
from: "direct:start"
steps:
- to: "mock:result"
"#,
);
let test_doc_body =
"routeFiles:\n - demo.yaml\ninputs: []\nexpects:\n mock:result:\n count: 1\n";
write_routes_file(dir.path(), "demo.test.yaml", test_doc_body);
let mut child = spawn_camel_run(dir.path());
let out_buf: Arc<Mutex<String>> = Arc::new(Mutex::new(String::new()));
let err_buf: Arc<Mutex<String>> = Arc::new(Mutex::new(String::new()));
let stdout = child
.stdout
.take()
.expect("child stdout was configured as piped");
let stderr = child
.stderr
.take()
.expect("child stderr was configured as piped");
let out_thread_buf = Arc::clone(&out_buf);
let err_thread_buf = Arc::clone(&err_buf);
let out_handle = thread::spawn(move || drain_to_buffer(stdout, out_thread_buf));
let err_handle = thread::spawn(move || drain_to_buffer(stderr, err_thread_buf));
let armed = wait_for_marker(
&mut child,
&[Arc::clone(&out_buf), Arc::clone(&err_buf)],
"hot-reload: watching",
Duration::from_secs(10),
);
let captured_so_far = || {
format!(
"stdout:\n{}\nstderr:\n{}",
out_buf.lock().expect("stdout buffer lock poisoned"),
err_buf.lock().expect("stderr buffer lock poisoned")
)
};
assert!(
armed,
"file watcher did not report itself armed within 10 s;\n{}",
captured_so_far()
);
std::fs::write(
dir.path().join("routes/demo.test.yaml"),
format!("{test_doc_body}\n"),
)
.expect("rewrite demo.test.yaml");
thread::sleep(Duration::from_secs(2));
let status = child.try_wait().expect("try_wait after test-doc save");
assert!(
status.is_none(),
"camel run died after the colocated test-doc save (status: {status:?}); \
the reload pass must skip *.test.yaml, not parse it;\n{}",
captured_so_far()
);
send_term(&child);
let exited = wait_exit_bounded(&mut child, Duration::from_secs(10));
let _ = out_handle.join();
let _ = err_handle.join();
assert!(
exited,
"camel run did not exit within 10 s after SIGTERM;\n{}",
captured_so_far()
);
let stdout_text = out_buf.lock().expect("stdout buffer lock poisoned").clone();
let stderr_text = err_buf.lock().expect("stderr buffer lock poisoned").clone();
assert!(
!stderr_text.contains("demo.test.yaml"),
"stderr names the colocated test doc; the reload pass must skip it:\n{stderr_text}"
);
assert!(
!stdout_text.contains("demo.test.yaml"),
"stdout names the colocated test doc; the reload pass must skip it:\n{stdout_text}"
);
}