Match bDS2 zero-byte route validation
This commit is contained in:
@@ -45,19 +45,24 @@ pub fn validate_site(
|
|||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
let mut actual = HashSet::new();
|
let mut actual = HashSet::new();
|
||||||
|
let mut zero_byte = HashSet::new();
|
||||||
if output_dir.exists() {
|
if output_dir.exists() {
|
||||||
for entry in WalkDir::new(&output_dir).into_iter().filter_map(Result::ok) {
|
for entry in WalkDir::new(&output_dir).into_iter().filter_map(Result::ok) {
|
||||||
if !entry.file_type().is_file() || entry.file_name() != "index.html" {
|
if !entry.file_type().is_file() || entry.file_name() != "index.html" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
let path = relative_path(&output_dir, entry.path());
|
||||||
if entry.metadata().is_ok_and(|metadata| metadata.len() > 0) {
|
if entry.metadata().is_ok_and(|metadata| metadata.len() > 0) {
|
||||||
actual.insert(relative_path(&output_dir, entry.path()));
|
actual.insert(path);
|
||||||
|
} else {
|
||||||
|
zero_byte.insert(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut missing_pages = expected.difference(&actual).cloned().collect::<Vec<_>>();
|
let mut missing_pages = expected.difference(&actual).cloned().collect::<Vec<_>>();
|
||||||
let mut extra_pages = actual.difference(&expected).cloned().collect::<Vec<_>>();
|
let mut extra_pages = actual.difference(&expected).cloned().collect::<Vec<_>>();
|
||||||
|
extra_pages.extend(zero_byte.difference(&expected).cloned());
|
||||||
let generated_at = queries::generated_file_hash::list_generated_file_hashes(conn, project_id)?
|
let generated_at = queries::generated_file_hash::list_generated_file_hashes(conn, project_id)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|file| (file.relative_path, file.updated_at))
|
.map(|file| (file.relative_path, file.updated_at))
|
||||||
@@ -74,6 +79,7 @@ pub fn validate_site(
|
|||||||
|
|
||||||
missing_pages.sort();
|
missing_pages.sort();
|
||||||
extra_pages.sort();
|
extra_pages.sort();
|
||||||
|
extra_pages.dedup();
|
||||||
stale_pages.sort();
|
stale_pages.sort();
|
||||||
stale_pages.dedup();
|
stale_pages.dedup();
|
||||||
|
|
||||||
|
|||||||
@@ -782,12 +782,16 @@ fn site_validation_detects_missing_zero_byte_and_extra_index_routes() {
|
|||||||
std::fs::write(dir.path().join("index.html"), "").unwrap();
|
std::fs::write(dir.path().join("index.html"), "").unwrap();
|
||||||
let extra = dir.path().join("ghost/index.html");
|
let extra = dir.path().join("ghost/index.html");
|
||||||
std::fs::create_dir_all(extra.parent().unwrap()).unwrap();
|
std::fs::create_dir_all(extra.parent().unwrap()).unwrap();
|
||||||
std::fs::write(extra, "ghost").unwrap();
|
std::fs::write(&extra, "ghost").unwrap();
|
||||||
|
let zero_byte_extra = dir.path().join("empty/index.html");
|
||||||
|
std::fs::create_dir_all(zero_byte_extra.parent().unwrap()).unwrap();
|
||||||
|
std::fs::write(&zero_byte_extra, "").unwrap();
|
||||||
|
|
||||||
let report = validate_site(db.conn(), dir.path(), "p1").unwrap();
|
let report = validate_site(db.conn(), dir.path(), "p1").unwrap();
|
||||||
|
|
||||||
assert!(report.missing_pages.contains(&"index.html".to_string()));
|
assert!(report.missing_pages.contains(&"index.html".to_string()));
|
||||||
assert!(report.extra_pages.contains(&"ghost/index.html".to_string()));
|
assert!(report.extra_pages.contains(&"ghost/index.html".to_string()));
|
||||||
|
assert!(report.extra_pages.contains(&"empty/index.html".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -450,7 +450,8 @@ surface SiteValidationSurface {
|
|||||||
rule SiteValidationScan {
|
rule SiteValidationScan {
|
||||||
when: SiteValidationScanRequested()
|
when: SiteValidationScanRequested()
|
||||||
-- Parses <loc> entries from sitemap.xml into expected URL set
|
-- Parses <loc> entries from sitemap.xml into expected URL set
|
||||||
-- Scans HTML output dir for index.html files (zero-byte = missing)
|
-- Scans HTML output dir for index.html files (an expected zero-byte route
|
||||||
|
-- is missing; an unexpected zero-byte route is extra)
|
||||||
-- Compares source .md mtime against generated HTML mtime
|
-- Compares source .md mtime against generated HTML mtime
|
||||||
ensures: SiteValidationReport
|
ensures: SiteValidationReport
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,8 @@ rule ValidateSite {
|
|||||||
-- expected: sitemap-eligible routes derived from published snapshots
|
-- expected: sitemap-eligible routes derived from published snapshots
|
||||||
-- actual: non-empty **/index.html files on disk
|
-- actual: non-empty **/index.html files on disk
|
||||||
-- missing: expected routes with no non-empty index.html
|
-- missing: expected routes with no non-empty index.html
|
||||||
-- extra: non-empty index.html routes absent from the expected set
|
-- extra: index.html routes absent from the expected set, including
|
||||||
|
-- zero-byte files
|
||||||
-- stale: existing post routes whose source mtime is more than one second
|
-- stale: existing post routes whose source mtime is more than one second
|
||||||
-- newer than both the output mtime and tracked generation time
|
-- newer than both the output mtime and tracked generation time
|
||||||
-- Standalone HTML, XML, JSON, assets, Pagefind files, and content hashes are
|
-- Standalone HTML, XML, JSON, assets, Pagefind files, and content hashes are
|
||||||
|
|||||||
Reference in New Issue
Block a user