mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-24 15:01:38 +00:00
New snapshot tests
This commit is contained in:
parent
ad93631ef8
commit
684a33c418
12 changed files with 921 additions and 90 deletions
|
|
@ -1,15 +1,28 @@
|
|||
mod test_util;
|
||||
|
||||
use std::{
|
||||
fs::{self, File},
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use log::error;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use librojo::{
|
||||
imfs::Imfs,
|
||||
project::{Project, ProjectNode},
|
||||
project::Project,
|
||||
live_session::LiveSession,
|
||||
rbx_snapshot::{SnapshotContext, snapshot_project_tree},
|
||||
snapshot_reconciler::{RbxSnapshotInstance},
|
||||
};
|
||||
|
||||
use crate::test_util::{
|
||||
copy_recursive,
|
||||
snapshot::*,
|
||||
tree::trees_equal,
|
||||
};
|
||||
|
||||
macro_rules! generate_snapshot_tests {
|
||||
|
|
@ -18,6 +31,8 @@ macro_rules! generate_snapshot_tests {
|
|||
paste::item! {
|
||||
#[test]
|
||||
fn [<snapshot_ $name>]() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let tests_folder = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects");
|
||||
let project_folder = tests_folder.join(stringify!($name));
|
||||
run_snapshot_test(&project_folder);
|
||||
|
|
@ -29,13 +44,79 @@ macro_rules! generate_snapshot_tests {
|
|||
|
||||
generate_snapshot_tests!(
|
||||
empty,
|
||||
multi_partition_game,
|
||||
nested_partitions,
|
||||
single_partition_game,
|
||||
single_partition_model,
|
||||
transmute_partition
|
||||
);
|
||||
|
||||
const SNAPSHOT_EXPECTED_NAME: &str = "expected-snapshot.json";
|
||||
#[test]
|
||||
fn multi_partition_game() {
|
||||
let _ = env_logger::try_init();
|
||||
let source_path = project_path("multi_partition_game");
|
||||
|
||||
let (dir, live_session) = start_session(&source_path);
|
||||
tree_step("initial", &live_session, &source_path);
|
||||
|
||||
let added_path = dir.path().join("a/added");
|
||||
fs::create_dir_all(&added_path)
|
||||
.expect("Couldn't create directory");
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
|
||||
tree_step("with_dir", &live_session, &source_path);
|
||||
|
||||
let moved_path = dir.path().join("b/added");
|
||||
fs::rename(&added_path, &moved_path)
|
||||
.expect("Couldn't rename directory");
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
|
||||
tree_step("with_moved_dir", &live_session, &source_path);
|
||||
}
|
||||
|
||||
/// Find the path to the given test project relative to the manifest.
|
||||
fn project_path(name: &str) -> PathBuf {
|
||||
let mut path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects");
|
||||
path.push(name);
|
||||
path
|
||||
}
|
||||
|
||||
/// Starts a new LiveSession for the project located at the given file path.
|
||||
fn start_session(source_path: &Path) -> (TempDir, LiveSession) {
|
||||
let dir = tempdir()
|
||||
.expect("Couldn't create temporary directory");
|
||||
|
||||
copy_recursive(&source_path, dir.path())
|
||||
.expect("Couldn't copy project to temporary directory");
|
||||
|
||||
let project = Arc::new(Project::load_fuzzy(dir.path())
|
||||
.expect("Couldn't load project from temp directory"));
|
||||
|
||||
let live_session = LiveSession::new(Arc::clone(&project))
|
||||
.expect("Couldn't start live session");
|
||||
|
||||
(dir, live_session)
|
||||
}
|
||||
|
||||
/// Marks a 'step' in the test, which will snapshot the session's current
|
||||
/// RbxTree object and compare it against the saved snapshot if it exists.
|
||||
fn tree_step(step: &str, live_session: &LiveSession, source_path: &Path) {
|
||||
let rbx_session = live_session.rbx_session.lock().unwrap();
|
||||
let tree = rbx_session.get_tree();
|
||||
|
||||
match read_tree_by_name(source_path, step) {
|
||||
Some(existing) => match trees_equal(&existing, tree) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
error!("Trees at step '{}' were not equal.\n{}", step, e);
|
||||
panic!("Tree mismatch at step '{}'", step);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
write_tree_by_name(source_path, step, tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_snapshot_test(path: &Path) {
|
||||
println!("Running snapshot from project: {}", path.display());
|
||||
|
|
@ -62,67 +143,4 @@ fn run_snapshot_test(path: &Path) {
|
|||
Some(expected_snapshot) => assert_eq!(snapshot, expected_snapshot),
|
||||
None => write_expected_snapshot(path, &snapshot),
|
||||
}
|
||||
}
|
||||
|
||||
/// Snapshots contain absolute paths, which simplifies much of Rojo.
|
||||
///
|
||||
/// For saving snapshots to the disk, we should strip off the project folder
|
||||
/// path to make them machine-independent. This doesn't work for paths that fall
|
||||
/// outside of the project folder, but that's okay here.
|
||||
///
|
||||
/// We also need to sort children, since Rojo tends to enumerate the filesystem
|
||||
/// in an unpredictable order.
|
||||
fn anonymize_snapshot(project_folder_path: &Path, snapshot: &mut RbxSnapshotInstance) {
|
||||
match snapshot.metadata.source_path.as_mut() {
|
||||
Some(path) => *path = anonymize_path(project_folder_path, path),
|
||||
None => {},
|
||||
}
|
||||
|
||||
match snapshot.metadata.project_definition.as_mut() {
|
||||
Some((_, project_node)) => anonymize_project_node(project_folder_path, project_node),
|
||||
None => {},
|
||||
}
|
||||
|
||||
snapshot.children.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
|
||||
for child in snapshot.children.iter_mut() {
|
||||
anonymize_snapshot(project_folder_path, child);
|
||||
}
|
||||
}
|
||||
|
||||
fn anonymize_project_node(project_folder_path: &Path, project_node: &mut ProjectNode) {
|
||||
match project_node.path.as_mut() {
|
||||
Some(path) => *path = anonymize_path(project_folder_path, path),
|
||||
None => {},
|
||||
}
|
||||
|
||||
for child_node in project_node.children.values_mut() {
|
||||
anonymize_project_node(project_folder_path, child_node);
|
||||
}
|
||||
}
|
||||
|
||||
fn anonymize_path(project_folder_path: &Path, path: &Path) -> PathBuf {
|
||||
if path.is_absolute() {
|
||||
path.strip_prefix(project_folder_path)
|
||||
.expect("Could not anonymize absolute path")
|
||||
.to_path_buf()
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
}
|
||||
|
||||
fn read_expected_snapshot(path: &Path) -> Option<Option<RbxSnapshotInstance<'static>>> {
|
||||
let contents = fs::read(path.join(SNAPSHOT_EXPECTED_NAME)).ok()?;
|
||||
let snapshot: Option<RbxSnapshotInstance<'static>> = serde_json::from_slice(&contents)
|
||||
.expect("Could not deserialize snapshot");
|
||||
|
||||
Some(snapshot)
|
||||
}
|
||||
|
||||
fn write_expected_snapshot(path: &Path, snapshot: &Option<RbxSnapshotInstance>) {
|
||||
let mut file = File::create(path.join(SNAPSHOT_EXPECTED_NAME))
|
||||
.expect("Could not open file to write snapshot");
|
||||
|
||||
serde_json::to_writer_pretty(&mut file, snapshot)
|
||||
.expect("Could not serialize snapshot to file");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue