Skip to content

Commit

Permalink
Add asset graph request tests - part 1 of X (#9876)
Browse files Browse the repository at this point in the history
* Fix inmemory fs and add a couple of tests

* Fix problems preventing build from running

* Some dependencies weren't forwarded properly (options on transformer)
* We need to have core-path resolving to a valid location

* Fix bugs and warnings

* Clean-up long function

---------

Co-authored-by: pyamada (RDE) <pyamada@atlassian.com>
  • Loading branch information
yamadapc and pyamada-atlassian authored Jul 31, 2024
1 parent 2aac813 commit 2731911
Show file tree
Hide file tree
Showing 13 changed files with 307 additions and 51 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 12 additions & 6 deletions crates/parcel/src/project_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub fn infer_project_root(

#[cfg(test)]
mod tests {
use std::{path::MAIN_SEPARATOR_STR, sync::Arc};
use std::sync::Arc;

use parcel_filesystem::in_memory_file_system::InMemoryFileSystem;
use parcel_resolver::FileSystem;
Expand Down Expand Up @@ -211,8 +211,14 @@ mod tests {
}
}

#[cfg(target_os = "windows")]
fn root() -> PathBuf {
PathBuf::from(MAIN_SEPARATOR_STR)
PathBuf::from("C:\\")
}

#[cfg(not(target_os = "windows"))]
fn root() -> PathBuf {
PathBuf::from("/")
}

fn cwd() -> PathBuf {
Expand All @@ -226,7 +232,7 @@ mod tests {
let fs = Arc::new(InMemoryFileSystem::default());
let root = root();

fs.set_current_working_directory(cwd());
fs.set_current_working_directory(&cwd());
fs.write_file(&root.join(lockfile), String::from("{}"));

assert_eq!(
Expand All @@ -250,7 +256,7 @@ mod tests {
let entries = vec![String::from("src/a.js")];
let fs = Arc::new(InMemoryFileSystem::default());

fs.set_current_working_directory(cwd.clone());
fs.set_current_working_directory(&cwd);
fs.write_file(&root().join(lockfile), String::from("{}"));
fs.write_file(&cwd.join(lockfile), String::from("{}"));

Expand All @@ -277,7 +283,7 @@ mod tests {

let fs = Arc::new(InMemoryFileSystem::default());

fs.set_current_working_directory(cwd.clone());
fs.set_current_working_directory(&cwd);
fs.write_file(&root().join(lockfile), String::from("{}"));
fs.write_file(
&cwd.join("packages").join("foo").join(lockfile),
Expand All @@ -304,7 +310,7 @@ mod tests {
let root = root();
let vcs = root.join(vcs);

fs.set_current_working_directory(cwd());
fs.set_current_working_directory(&cwd());
fs.create_directory(&vcs)
.expect(format!("Expected {} directory to be created", vcs.display()).as_str());

Expand Down
4 changes: 3 additions & 1 deletion crates/parcel/src/request_tracker/request_graph.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use petgraph::stable_graph::StableDiGraph;

use crate::request_tracker::RunRequestError;

pub type RequestGraph<T> = StableDiGraph<RequestNode<T>, RequestEdgeType>;

#[derive(Debug)]
pub enum RequestNode<T> {
Error(String),
Error(RunRequestError),
Root,
Incomplete,
Valid(T),
Expand Down
9 changes: 7 additions & 2 deletions crates/parcel/src/request_tracker/request_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@ impl RequestTracker {
#[allow(unused)]
pub fn run_request(&mut self, request: impl Request) -> anyhow::Result<RequestResult> {
let thread_pool = rayon::ThreadPoolBuilder::new()
.thread_name(|count| format!("RequestTracker-{}", count))
.num_threads(num_cpus::get() + 4)
.panic_handler(|failure| {
tracing::error!("Lost thread from thread-pool. This is a bug in parcel. Builds may stall.");
std::process::exit(1);
})
.build()?;
thread_pool.in_place_scope(|scope| {
let request_id = request.id();
Expand Down Expand Up @@ -229,7 +234,7 @@ impl RequestTracker {

*request_node = match result {
Ok(result) => RequestNode::Valid(result.result.clone()),
Err(error) => RequestNode::Error(error.to_string()),
Err(error) => RequestNode::Error(anyhow!(error.to_string())),
};

Ok(())
Expand All @@ -255,7 +260,7 @@ impl RequestTracker {
match request_node {
RequestNode::Root => Err(diagnostic_error!("Impossible")),
RequestNode::Incomplete => Err(diagnostic_error!("Impossible")),
RequestNode::Error(error) => Err(anyhow!(error.clone())),
RequestNode::Error(error) => Err(anyhow!(error.to_string())),
RequestNode::Valid(value) => Ok(value.clone()),
}
}
Expand Down
189 changes: 186 additions & 3 deletions crates/parcel/src/requests/asset_graph_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,198 @@ impl AssetGraphBuilder {

#[cfg(test)]
mod test {
use crate::requests::AssetGraphRequest;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use tracing::Level;

use parcel_core::types::Code;
use parcel_filesystem::in_memory_file_system::InMemoryFileSystem;
use parcel_filesystem::FileSystem;

use crate::requests::{AssetGraphRequest, RequestResult};
use crate::test_utils::{request_tracker, RequestTrackerTestOptions};

#[test]
fn test_asset_graph_request() {
fn test_asset_graph_request_with_no_entries() {
let options = RequestTrackerTestOptions::default();
let mut request_tracker = request_tracker(options);

let asset_graph_request = AssetGraphRequest {};
let _ = request_tracker.run_request(asset_graph_request);
let RequestResult::AssetGraph(asset_graph_request_result) =
request_tracker.run_request(asset_graph_request).unwrap()
else {
assert!(false, "Got invalid result");
return;
};

assert_eq!(asset_graph_request_result.graph.assets.len(), 0);
assert_eq!(asset_graph_request_result.graph.dependencies.len(), 0);
}

#[test]
fn test_asset_graph_request_with_a_single_entry_with_no_dependencies() {
let _ = tracing_subscriber::FmtSubscriber::builder()
.with_max_level(Level::DEBUG)
.try_init();

let mut options = RequestTrackerTestOptions::default();
let fs = InMemoryFileSystem::default();
#[cfg(not(target_os = "windows"))]
let temporary_dir = PathBuf::from("/parcel_tests");
#[cfg(target_os = "windows")]
let temporary_dir = PathBuf::from("c:/windows/parcel_tests");
assert!(temporary_dir.is_absolute());
fs.create_directory(&temporary_dir).unwrap();
fs.set_current_working_directory(&temporary_dir); // <- resolver is broken without this
options
.parcel_options
.entries
.push(temporary_dir.join("entry.js").to_str().unwrap().to_string());
options.project_root = temporary_dir.clone();
options.search_path = temporary_dir.clone();
fs.write_file(
&temporary_dir.join("entry.js"),
String::from(
r#"
console.log('hello world');
"#,
),
);
options.fs = Arc::new(fs);

let mut request_tracker = request_tracker(options);

let asset_graph_request = AssetGraphRequest {};
let RequestResult::AssetGraph(asset_graph_request_result) = request_tracker
.run_request(asset_graph_request)
.expect("Failed to run asset graph request")
else {
assert!(false, "Got invalid result");
return;
};

assert_eq!(asset_graph_request_result.graph.assets.len(), 1);
assert_eq!(asset_graph_request_result.graph.dependencies.len(), 1);
assert_eq!(
asset_graph_request_result
.graph
.assets
.get(0)
.unwrap()
.asset
.file_path,
temporary_dir.join("entry.js")
);
assert_eq!(
asset_graph_request_result
.graph
.assets
.get(0)
.unwrap()
.asset
.code,
Arc::new(Code::from(
String::from(
r#"
console.log('hello world');
"#
)
.trim_start()
.trim_end_matches(|p| p == ' ')
.to_string()
))
);
}

#[test]
fn test_asset_graph_request_with_a_couple_of_entries() {
let _ = tracing_subscriber::FmtSubscriber::builder()
.with_max_level(Level::TRACE)
.try_init();

let mut options = RequestTrackerTestOptions::default();
let fs = InMemoryFileSystem::default();
#[cfg(not(target_os = "windows"))]
let temporary_dir = PathBuf::from("/parcel_tests");
#[cfg(target_os = "windows")]
let temporary_dir = PathBuf::from("C:\\windows\\parcel_tests");
fs.create_directory(&temporary_dir).unwrap();
fs.set_current_working_directory(&temporary_dir); // <- resolver is broken without this
options
.parcel_options
.entries
.push(temporary_dir.join("entry.js").to_str().unwrap().to_string());
options.project_root = temporary_dir.clone();
options.search_path = temporary_dir.clone();
options.parcel_options.core_path = temporary_dir.clone().join("parcel_core");
fs.write_file(
&temporary_dir.join("entry.js"),
String::from(
r#"
import {x} from './a';
import {y} from './b';
console.log(x + y);
"#,
),
);
fs.write_file(
&temporary_dir.join("a.js"),
String::from(
r#"
export const x = 15;
"#,
),
);
fs.write_file(
&temporary_dir.join("b.js"),
String::from(
r#"
export const y = 27;
"#,
),
);
setup_core_modules(&fs, &options.parcel_options.core_path);
options.fs = Arc::new(fs);

let mut request_tracker = request_tracker(options);

let asset_graph_request = AssetGraphRequest {};
let RequestResult::AssetGraph(asset_graph_request_result) = request_tracker
.run_request(asset_graph_request)
.expect("Failed to run asset graph request")
else {
assert!(false, "Got invalid result");
return;
};

// Entry, 2 assets + helpers file
assert_eq!(asset_graph_request_result.graph.assets.len(), 4);
// Entry, entry to assets (2), assets to helpers (2)
assert_eq!(asset_graph_request_result.graph.dependencies.len(), 5);

assert_eq!(
asset_graph_request_result
.graph
.assets
.get(0)
.unwrap()
.asset
.file_path,
temporary_dir.join("entry.js")
);
}

fn setup_core_modules(fs: &InMemoryFileSystem, core_path: &Path) {
let transformer_path = core_path
.join("node_modules")
.join("@parcel/transformer-js");
let source_path = transformer_path.join("src");
fs.create_directory(&source_path).unwrap();
fs.write_file(&transformer_path.join("package.json"), String::from("{}"));
fs.write_file(
&source_path.join("esmodule-helpers.js"),
String::from("/* helpers */"),
);
}
}
2 changes: 2 additions & 0 deletions crates/parcel/src/requests/target_request/package_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ pub struct PackageJson {

#[derive(Debug, Clone, Deserialize)]
pub enum SourceField {
#[allow(unused)]
Source(String),
#[allow(unused)]
Sources(Vec<String>),
}

Expand Down
13 changes: 9 additions & 4 deletions crates/parcel/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::path::PathBuf;
use std::sync::Arc;

use parcel_config::parcel_config_fixtures::default_config;
use parcel_core::types::BuildMode;
use parcel_core::{
config_loader::ConfigLoader,
plugin::{PluginContext, PluginLogger, PluginOptions},
Expand Down Expand Up @@ -37,6 +38,7 @@ pub struct RequestTrackerTestOptions {
pub plugins: Option<PluginsRef>,
pub project_root: PathBuf,
pub search_path: PathBuf,
pub parcel_options: ParcelOptions,
}

impl Default for RequestTrackerTestOptions {
Expand All @@ -46,6 +48,7 @@ impl Default for RequestTrackerTestOptions {
plugins: None,
project_root: PathBuf::default(),
search_path: PathBuf::default(),
parcel_options: ParcelOptions::default(),
}
}
}
Expand All @@ -56,6 +59,7 @@ pub(crate) fn request_tracker(options: RequestTrackerTestOptions) -> RequestTrac
plugins,
project_root,
search_path,
parcel_options,
} = options;

let config_loader = Arc::new(ConfigLoader {
Expand All @@ -67,17 +71,18 @@ pub(crate) fn request_tracker(options: RequestTrackerTestOptions) -> RequestTrac
let plugins = plugins.unwrap_or_else(|| {
config_plugins(PluginContext {
config: Arc::clone(&config_loader),
options: Arc::new(PluginOptions::default()),
options: Arc::new(PluginOptions {
mode: BuildMode::default(),
project_root: project_root.clone(),
}),
logger: PluginLogger::default(),
})
});

let parcel_options = Arc::new(ParcelOptions::default());

RequestTracker::new(
Arc::clone(&config_loader),
fs,
parcel_options,
Arc::new(parcel_options),
plugins,
project_root,
)
Expand Down
2 changes: 1 addition & 1 deletion crates/parcel_config/src/parcel_rc_config_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ mod tests {
let default_config = default_config(Arc::new(project_root.join(".parcelrc")));
let files = vec![default_config.path.clone()];

fs.set_current_working_directory(PathBuf::from("/cwd"));
fs.set_current_working_directory(Path::new("/cwd"));
fs.write_file(&default_config.path, default_config.parcel_rc);

let parcel_config = ParcelRcConfigLoader::new(fs, Arc::new(MockPackageManager::default()))
Expand Down
Loading

0 comments on commit 2731911

Please sign in to comment.