summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorsigmaSd <bedisnbiba@gmail.com>2022-11-29 18:43:54 +0100
committerGitHub <noreply@github.com>2022-11-29 18:43:54 +0100
commit2656af2544cd1773e5b7d57e4306a8cec15ef887 (patch)
tree8e809cf8461162c0301f447c002120f2d379813a /cli
parente4fe5ee72ace30ccd1b7b6b15717164cf79f49c4 (diff)
fix(coverage): Error if the emit cache is invalid (#16850)
Diffstat (limited to 'cli')
-rw-r--r--cli/cache/emit.rs29
-rw-r--r--cli/emit.rs6
-rw-r--r--cli/tests/coverage_tests.rs62
-rw-r--r--cli/tests/testdata/coverage/invalid_cache/mod.test.ts2
-rw-r--r--cli/tests/testdata/coverage/invalid_cache/mod_after.ts6
-rw-r--r--cli/tests/testdata/coverage/invalid_cache/mod_before.ts15
-rw-r--r--cli/tools/coverage/mod.rs4
7 files changed, 101 insertions, 23 deletions
diff --git a/cli/cache/emit.rs b/cli/cache/emit.rs
index b3edcbc69..8595627f8 100644
--- a/cli/cache/emit.rs
+++ b/cli/cache/emit.rs
@@ -44,7 +44,7 @@ impl EmitCache {
pub fn get_emit_code(
&self,
specifier: &ModuleSpecifier,
- expected_source_hash: Option<u64>,
+ expected_source_hash: u64,
) -> Option<String> {
let meta_filename = self.get_meta_filename(specifier)?;
let emit_filename = self.get_emit_filename(specifier)?;
@@ -52,10 +52,8 @@ impl EmitCache {
// load and verify the meta data file is for this source and CLI version
let bytes = self.disk_cache.get(&meta_filename).ok()?;
let meta: EmitMetadata = serde_json::from_slice(&bytes).ok()?;
- if let Some(expected_source_hash) = expected_source_hash {
- if meta.source_hash != expected_source_hash.to_string() {
- return None;
- }
+ if meta.source_hash != expected_source_hash.to_string() {
+ return None;
}
// load and verify the emit is for the meta data
@@ -173,31 +171,26 @@ mod test {
let specifier2 =
ModuleSpecifier::from_file_path(temp_dir.path().join("file2.ts"))
.unwrap();
- assert_eq!(cache.get_emit_code(&specifier1, Some(1)), None);
+ assert_eq!(cache.get_emit_code(&specifier1, 1), None);
let emit_code1 = "text1".to_string();
let emit_code2 = "text2".to_string();
cache.set_emit_code(&specifier1, 10, &emit_code1);
cache.set_emit_code(&specifier2, 2, &emit_code2);
// providing the incorrect source hash
- assert_eq!(cache.get_emit_code(&specifier1, Some(5)), None);
+ assert_eq!(cache.get_emit_code(&specifier1, 5), None);
// providing the correct source hash
assert_eq!(
- cache.get_emit_code(&specifier1, Some(10)),
- Some(emit_code1.clone()),
- );
- assert_eq!(cache.get_emit_code(&specifier2, Some(2)), Some(emit_code2));
- // providing no hash
- assert_eq!(
- cache.get_emit_code(&specifier1, None),
+ cache.get_emit_code(&specifier1, 10),
Some(emit_code1.clone()),
);
+ assert_eq!(cache.get_emit_code(&specifier2, 2), Some(emit_code2));
// try changing the cli version (should not load previous ones)
let cache = EmitCache {
disk_cache: disk_cache.clone(),
cli_version: "2.0.0".to_string(),
};
- assert_eq!(cache.get_emit_code(&specifier1, Some(10)), None);
+ assert_eq!(cache.get_emit_code(&specifier1, 10), None);
cache.set_emit_code(&specifier1, 5, &emit_code1);
// recreating the cache should still load the data because the CLI version is the same
@@ -205,12 +198,12 @@ mod test {
disk_cache,
cli_version: "2.0.0".to_string(),
};
- assert_eq!(cache.get_emit_code(&specifier1, Some(5)), Some(emit_code1));
+ assert_eq!(cache.get_emit_code(&specifier1, 5), Some(emit_code1));
// adding when already exists should not cause issue
let emit_code3 = "asdf".to_string();
cache.set_emit_code(&specifier1, 20, &emit_code3);
- assert_eq!(cache.get_emit_code(&specifier1, Some(5)), None);
- assert_eq!(cache.get_emit_code(&specifier1, Some(20)), Some(emit_code3));
+ assert_eq!(cache.get_emit_code(&specifier1, 5), None);
+ assert_eq!(cache.get_emit_code(&specifier1, 20), Some(emit_code3));
}
}
diff --git a/cli/emit.rs b/cli/emit.rs
index 3bf56fae6..ee591b2a1 100644
--- a/cli/emit.rs
+++ b/cli/emit.rs
@@ -12,7 +12,7 @@ use std::sync::Arc;
/// A hashing function that takes the source code and emit options
/// hash then generates a string hash which can be stored to
/// determine if the cached emit is valid or not.
-fn get_source_hash(source_text: &str, emit_options_hash: u64) -> u64 {
+pub fn get_source_hash(source_text: &str, emit_options_hash: u64) -> u64 {
FastInsecureHasher::new()
.write_str(source_text)
.write_u64(emit_options_hash)
@@ -30,9 +30,7 @@ pub fn emit_parsed_source(
) -> Result<String, AnyError> {
let source_hash = get_source_hash(source, emit_config_hash);
- if let Some(emit_code) =
- emit_cache.get_emit_code(specifier, Some(source_hash))
- {
+ if let Some(emit_code) = emit_cache.get_emit_code(specifier, source_hash) {
Ok(emit_code)
} else {
// this will use a cached version if it exists
diff --git a/cli/tests/coverage_tests.rs b/cli/tests/coverage_tests.rs
index 1806417ea..6515fd6ec 100644
--- a/cli/tests/coverage_tests.rs
+++ b/cli/tests/coverage_tests.rs
@@ -26,6 +26,68 @@ mod coverage {
no_snaps_included("no_snaps_included", "ts");
}
+ #[test]
+ fn error_if_invalid_cache() {
+ let deno_dir = TempDir::new();
+ let deno_dir_path = deno_dir.path();
+ let tempdir = TempDir::new();
+ let tempdir = tempdir.path().join("cov");
+
+ let invalid_cache_path =
+ util::testdata_path().join("coverage/invalid_cache");
+ let mod_before_path = util::testdata_path()
+ .join(&invalid_cache_path)
+ .join("mod_before.ts");
+ let mod_after_path = util::testdata_path()
+ .join(&invalid_cache_path)
+ .join("mod_after.ts");
+ let mod_test_path = util::testdata_path()
+ .join(&invalid_cache_path)
+ .join("mod.test.ts");
+
+ let mod_temp_path = deno_dir_path.join("mod.ts");
+ let mod_test_temp_path = deno_dir_path.join("mod.test.ts");
+
+ // Write the inital mod.ts file
+ std::fs::copy(mod_before_path, &mod_temp_path).unwrap();
+ // And the test file
+ std::fs::copy(mod_test_path, &mod_test_temp_path).unwrap();
+
+ // Generate coverage
+ let status = util::deno_cmd_with_deno_dir(&deno_dir)
+ .current_dir(deno_dir_path)
+ .arg("test")
+ .arg("--quiet")
+ .arg(format!("--coverage={}", tempdir.to_str().unwrap()))
+ .stdout(std::process::Stdio::piped())
+ .stderr(std::process::Stdio::inherit())
+ .status()
+ .unwrap();
+
+ assert!(status.success());
+
+ // Modify the file between deno test and deno coverage, thus invalidating the cache
+ std::fs::copy(mod_after_path, mod_temp_path).unwrap();
+
+ let output = util::deno_cmd_with_deno_dir(&deno_dir)
+ .current_dir(deno_dir_path)
+ .arg("coverage")
+ .arg(format!("{}/", tempdir.to_str().unwrap()))
+ .stdout(std::process::Stdio::piped())
+ .stderr(std::process::Stdio::piped())
+ .output()
+ .unwrap();
+
+ assert!(output.stdout.is_empty());
+
+ // Expect error
+ let error =
+ util::strip_ansi_codes(std::str::from_utf8(&output.stderr).unwrap())
+ .to_string();
+ assert!(error.contains("error: Missing transpiled source code"));
+ assert!(error.contains("Before generating coverage report, run `deno test --coverage` to ensure consistent state."));
+ }
+
fn run_coverage_text(test_name: &str, extension: &str) {
let deno_dir = TempDir::new();
let tempdir = TempDir::new();
diff --git a/cli/tests/testdata/coverage/invalid_cache/mod.test.ts b/cli/tests/testdata/coverage/invalid_cache/mod.test.ts
new file mode 100644
index 000000000..5815d07a3
--- /dev/null
+++ b/cli/tests/testdata/coverage/invalid_cache/mod.test.ts
@@ -0,0 +1,2 @@
+import { test } from "./mod.ts";
+Deno.test("test", () => void test());
diff --git a/cli/tests/testdata/coverage/invalid_cache/mod_after.ts b/cli/tests/testdata/coverage/invalid_cache/mod_after.ts
new file mode 100644
index 000000000..294dc0843
--- /dev/null
+++ b/cli/tests/testdata/coverage/invalid_cache/mod_after.ts
@@ -0,0 +1,6 @@
+export function test() {
+ return 42;
+}
+if (import.meta.main) {
+ test();
+}
diff --git a/cli/tests/testdata/coverage/invalid_cache/mod_before.ts b/cli/tests/testdata/coverage/invalid_cache/mod_before.ts
new file mode 100644
index 000000000..ea52ccbce
--- /dev/null
+++ b/cli/tests/testdata/coverage/invalid_cache/mod_before.ts
@@ -0,0 +1,15 @@
+export function test() {
+ console.log("1");
+ console.log("2");
+ console.log("3");
+ console.log("4");
+ console.log("5");
+ console.log("6");
+ console.log("7");
+ console.log("8");
+ console.log("9");
+ return 42;
+}
+if (import.meta.main) {
+ test();
+}
diff --git a/cli/tools/coverage/mod.rs b/cli/tools/coverage/mod.rs
index b9bbe14f2..f19cdfa3f 100644
--- a/cli/tools/coverage/mod.rs
+++ b/cli/tools/coverage/mod.rs
@@ -3,6 +3,7 @@
use crate::args::CoverageFlags;
use crate::args::Flags;
use crate::colors;
+use crate::emit::get_source_hash;
use crate::proc_state::ProcState;
use crate::tools::fmt::format_json;
use crate::util::fs::collect_files;
@@ -677,7 +678,8 @@ pub async fn cover_files(
| MediaType::Mts
| MediaType::Cts
| MediaType::Tsx => {
- match ps.emit_cache.get_emit_code(&file.specifier, None) {
+ let source_hash = get_source_hash(&file.source, ps.emit_options_hash);
+ match ps.emit_cache.get_emit_code(&file.specifier, source_hash) {
Some(code) => code,
None => {
return Err(anyhow!(