From 52c31f1de1446f093b1a9c0462f4509d006888af Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 25 Mar 2020 11:57:23 +0100 Subject: [PATCH] test(code_gen): add incremental compilation test --- crates/mun_codegen/Cargo.toml | 1 + crates/mun_codegen/src/mock.rs | 30 +++++++++++++++++++++++ crates/mun_codegen/src/test.rs | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/crates/mun_codegen/Cargo.toml b/crates/mun_codegen/Cargo.toml index 6ed9c2395..d8ffa524e 100644 --- a/crates/mun_codegen/Cargo.toml +++ b/crates/mun_codegen/Cargo.toml @@ -27,6 +27,7 @@ features = ["llvm7-0"] [dev-dependencies] insta = "0.12.0" +parking_lot = "0.10" [build-dependencies] semver = "0.9.0" diff --git a/crates/mun_codegen/src/mock.rs b/crates/mun_codegen/src/mock.rs index e8d4c2a9f..d8562610e 100644 --- a/crates/mun_codegen/src/mock.rs +++ b/crates/mun_codegen/src/mock.rs @@ -1,5 +1,6 @@ use crate::{IrDatabase, OptimizationLevel}; use hir::{FileId, RelativePathBuf, SourceDatabase, SourceRoot, SourceRootId}; +use parking_lot::Mutex; use std::sync::Arc; /// A mock implementation of the IR database. It can be used to set up a simple test case. @@ -12,12 +13,20 @@ use std::sync::Arc; #[derive(Default, Debug)] pub(crate) struct MockDatabase { runtime: salsa::Runtime, + events: Mutex>>>, } impl salsa::Database for MockDatabase { fn salsa_runtime(&self) -> &salsa::Runtime { &self.runtime } + + fn salsa_event(&self, event: impl Fn() -> salsa::Event) { + let mut events = self.events.lock(); + if let Some(events) = &mut *events { + events.push(event()); + } + } } impl MockDatabase { @@ -43,4 +52,25 @@ impl MockDatabase { db.set_context(Arc::new(context)); (db, file_id) } + + pub fn log(&self, f: impl FnOnce()) -> Vec> { + *self.events.lock() = Some(Vec::new()); + f(); + self.events.lock().take().unwrap() + } + + pub fn log_executed(&self, f: impl FnOnce()) -> Vec { + let events = self.log(f); + events + .into_iter() + .filter_map(|e| match e.kind { + // This pretty horrible, but `Debug` is the only way to inspect + // QueryDescriptor at the moment. + salsa::EventKind::WillExecute { database_key } => { + Some(format!("{:?}", database_key)) + } + _ => None, + }) + .collect() + } } diff --git a/crates/mun_codegen/src/test.rs b/crates/mun_codegen/src/test.rs index 494b3179d..9693b9714 100644 --- a/crates/mun_codegen/src/test.rs +++ b/crates/mun_codegen/src/test.rs @@ -479,6 +479,51 @@ fn extern_fn() { ) } +#[test] +fn incremental_compilation() { + let (mut db, file_id) = MockDatabase::with_single_file( + r#" + struct Foo(int); + + pub fn foo(foo: Foo):int { + foo.0 + } + "#, + ); + db.set_optimization_lvl(OptimizationLevel::Default); + db.set_target(Target::host_target().unwrap()); + + { + let events = db.log_executed(|| { + db.file_ir(file_id); + }); + assert!( + format!("{:?}", events).contains("group_ir"), + "{:#?}", + events + ); + assert!(format!("{:?}", events).contains("file_ir"), "{:#?}", events); + } + + db.set_optimization_lvl(OptimizationLevel::Aggressive); + + { + let events = db.log_executed(|| { + db.file_ir(file_id); + }); + println!("events: {:?}", events); + assert!( + !format!("{:?}", events).contains("group_ir"), + "{:#?}", + events + ); + assert!(format!("{:?}", events).contains("file_ir"), "{:#?}", events); + } + + // TODO: Try to disconnect `group_ir` and `file_ir` + // TODO: Add support for multiple files in a group +} + fn test_snapshot(text: &str) { test_snapshot_with_optimization(text, OptimizationLevel::Default); }