From de54a87026dc06930a63922d209013b6fbafa5a4 Mon Sep 17 00:00:00 2001 From: lodekeeper-z Date: Sat, 21 Mar 2026 23:12:03 +0000 Subject: [PATCH] test(cache): add unit tests for SlashingsCache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive unit tests covering: - initEmpty creates empty cache with null slot - initFromValidators populates slashed bits correctly - isInitialized checks slot matching - recordValidatorSlashing requires initialization - recordValidatorSlashing grows bitset capacity - clone creates independent copy 🤖 Generated with AI assistance --- .../cache/slashings_cache.zig | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/src/state_transition/cache/slashings_cache.zig b/src/state_transition/cache/slashings_cache.zig index 50f62b9fc..1753701ea 100644 --- a/src/state_transition/cache/slashings_cache.zig +++ b/src/state_transition/cache/slashings_cache.zig @@ -100,3 +100,100 @@ pub fn buildFromStateIfNeeded( slashings_cache.deinit(); slashings_cache.* = new_cache; } + +test "SlashingsCache - initEmpty creates empty cache" { + const allocator = std.testing.allocator; + var cache = try SlashingsCache.initEmpty(allocator); + defer cache.deinit(); + + try std.testing.expect(cache.latest_block_slot == null); + try std.testing.expect(!cache.isSlashed(0)); + try std.testing.expect(!cache.isSlashed(100)); +} + +test "SlashingsCache - initFromValidators populates slashed bits" { + const allocator = std.testing.allocator; + var validators: [5]Validator = undefined; + @memset(std.mem.asBytes(&validators), 0); + + // Mark validators 1 and 3 as slashed + validators[1].slashed = true; + validators[3].slashed = true; + + var cache = try SlashingsCache.initFromValidators(allocator, 42, &validators); + defer cache.deinit(); + + try std.testing.expectEqual(@as(?Slot, 42), cache.latest_block_slot); + try std.testing.expect(!cache.isSlashed(0)); + try std.testing.expect(cache.isSlashed(1)); + try std.testing.expect(!cache.isSlashed(2)); + try std.testing.expect(cache.isSlashed(3)); + try std.testing.expect(!cache.isSlashed(4)); +} + +test "SlashingsCache - isInitialized checks slot" { + const allocator = std.testing.allocator; + var cache = try SlashingsCache.initEmpty(allocator); + defer cache.deinit(); + + try std.testing.expect(!cache.isInitialized(0)); + try std.testing.expect(!cache.isInitialized(42)); + + cache.updateLatestBlockSlot(42); + try std.testing.expect(cache.isInitialized(42)); + try std.testing.expect(!cache.isInitialized(43)); +} + +test "SlashingsCache - recordValidatorSlashing requires initialization" { + const allocator = std.testing.allocator; + var cache = try SlashingsCache.initEmpty(allocator); + defer cache.deinit(); + + // Should fail when not initialized + try std.testing.expectError(error.SlashingsCacheUninitialized, cache.recordValidatorSlashing(10, 5)); + + // Initialize and try again + cache.updateLatestBlockSlot(10); + try cache.recordValidatorSlashing(10, 5); + try std.testing.expect(cache.isSlashed(5)); + + // Wrong slot should fail + try std.testing.expectError(error.SlashingsCacheUninitialized, cache.recordValidatorSlashing(11, 6)); +} + +test "SlashingsCache - recordValidatorSlashing grows capacity" { + const allocator = std.testing.allocator; + var cache = try SlashingsCache.initEmpty(allocator); + defer cache.deinit(); + + cache.updateLatestBlockSlot(0); + + // Record slashing for a high index — should grow the bitset + try cache.recordValidatorSlashing(0, 1000); + try std.testing.expect(cache.isSlashed(1000)); + try std.testing.expect(!cache.isSlashed(999)); +} + +test "SlashingsCache - clone creates independent copy" { + const allocator = std.testing.allocator; + var validators: [3]Validator = undefined; + @memset(std.mem.asBytes(&validators), 0); + validators[1].slashed = true; + + var original = try SlashingsCache.initFromValidators(allocator, 10, &validators); + defer original.deinit(); + + var cloned = try original.clone(allocator); + defer cloned.deinit(); + + // Both should see validator 1 as slashed + try std.testing.expect(cloned.isSlashed(1)); + try std.testing.expectEqual(@as(?Slot, 10), cloned.latest_block_slot); + + // Modify original — clone should be unaffected + original.updateLatestBlockSlot(20); + try original.recordValidatorSlashing(20, 2); + + try std.testing.expectEqual(@as(?Slot, 10), cloned.latest_block_slot); + try std.testing.expect(!cloned.isSlashed(2)); +}