Skip to content

Commit ee6cf71

Browse files
Copilotnhorton
andauthored
Add specs for committed cache store to prevent file creep (#3)
* Initial plan * Add committed cache specs and populate initial cache files Co-authored-by: nhorton <204146+nhorton@users.noreply.github.com> * Refactor committed cache specs based on code review feedback Co-authored-by: nhorton <204146+nhorton@users.noreply.github.com> * Refactor committed cache specs based on PR feedback - Remove initial cache population block (files now exist) - Add shared examples for cache validation - Move cache entries to top-level let blocks - Configure store with compress: false and raw: true - Use JSON for readable value files - Regenerate value files with readable JSON format Co-authored-by: nhorton <204146+nhorton@users.noreply.github.com> * DRY up spec with let statements for file lists - Extract Dir.glob calls to top-level let statements - Add key_files, value_files, all_files, and key_contents helpers - Simplify shared examples to use let helpers - Simplify test assertions by reusing all_files instead of inline Dir.glob - Reduces code duplication and improves readability Co-authored-by: nhorton <204146+nhorton@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: nhorton <204146+nhorton@users.noreply.github.com>
1 parent 05907e7 commit ee6cf71

8 files changed

+152
-0
lines changed

spec/committed_cache_spec.rb

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# frozen_string_literal: true
2+
3+
require "spec_helper"
4+
require "json"
5+
6+
RSpec.describe "Committed Cache Directory" do
7+
# Use a non-git-ignored directory for cache storage
8+
let(:committed_cache_path) { File.join(__dir__, "fixtures", "committed_cache") }
9+
# Configure store with raw mode to avoid compression
10+
let(:store) { ActiveSupport::Cache::SourceControlCacheStore.new(cache_path: committed_cache_path, compress: false) }
11+
12+
# Predefined cache entries (keys and values as JSON strings for readability)
13+
let(:cache_entries) do
14+
{
15+
"user:123:profile" => { name: "John Doe", email: "john@example.com" }.to_json,
16+
"user:456:profile" => { name: "Jane Smith", email: "jane@example.com" }.to_json,
17+
"config:app:settings" => { theme: "dark", language: "en" }.to_json
18+
}
19+
end
20+
21+
# File list helpers
22+
let(:key_files) { Dir.glob(File.join(committed_cache_path, "*.key")) }
23+
let(:value_files) { Dir.glob(File.join(committed_cache_path, "*.value")) }
24+
let(:all_files) do
25+
Dir.glob(File.join(committed_cache_path, "**", "*"), File::FNM_DOTMATCH)
26+
.reject { |f| File.directory?(f) }
27+
.sort
28+
end
29+
let(:key_contents) { key_files.map { |f| File.read(f) }.sort }
30+
31+
# Shared examples for validating cache state
32+
shared_examples "validates committed cache files" do
33+
it "has the expected number of key files" do
34+
expect(key_files.length).to eq(3)
35+
end
36+
37+
it "has the expected number of value files" do
38+
expect(value_files.length).to eq(3)
39+
end
40+
41+
it "preserves original keys in .key files" do
42+
expect(key_contents).to contain_exactly(*cache_entries.keys.sort)
43+
end
44+
45+
it "has valid value files that can be deserialized" do
46+
# All value files should be readable
47+
value_files.each do |value_file|
48+
expect(File.read(value_file).length).to be > 0
49+
end
50+
end
51+
52+
it "maintains the exact file count" do
53+
# Should have exactly 7 files (3 entries × 2 files each + 1 README.md)
54+
expect(all_files.length).to eq(7)
55+
end
56+
end
57+
58+
describe "cache stability verification" do
59+
# Capture initial state for comparison
60+
let(:initial_file_list) { all_files }
61+
62+
before(:each) do
63+
# Ensure cache entries exist before each test using raw mode
64+
cache_entries.each do |key, value|
65+
store.write(key, value, raw: true)
66+
end
67+
end
68+
69+
it "does not create new files when reading existing entries" do
70+
# Capture state before reading
71+
files_before = initial_file_list
72+
73+
# Read existing entries with raw mode
74+
cache_entries.keys.each do |key|
75+
store.read(key, raw: true)
76+
end
77+
78+
# Verify no new files were created
79+
expect(all_files).to eq(files_before)
80+
end
81+
82+
it "does not create new files when writing to existing keys with same values" do
83+
# Capture state before writing
84+
files_before = initial_file_list
85+
86+
# Write same values to existing keys with raw mode
87+
cache_entries.each do |key, value|
88+
store.write(key, value, raw: true)
89+
end
90+
91+
# Verify no new files were created (same files should exist)
92+
expect(all_files).to eq(files_before)
93+
end
94+
95+
it "has all expected cache files present" do
96+
# Verify that all expected keys exist
97+
cache_entries.each do |key, expected_value|
98+
expect(store.read(key, raw: true)).to eq(expected_value)
99+
end
100+
end
101+
102+
it "does not create new files during multiple read operations" do
103+
# Capture state before reading
104+
files_before = initial_file_list
105+
106+
# Perform multiple read operations
107+
10.times do
108+
cache_entries.keys.each do |key|
109+
store.read(key, raw: true)
110+
end
111+
end
112+
113+
# Verify no new files were created
114+
expect(all_files).to eq(files_before)
115+
end
116+
117+
include_examples "validates committed cache files"
118+
end
119+
120+
describe "file content verification" do
121+
include_examples "validates committed cache files"
122+
123+
it "includes README.md documentation" do
124+
readme_path = File.join(committed_cache_path, "README.md")
125+
expect(File.exist?(readme_path)).to be true
126+
expect(File.read(readme_path)).to include("Committed Cache Directory")
127+
end
128+
end
129+
end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
config:app:settings
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
user:123:profile
Binary file not shown.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Committed Cache Directory
2+
3+
This directory contains cache files that are intentionally committed to source control for testing purposes.
4+
5+
## Purpose
6+
7+
This directory is used by the `committed_cache_spec.rb` test suite to verify that:
8+
1. Cache files can be stored in a non-git-ignored directory
9+
2. Once populated, no new files are created on subsequent runs
10+
3. The cache remains stable across different environments and PRs
11+
12+
## Files
13+
14+
The cache files in this directory are generated by the test suite and should not be manually modified.
15+
They represent a stable set of cache entries used for validation testing.
16+
17+
## Do Not Ignore
18+
19+
**Important:** This directory and its contents should NOT be added to `.gitignore`.
20+
The cache files are intentionally version-controlled to ensure test stability.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
user:456:profile
Binary file not shown.

0 commit comments

Comments
 (0)