Skip to content

Commit

Permalink
When starting edgedb-server for tests, log to a file instead of the t…
Browse files Browse the repository at this point in the history
…erminal (#318)
  • Loading branch information
aljazerzen authored Apr 18, 2024
1 parent 69f080a commit 0a6d2ea
Showing 1 changed file with 68 additions and 24 deletions.
92 changes: 68 additions & 24 deletions edgedb-tokio/tests/func/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::env;
use std::fs::{self, File};
use std::io::{BufRead, BufReader};
use std::os::unix::io::FromRawFd;
use std::process;
use std::process::{self, Stdio};
use std::str::FromStr;
use std::sync::Mutex;

use command_fds::{CommandFdExt, FdMapping};
Expand Down Expand Up @@ -36,50 +37,45 @@ impl ServerGuard {
} else {
"edgedb-server".to_string()
};
let (pipe_read, pipe_write) = nix::unistd::pipe().unwrap();

let mut cmd = Command::new(&bin_name);
cmd.env("EDGEDB_SERVER_SECURITY", "insecure_dev_mode");
cmd.arg("--temp-dir");
cmd.arg("--testmode");
cmd.arg("--emit-server-status=fd://3");
cmd.arg("--port=auto");
cmd.arg("--tls-cert-mode=generate_self_signed");

// pipe server status on fd 3 into a reader bellow
let (status_read, status_write) = nix::unistd::pipe().unwrap();
cmd.fd_mappings(vec![FdMapping {
parent_fd: pipe_write,
parent_fd: status_write,
child_fd: 3,
}])
.unwrap();

// pipe stderr into a buffer that's printed only when there is an error
cmd.stderr(Stdio::piped());

if nix::unistd::Uid::effective().as_raw() == 0 {
use std::os::unix::process::CommandExt;
// This is moslty true in vagga containers, so run edgedb/postgres
// by any non-root user
cmd.uid(1);
}

let process = cmd
eprintln!("Starting {}", bin_name);

let mut process = cmd
.spawn()
.unwrap_or_else(|_| panic!("Can run {}", bin_name));
let pipe = BufReader::new(unsafe { File::from_raw_fd(pipe_read) });
let mut result = Err(anyhow::anyhow!("no server info emitted"));
for line in pipe.lines() {
match line {
Ok(line) => {
if let Some(data) = line.strip_prefix("READY=") {
let data: ServerInfo =
serde_json::from_str(data).expect("valid server data");
println!("Server data {:?}", data);
result = Ok(data);
break;
}
}
Err(e) => {
eprintln!("Error reading from server: {}", e);
result = Err(e.into());
break;
}
}
}

// write log file
let stdout = process.stderr.take().unwrap();
std::thread::spawn(move || write_log_into_file(stdout));

// wait for server to start
let result = wait_for_server_status(status_read);

let mut sinfo = SHUTDOWN_INFO.lock().expect("shutdown mutex works");
if sinfo.is_empty() {
Expand Down Expand Up @@ -133,6 +129,54 @@ impl ServerGuard {
}
}

/// Reads the stream at file descriptor `status_read` until edgedb-server notifies that it is ready
fn wait_for_server_status(status_read: i32) -> Result<ServerInfo, anyhow::Error> {
let pipe = BufReader::new(unsafe { File::from_raw_fd(status_read) });
let mut result = Err(anyhow::anyhow!("no server info emitted"));
for line in pipe.lines() {
match line {
Ok(line) => {
if let Some(data) = line.strip_prefix("READY=") {
let data: ServerInfo = serde_json::from_str(data).expect("valid server data");
println!("Server data {:?}", data);
result = Ok(data);
break;
}
}
Err(e) => {
eprintln!("Error reading from server: {}", e);
result = Err(e.into());
break;
}
}
}
result
}

/// Writes a stream to a log file
fn write_log_into_file(stream: impl std::io::Read) {
let target_tmp_dir = std::env::var("CARGO_TARGET_TMPDIR").unwrap();
let mut log_dir = std::path::PathBuf::from_str(&target_tmp_dir).unwrap();
log_dir.push("server-logs");

let time_the_epoch = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.expect("Time went backwards")
.as_millis();

let mut log_file = log_dir.clone();
let file_name = time_the_epoch.to_string() + ".log";
log_file.push(file_name);

eprintln!("Writing server logs into {:?}", &log_file);

std::fs::create_dir_all(&log_dir).unwrap();
let mut log_file = File::create(log_file).unwrap();

let mut reader = BufReader::new(stream);
std::io::copy(&mut reader, &mut log_file).unwrap();
}

extern "C" fn stop_processes() {
let mut items = SHUTDOWN_INFO.lock().expect("shutdown mutex works");
for item in items.iter_mut() {
Expand Down

0 comments on commit 0a6d2ea

Please sign in to comment.