authorgravatar for leroycepearson@geemili.xyzLeRoyce Pearson <leroycepearson@geemili.xyz> 2020-04-14 21:39:34-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-25 13:48:43-04:00
log967b9825a7b57586cd34f51d9b915505ffbd455d
tree3b72c3274ddce6d96bac307f5f8e9b3a834b7564
parent4254d389d3b21e3c7613c327810b47483b92329b

Add "no file inputs" test

It checks whether the cache will respond correctly to inputs that don't initially depend on filesystem state. In that case, we have to check for the existence of a manifest file, instead of relying on reading the list of entries to tell us if the cache is invalid.

1 files changed, 54 insertions(+), 10 deletions(-)

lib/std/cache_hash.zig+54-10
......@@ -34,7 +34,6 @@ pub const CacheHash = struct {
3434 manifest_dir: fs.Dir,
3535 manifest_file: ?fs.File,
3636 manifest_dirty: bool,
37 force_check_manifest: bool,
3837 files: ArrayList(File),
3938 b64_digest: [BASE64_DIGEST_LEN]u8,
4039
......@@ -48,7 +47,6 @@ pub const CacheHash = struct {
4847 .manifest_dir = manifest_dir,
4948 .manifest_file = null,
5049 .manifest_dirty = false,
51 .force_check_manifest = false,
5250 .files = ArrayList(File).init(alloc),
5351 .b64_digest = undefined,
5452 };
......@@ -104,22 +102,37 @@ pub const CacheHash = struct {
104102
105103 base64_encoder.encode(self.b64_digest[0..], &bin_digest);
106104
107 if (self.files.toSlice().len == 0 and !self.force_check_manifest) {
108 return self.b64_digest;
109 }
110
111105 self.blake3 = Blake3.init();
112106 self.blake3.update(&bin_digest);
113107
114 {
115 const manifest_file_path = try fmt.allocPrint(self.alloc, "{}.txt", .{self.b64_digest});
116 defer self.alloc.free(manifest_file_path);
108 const manifest_file_path = try fmt.allocPrint(self.alloc, "{}.txt", .{self.b64_digest});
109 defer self.alloc.free(manifest_file_path);
117110
111 if (self.files.items.len != 0) {
118112 self.manifest_file = try self.manifest_dir.createFile(manifest_file_path, .{
119113 .read = true,
120114 .truncate = false,
121115 .lock = .Exclusive,
122116 });
117 } else {
118 // If there are no file inputs, we check if the manifest file exists instead of
119 // comparing the hashes on the files used for the cached item
120 self.manifest_file = self.manifest_dir.openFile(manifest_file_path, .{
121 .read = true,
122 .write = true,
123 .lock = .Exclusive,
124 }) catch |err| switch (err) {
125 error.FileNotFound => {
126 self.manifest_dirty = true;
127 self.manifest_file = try self.manifest_dir.createFile(manifest_file_path, .{
128 .read = true,
129 .truncate = false,
130 .lock = .Exclusive,
131 });
132 return null;
133 },
134 else => |e| return e,
135 };
123136 }
124137
125138 // TODO: Figure out a good max value?
......@@ -206,7 +219,7 @@ pub const CacheHash = struct {
206219 return null;
207220 }
208221
209 if (idx < input_file_count or idx == 0) {
222 if (idx < input_file_count) {
210223 self.manifest_dirty = true;
211224 while (idx < input_file_count) : (idx += 1) {
212225 var cache_hash_file = &self.files.items[idx];
......@@ -438,3 +451,34 @@ test "check that changing a file makes cache fail" {
438451 try cwd.deleteTree(temp_manifest_dir);
439452 try cwd.deleteFile(temp_file);
440453}
454
455test "no file inputs" {
456 const cwd = fs.cwd();
457 const temp_manifest_dir = "no_file_inputs_manifest_dir";
458 defer cwd.deleteTree(temp_manifest_dir) catch unreachable;
459
460 var digest1: [BASE64_DIGEST_LEN]u8 = undefined;
461 var digest2: [BASE64_DIGEST_LEN]u8 = undefined;
462
463 {
464 var ch = try CacheHash.init(testing.allocator, temp_manifest_dir);
465 defer ch.release();
466
467 ch.add("1234");
468
469 // There should be nothing in the cache
470 testing.expectEqual(@as(?[64]u8, null), try ch.hit());
471
472 digest1 = ch.final();
473 }
474 {
475 var ch = try CacheHash.init(testing.allocator, temp_manifest_dir);
476 defer ch.release();
477
478 ch.add("1234");
479
480 digest2 = (try ch.hit()).?;
481 }
482
483 testing.expectEqual(digest1, digest2);
484}