diff --git a/tests/HostCacheSourceStamp/main.cpp b/tests/HostCacheSourceStamp/main.cpp index b6904e8..4110c82 100644 --- a/tests/HostCacheSourceStamp/main.cpp +++ b/tests/HostCacheSourceStamp/main.cpp @@ -119,6 +119,17 @@ int main() { Check(fs::last_write_time(probePcm) == afterCold, "unchanged sources do not rebuild the cache"); Check(ReadStamp(moduleCacheDir) == firstStamp, "unchanged sources keep the same stamp"); + // The compiled project file is the other half of the same hazard: it is + // loaded into this process and must have been compiled against the + // declarations this process was built from. + fs::path projectSo; + for (const fs::directory_entry& entry : fs::recursive_directory_iterator(projectDir)) { + if (entry.path().filename() == "project.so") projectSo = entry.path(); + } + Check(!projectSo.empty(), "the project file was compiled to a project.so"); + if (projectSo.empty()) return 1; + const fs::file_time_type soBeforeEdit = fs::last_write_time(projectSo); + // Now the case the mtime rule cannot see. The edit lands in a module the // probe does not name, because the cached PCMs import each other: a change // anywhere in the set invalidates all of them. @@ -139,6 +150,11 @@ int main() { Check(fs::last_write_time(probePcm) > afterCold, "a content change rebuilds the cache even when the source's mtime is older"); Check(ReadStamp(moduleCacheDir) != firstStamp, "the recorded stamp follows the sources"); + // project.cpp itself is untouched, so only the stamp can force this. It + // once covered the version string alone (the rest sat behind a NUL in a + // format string): a project.so built against a class of another size was + // reused and corrupted the heap when it filled one in. + Check(fs::last_write_time(projectSo) > soBeforeEdit, "changed declarations recompile project.so even though project.cpp is unchanged"); fs::remove_all(scratch, ec);