Add serve snapshot test for empty project

This commit is contained in:
Lucien Greathouse
2019-09-03 17:56:23 -07:00
parent d5c816f24d
commit ea765eb929
10 changed files with 176 additions and 213 deletions

View File

@@ -6,12 +6,18 @@ edition = "2018"
publish = false
[dependencies]
insta = "0.10.0"
paste = "0.1.5"
tempfile = "3.1.0"
reqwest = "0.9.20"
env_logger = "0.6.2"
log = "0.4.8"
paste = "0.1.5"
reqwest = "0.9.20"
serde = "1.0.99"
serde_json = "1.0.40"
tempfile = "3.1.0"
walkdir = "2.2.9"
# We execute Rojo via std::process::Command, so depend on it so it's built!
rojo = { path = ".." }
[dependencies.insta]
version = "0.11.0"
features = ["redactions"]

View File

@@ -0,0 +1,6 @@
{
"name": "empty",
"tree": {
"$className": "Folder"
}
}

View File

@@ -1,9 +0,0 @@
{
"name": "placeholder",
"tree": {
"$className": "StringValue",
"$properties": {
"Value": "Hello, world!"
}
}
}

View File

@@ -1,6 +1,6 @@
use std::{fs, process::Command};
use insta::assert_snapshot_matches;
use insta::assert_snapshot;
use tempfile::tempdir;
use crate::util::{get_build_tests_path, get_rojo_path, get_working_dir_path};
@@ -78,5 +78,5 @@ fn run_build_test(test_name: &str) {
let contents = fs::read_to_string(&output_path).expect("Couldn't read output file");
assert_snapshot_matches!(test_name, contents);
assert_snapshot!(test_name, contents);
}

View File

@@ -1,41 +1,111 @@
use std::process::Command;
use std::{
fs,
path::PathBuf,
process::Command,
sync::atomic::{AtomicUsize, Ordering},
};
use crate::util::{get_rojo_path, get_serve_tests_path, get_working_dir_path};
use insta::assert_yaml_snapshot;
use tempfile::{tempdir, TempDir};
use librojo::web_interface::ServerInfoResponse;
use crate::util::{
copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop,
};
#[test]
fn serve_test() {
fn empty() {
let _ = env_logger::try_init();
let serve_test_path = get_serve_tests_path();
let working_dir = get_working_dir_path();
let mut session = TestServeSession::new("empty");
let info = session.wait_to_come_online();
let input_path = serve_test_path.join("placeholder");
assert_yaml_snapshot!(info, {
".sessionId" => "[session id]"
});
}
let exe_path = get_rojo_path();
fn get_port_number() -> usize {
static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103);
let mut handle = Command::new(exe_path)
.args(&["serve", input_path.to_str().unwrap(), "--port", "35103"])
.current_dir(working_dir)
.spawn()
.expect("Couldn't start Rojo");
NEXT_PORT_NUMBER.fetch_add(1, Ordering::SeqCst)
}
loop {
let mut response = match reqwest::get("http://localhost:35103/api/rojo") {
Ok(res) => res,
Err(err) => {
log::info!("Server error, retrying: {}", err);
std::thread::sleep(std::time::Duration::from_millis(30));
continue;
}
};
struct TestServeSession {
// Drop order is important here: we want the process to be killed before the
// directory it's operating on is destroyed.
rojo_process: KillOnDrop,
_dir: TempDir,
let text = response.text().expect("Couldn't get response text");
port: usize,
project_path: PathBuf,
}
log::info!("Got response body: {}", text);
break;
impl TestServeSession {
pub fn new(name: &str) -> Self {
let serve_test_path = get_serve_tests_path();
let working_dir = get_working_dir_path();
let exe_path = get_rojo_path();
let source_path = serve_test_path.join(name);
let dir = tempdir().expect("Couldn't create temporary directory");
let project_path = dir.path().join(name);
fs::create_dir(&project_path).expect("Couldn't create temporary project subdirectory");
copy_recursive(&source_path, &project_path)
.expect("Couldn't copy project to temporary directory");
let port = get_port_number();
let port_string = port.to_string();
let rojo_process = Command::new(exe_path)
.args(&[
"serve",
project_path.to_str().unwrap(),
"--port",
port_string.as_str(),
])
.current_dir(working_dir)
.spawn()
.expect("Couldn't start Rojo");
TestServeSession {
rojo_process: KillOnDrop(rojo_process),
_dir: dir,
port,
project_path,
}
}
handle
.kill()
.expect("Rojo server was not running at end of test");
pub fn wait_to_come_online(&mut self) -> ServerInfoResponse {
loop {
match self.rojo_process.0.try_wait() {
Ok(Some(status)) => panic!("Rojo process exited with status {}", status),
Ok(None) => { /* process is still running */ }
Err(err) => panic!("Failed to wait on Rojo process: {}", err),
}
let info = match self.get_api_rojo() {
Ok(info) => info,
Err(err) => {
log::debug!("Server error, retrying: {}", err);
std::thread::sleep(std::time::Duration::from_millis(30));
continue;
}
};
log::info!("Got session info: {:?}", info);
return info;
}
}
pub fn get_api_rojo(&self) -> Result<ServerInfoResponse, reqwest::Error> {
let info_url = format!("http://localhost:{}/api/rojo", self.port);
let body = reqwest::get(&info_url)?.text()?;
Ok(serde_json::from_str(&body).expect("Server returned malformed response"))
}
}

View File

@@ -0,0 +1,8 @@
---
source: rojo-test/src/serve_test.rs
expression: info
---
sessionId: "[session id]"
serverVersion: 0.5.0
protocolVersion: 3
expectedPlaceIds: ~

View File

@@ -1,4 +1,10 @@
use std::path::{Path, PathBuf};
use std::{
fs, io,
path::{Path, PathBuf},
process::Child,
};
use walkdir::WalkDir;
pub fn get_rojo_path() -> PathBuf {
let working_dir = get_working_dir_path();
@@ -29,3 +35,37 @@ pub fn get_serve_tests_path() -> PathBuf {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
manifest_dir.join("serve-tests")
}
/// Recursively walk a directory and copy each item to the equivalent location
/// in another directory. Equivalent to `cp -r src/* dst`
pub fn copy_recursive(from: &Path, to: &Path) -> io::Result<()> {
for entry in WalkDir::new(from) {
let entry = entry?;
let path = entry.path();
let new_path = to.join(path.strip_prefix(from).unwrap());
let file_type = entry.file_type();
if file_type.is_dir() {
match fs::create_dir(new_path) {
Ok(_) => {}
Err(err) => match err.kind() {
io::ErrorKind::AlreadyExists => {}
_ => panic!(err),
},
}
} else {
fs::copy(path, new_path)?;
}
}
Ok(())
}
pub struct KillOnDrop(pub Child);
impl Drop for KillOnDrop {
fn drop(&mut self) {
let _ = self.0.kill();
}
}