Replace rojo-test with regular tests folder again (#323)

* Replace rojo-test with regular tests folder again

* Bump MSRV to 1.43.1
This commit is contained in:
Lucien Greathouse
2020-05-20 15:30:05 -07:00
committed by GitHub
parent ca5b8ab309
commit 5ccd02939b
71 changed files with 96 additions and 217 deletions

View File

@@ -1,27 +0,0 @@
[package]
name = "rojo-test"
version = "0.1.0"
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
edition = "2018"
publish = false
[features]
default = []
unstable_glob_ignore_paths = []
[dependencies]
env_logger = "0.7.1"
insta = { version = "0.13.1", features = ["redactions"] }
log = "0.4.8"
paste = "0.1.5"
rbx_dom_weak = "1.9.0"
reqwest = "0.9.20"
serde = "1.0.99"
serde_json = "1.0.40"
serde_yaml = "0.8.9"
tempfile = "3.1.0"
walkdir = "2.2.9"
rojo = { path = ".." }
rojo-insta-ext = { path = "../rojo-insta-ext" }

View File

@@ -1,8 +0,0 @@
# rojo-test
This project does end-to-end testing of Rojo by executing it and checking what side-effects it has.
rojo-test is meant to be run as a test with:
```bash
cargo test
```

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/build_test.rs
source: tests/tests/build.rs
expression: contents
---
<roblox version="4">

View File

@@ -1,12 +0,0 @@
---
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="StringValue" referent="0">
<Properties>
<string name="Name">plain</string>
<string name="Value">This is a bare text file with no project.</string>
</Properties>
</Item>
</roblox>

View File

@@ -1,11 +0,0 @@
---
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">plain_gitkeep</string>
</Properties>
</Item>
</roblox>

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
---
messageCursor: 1

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
---
messageCursor: 1

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
---
messageCursor: 1

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -0,0 +1,9 @@
---
source: tests/tests/serve.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~
protocolVersion: 3
rootInstanceId: id-2
serverVersion: "[server-version]"
sessionId: id-1

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
---
messageCursor: 1

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:

View File

@@ -0,0 +1,9 @@
---
source: tests/tests/serve.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~
protocolVersion: 3
rootInstanceId: id-2
serverVersion: "[server-version]"
sessionId: id-1

View File

@@ -1,5 +1,5 @@
---
source: rojo-test/src/serve_test.rs
source: tests/tests/serve.rs
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
---
messageCursor: 1

View File

@@ -1,19 +0,0 @@
---
source: rojo-test/src/serve_test.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:
id-2:
Children: []
ClassName: StringValue
Id: id-2
Metadata:
ignoreUnknownInstances: false
Name: just_txt
Parent: ~
Properties:
Value:
Type: String
Value: "Hello, world!"
messageCursor: 0
sessionId: id-1

View File

@@ -1,9 +0,0 @@
---
source: rojo-test/src/serve_test.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~
protocolVersion: 3
rootInstanceId: id-2
serverVersion: "[server-version]"
sessionId: id-1

View File

@@ -1,9 +0,0 @@
---
source: rojo-test/src/serve_test.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~
protocolVersion: 3
rootInstanceId: id-2
serverVersion: "[server-version]"
sessionId: id-1

View File

@@ -1,9 +0,0 @@
---
source: rojo-test/src/serve_test.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~
protocolVersion: 3
rootInstanceId: id-2
serverVersion: "[server-version]"
sessionId: id-1

View File

@@ -1,93 +0,0 @@
use std::{fs, path::Path, process::Command};
use insta::assert_snapshot;
use tempfile::tempdir;
use crate::util::{get_build_tests_path, get_rojo_path, get_working_dir_path};
macro_rules! gen_build_tests {
( $($test_name: ident,)* ) => {
$(
paste::item! {
#[test]
fn [<build_ $test_name>]() {
let _ = env_logger::try_init();
run_build_test(stringify!($test_name));
}
}
)*
};
}
gen_build_tests! {
client_in_folder,
client_init,
csv_bug_145,
csv_bug_147,
csv_in_folder,
deep_nesting,
gitkeep,
infer_service_name,
infer_starter_player,
init_meta_class_name,
init_meta_properties,
init_with_children,
json_as_lua,
json_model_in_folder,
json_model_legacy_name,
module_in_folder,
module_init,
rbxm_in_folder,
rbxmx_in_folder,
rbxmx_ref,
script_meta_disabled,
server_in_folder,
server_init,
txt,
txt_in_folder,
}
#[cfg(feature = "unstable_glob_ignore_paths")]
gen_build_tests! {
ignore_glob_inner,
ignore_glob_nested,
ignore_glob_spec,
}
fn run_build_test(test_name: &str) {
let build_test_path = get_build_tests_path();
let working_dir = get_working_dir_path();
let input_path = build_test_path.join(test_name);
let output_dir = tempdir().expect("couldn't create temporary directory");
let output_path = output_dir.path().join(format!("{}.rbxmx", test_name));
let exe_path = get_rojo_path();
let status = Command::new(exe_path)
.args(&[
"build",
input_path.to_str().unwrap(),
"-o",
output_path.to_str().unwrap(),
])
.env("RUST_LOG", "error")
.current_dir(working_dir)
.status()
.expect("Couldn't start Rojo");
assert!(status.success(), "Rojo did not exit successfully");
let contents = fs::read_to_string(&output_path).expect("Couldn't read output file");
let mut settings = insta::Settings::new();
let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("build-test-snapshots");
settings.set_snapshot_path(snapshot_path);
settings.bind(|| {
assert_snapshot!(test_name, contents);
});
}

View File

@@ -1,104 +0,0 @@
use std::collections::HashMap;
use rbx_dom_weak::RbxId;
use serde::Serialize;
use librojo::web_api::{Instance, InstanceUpdate, ReadResponse, SubscribeResponse};
use rojo_insta_ext::RedactionMap;
/// A convenience method to store all of the redactable data from a piece of
/// data, then immediately redact it and return a serde_yaml Value.
pub trait InternAndRedact<T> {
fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value;
}
impl<I, T> InternAndRedact<T> for I
where
I: Serialize + Internable<T>,
{
fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value {
self.intern(redactions, extra);
redactions.redacted_yaml(self)
}
}
/// A trait to describe how to discover redactable data from an type.
///
/// The 'extra' parameter is a kludge to support types like Instance or
/// ReadResponse that need some additional information in order to be
/// deterministic.
pub trait Internable<T> {
fn intern(&self, redactions: &mut RedactionMap, extra: T);
}
impl Internable<RbxId> for ReadResponse<'_> {
fn intern(&self, redactions: &mut RedactionMap, root_id: RbxId) {
redactions.intern(root_id);
let root_instance = self.instances.get(&root_id).unwrap();
for &child_id in root_instance.children.iter() {
self.intern(redactions, child_id);
}
}
}
impl<'a> Internable<&'a HashMap<RbxId, Instance<'_>>> for Instance<'a> {
fn intern(
&self,
redactions: &mut RedactionMap,
other_instances: &HashMap<RbxId, Instance<'_>>,
) {
redactions.intern(self.id);
for child_id in self.children.iter() {
let child = &other_instances[child_id];
child.intern(redactions, other_instances);
}
}
}
impl Internable<()> for SubscribeResponse<'_> {
fn intern(&self, redactions: &mut RedactionMap, _extra: ()) {
for message in &self.messages {
intern_instance_updates(redactions, &message.updated);
intern_instance_additions(redactions, &message.added);
}
}
}
fn intern_instance_updates(redactions: &mut RedactionMap, updates: &[InstanceUpdate]) {
for update in updates {
redactions.intern(update.id);
}
}
fn intern_instance_additions(
redactions: &mut RedactionMap,
additions: &HashMap<RbxId, Instance<'_>>,
) {
// This method redacts in a deterministic order from a HashMap by collecting
// all of the instances that are direct children of instances we've already
// interned.
let mut added_roots = Vec::new();
for (id, added) in additions {
let parent_id = added.parent.unwrap();
let parent_redacted = redactions.get_redacted_value(parent_id);
// Here, we assume that instances are only added to other instances that
// we've already interned. If that's not true, then we'll have some
// dangling unredacted IDs.
if let Some(parent_redacted) = parent_redacted {
added_roots.push((id, parent_redacted));
}
}
// Sort the input by the redacted key, which should match the traversal
// order we need for the tree.
added_roots.sort_unstable_by(|a, b| a.1.cmp(&b.1));
for (root_id, _redacted_id) in added_roots {
additions[root_id].intern(redactions, additions);
}
}

View File

@@ -1,7 +0,0 @@
#![cfg(test)]
mod build_test;
mod internable;
mod serve_test;
mod serve_util;
mod util;

View File

@@ -1,188 +0,0 @@
use std::fs;
use insta::assert_yaml_snapshot;
use tempfile::tempdir;
use crate::{internable::InternAndRedact, serve_util::run_serve_test};
#[test]
fn empty() {
run_serve_test("empty", |session, mut redactions| {
let info = session.get_api_rojo().unwrap();
let root_id = info.root_instance_id;
assert_yaml_snapshot!("empty_info", redactions.redacted_yaml(info));
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"empty_all",
read_response.intern_and_redact(&mut redactions, root_id)
);
});
}
#[test]
fn scripts() {
run_serve_test("scripts", |session, mut redactions| {
let info = session.get_api_rojo().unwrap();
let root_id = info.root_instance_id;
assert_yaml_snapshot!("scripts_info", redactions.redacted_yaml(info));
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"scripts_all",
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::write(session.path().join("src/foo.lua"), "Updated foo!").unwrap();
let subscribe_response = session.get_api_subscribe(0).unwrap();
assert_yaml_snapshot!(
"scripts_subscribe",
subscribe_response.intern_and_redact(&mut redactions, ())
);
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"scripts_all-2",
read_response.intern_and_redact(&mut redactions, root_id)
);
});
}
#[test]
fn add_folder() {
run_serve_test("add_folder", |session, mut redactions| {
let info = session.get_api_rojo().unwrap();
let root_id = info.root_instance_id;
assert_yaml_snapshot!("add_folder_info", redactions.redacted_yaml(info));
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"add_folder_all",
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::create_dir(session.path().join("src/my-new-folder")).unwrap();
let subscribe_response = session.get_api_subscribe(0).unwrap();
assert_yaml_snapshot!(
"add_folder_subscribe",
subscribe_response.intern_and_redact(&mut redactions, ())
);
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"add_folder_all-2",
read_response.intern_and_redact(&mut redactions, root_id)
);
});
}
#[test]
fn remove_file() {
run_serve_test("remove_file", |session, mut redactions| {
let info = session.get_api_rojo().unwrap();
let root_id = info.root_instance_id;
assert_yaml_snapshot!("remove_file_info", redactions.redacted_yaml(info));
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"remove_file_all",
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::remove_file(session.path().join("src/hello.txt")).unwrap();
let subscribe_response = session.get_api_subscribe(0).unwrap();
assert_yaml_snapshot!(
"remove_file_subscribe",
subscribe_response.intern_and_redact(&mut redactions, ())
);
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"remove_file_all-2",
read_response.intern_and_redact(&mut redactions, root_id)
);
});
}
#[test]
fn edit_init() {
run_serve_test("edit_init", |session, mut redactions| {
let info = session.get_api_rojo().unwrap();
let root_id = info.root_instance_id;
assert_yaml_snapshot!("edit_init_info", redactions.redacted_yaml(info));
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"edit_init_all",
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::write(session.path().join("src/init.lua"), b"-- Edited contents").unwrap();
let subscribe_response = session.get_api_subscribe(0).unwrap();
assert_yaml_snapshot!(
"edit_init_subscribe",
subscribe_response.intern_and_redact(&mut redactions, ())
);
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"edit_init_all-2",
read_response.intern_and_redact(&mut redactions, root_id)
);
});
}
#[test]
fn move_folder_of_stuff() {
run_serve_test("move_folder_of_stuff", |session, mut redactions| {
let info = session.get_api_rojo().unwrap();
let root_id = info.root_instance_id;
assert_yaml_snapshot!("move_folder_of_stuff_info", redactions.redacted_yaml(info));
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"move_folder_of_stuff_all",
read_response.intern_and_redact(&mut redactions, root_id)
);
// Create a directory full of stuff we can move in
let src_dir = tempdir().unwrap();
let stuff_path = src_dir.path().join("new-stuff");
fs::create_dir(&stuff_path).unwrap();
// Make a bunch of random files in our stuff folder
for i in 0..10 {
let file_name = stuff_path.join(format!("{}.txt", i));
let file_contents = format!("File #{}", i);
fs::write(file_name, file_contents).unwrap();
}
// We're hoping that this rename gets picked up as one event. This test
// will fail otherwise.
fs::rename(stuff_path, session.path().join("src/new-stuff")).unwrap();
let subscribe_response = session.get_api_subscribe(0).unwrap();
assert_yaml_snapshot!(
"move_folder_of_stuff_subscribe",
subscribe_response.intern_and_redact(&mut redactions, ())
);
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"move_folder_of_stuff_all-2",
read_response.intern_and_redact(&mut redactions, root_id)
);
});
}

View File

@@ -1,174 +0,0 @@
use std::{
fs,
path::{Path, PathBuf},
process::Command,
sync::atomic::{AtomicUsize, Ordering},
thread,
time::Duration,
};
use rbx_dom_weak::RbxId;
use tempfile::{tempdir, TempDir};
use librojo::web_api::{ReadResponse, ServerInfoResponse, SubscribeResponse};
use rojo_insta_ext::RedactionMap;
use crate::util::{
copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop,
};
/// Convenience method to run a `rojo serve` test.
///
/// Test projects should be defined in the `serve-tests` folder; their filename
/// should be given as the first parameter.
///
/// The passed in callback is where the actual test body should go. Setup and
/// cleanup happens automatically.
pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, RedactionMap)) {
let _ = env_logger::try_init();
let mut redactions = RedactionMap::new();
let mut session = TestServeSession::new(test_name);
let info = session.wait_to_come_online();
redactions.intern(info.session_id);
redactions.intern(info.root_instance_id);
let mut settings = insta::Settings::new();
let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots");
settings.set_snapshot_path(snapshot_path);
settings.set_sort_maps(true);
settings.add_redaction(".serverVersion", "[server-version]");
settings.bind(move || callback(session, redactions));
}
/// Represents a running Rojo serve session running in a temporary directory.
pub 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,
port: usize,
project_path: PathBuf,
}
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);
let source_is_file = fs::metadata(&source_path).unwrap().is_file();
if source_is_file {
fs::copy(&source_path, &project_path).expect("couldn't copy project file");
} else {
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,
}
}
pub fn path(&self) -> &Path {
&self.project_path
}
/// Waits for the `rojo serve` server to come online with expontential
/// backoff.
pub fn wait_to_come_online(&mut self) -> ServerInfoResponse {
const BASE_DURATION_MS: f32 = 30.0;
const EXP_BACKOFF_FACTOR: f32 = 1.3;
const MAX_TRIES: u32 = 5;
for i in 1..=MAX_TRIES {
match self.rojo_process.0.try_wait() {
Ok(Some(status)) => panic!("Rojo process exited with status {}", status),
Ok(None) => { /* The process is still running, as expected */ }
Err(err) => panic!("Failed to wait on Rojo process: {}", err),
}
let info = match self.get_api_rojo() {
Ok(info) => info,
Err(err) => {
let retry_time_ms = BASE_DURATION_MS * (i as f32).powf(EXP_BACKOFF_FACTOR);
let retry_time = Duration::from_millis(retry_time_ms as u64);
log::info!("Server error, retrying in {:?}: {}", retry_time, err);
thread::sleep(retry_time);
continue;
}
};
log::info!("Got session info: {:?}", info);
return info;
}
panic!("Rojo server did not respond after {} tries.", MAX_TRIES);
}
pub fn get_api_rojo(&self) -> Result<ServerInfoResponse, reqwest::Error> {
let url = format!("http://localhost:{}/api/rojo", self.port);
let body = reqwest::get(&url)?.text()?;
Ok(serde_json::from_str(&body).expect("Server returned malformed response"))
}
pub fn get_api_read(&self, id: RbxId) -> Result<ReadResponse, reqwest::Error> {
let url = format!("http://localhost:{}/api/read/{}", self.port, id);
let body = reqwest::get(&url)?.text()?;
Ok(serde_json::from_str(&body).expect("Server returned malformed response"))
}
pub fn get_api_subscribe(
&self,
cursor: u32,
) -> Result<SubscribeResponse<'static>, reqwest::Error> {
let url = format!("http://localhost:{}/api/subscribe/{}", self.port, cursor);
reqwest::get(&url)?.json()
}
}
/// Probably-okay way to generate random enough port numbers for running the
/// Rojo live server.
///
/// If this method ends up having problems, we should add an option for Rojo to
/// use a random port chosen by the operating system and figure out a good way
/// to get that port back to the test CLI.
fn get_port_number() -> usize {
static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103);
NEXT_PORT_NUMBER.fetch_add(1, Ordering::SeqCst)
}

View File

@@ -1,71 +0,0 @@
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();
let mut exe_path = working_dir.join("target/debug/rojo");
if cfg!(windows) {
exe_path.set_extension("exe");
}
exe_path
}
pub fn get_working_dir_path() -> PathBuf {
let mut manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
assert!(
manifest_dir.pop(),
"Manifest directory did not have a parent"
);
manifest_dir
}
pub fn get_build_tests_path() -> PathBuf {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
manifest_dir.join("build-tests")
}
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();
}
}