Skip to content

Commit e62b1d6

Browse files
Copilotnhorton
andcommitted
Add committed cache specs and populate initial cache files
Co-authored-by: nhorton <[email protected]>
1 parent 3ea6a03 commit e62b1d6

8 files changed

+187
-0
lines changed

spec/committed_cache_spec.rb

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# frozen_string_literal: true
2+
3+
require "spec_helper"
4+
5+
RSpec.describe "Committed Cache Directory" do
6+
# Use a non-git-ignored directory for cache storage
7+
let(:committed_cache_path) { File.join(__dir__, "fixtures", "committed_cache") }
8+
let(:store) { ActiveSupport::Cache::SourceControlCacheStore.new(cache_path: committed_cache_path) }
9+
10+
# Track files that exist at the start of the test suite
11+
let(:initial_files) do
12+
if File.directory?(committed_cache_path)
13+
Dir.glob(File.join(committed_cache_path, "**", "*"), File::FNM_DOTMATCH)
14+
.reject { |f| File.directory?(f) }
15+
.sort
16+
else
17+
[]
18+
end
19+
end
20+
21+
describe "initial cache population" do
22+
it "creates the cache directory if it doesn't exist" do
23+
expect(File.directory?(committed_cache_path)).to be true
24+
end
25+
26+
it "populates cache with predefined entries" do
27+
# Write predefined cache entries that will be committed
28+
store.write("user:123:profile", { name: "John Doe", email: "[email protected]" })
29+
store.write("user:456:profile", { name: "Jane Smith", email: "[email protected]" })
30+
store.write("config:app:settings", { theme: "dark", language: "en" })
31+
32+
# Verify the entries were written
33+
expect(store.read("user:123:profile")).to eq({ name: "John Doe", email: "[email protected]" })
34+
expect(store.read("user:456:profile")).to eq({ name: "Jane Smith", email: "[email protected]" })
35+
expect(store.read("config:app:settings")).to eq({ theme: "dark", language: "en" })
36+
end
37+
38+
it "creates .key and .value files for each entry" do
39+
# Ensure files exist
40+
cache_files = Dir.glob(File.join(committed_cache_path, "*"))
41+
42+
# We expect at least 6 files (3 entries × 2 files each)
43+
expect(cache_files.length).to be >= 6
44+
45+
# Check that we have both .key and .value files
46+
key_files = cache_files.select { |f| f.end_with?(".key") }
47+
value_files = cache_files.select { |f| f.end_with?(".value") }
48+
49+
expect(key_files.length).to be >= 3
50+
expect(value_files.length).to be >= 3
51+
end
52+
end
53+
54+
describe "cache stability verification" do
55+
before(:all) do
56+
# Capture the state of files before any tests run
57+
committed_cache_path = File.join(__dir__, "fixtures", "committed_cache")
58+
store = ActiveSupport::Cache::SourceControlCacheStore.new(cache_path: committed_cache_path)
59+
60+
# Ensure initial cache entries exist
61+
store.write("user:123:profile", { name: "John Doe", email: "[email protected]" })
62+
store.write("user:456:profile", { name: "Jane Smith", email: "[email protected]" })
63+
store.write("config:app:settings", { theme: "dark", language: "en" })
64+
65+
@initial_file_list = Dir.glob(File.join(committed_cache_path, "**", "*"), File::FNM_DOTMATCH)
66+
.reject { |f| File.directory?(f) }
67+
.sort
68+
end
69+
70+
it "does not create new files when reading existing entries" do
71+
# Read existing entries
72+
store.read("user:123:profile")
73+
store.read("user:456:profile")
74+
store.read("config:app:settings")
75+
76+
# Get current file list
77+
current_files = Dir.glob(File.join(committed_cache_path, "**", "*"), File::FNM_DOTMATCH)
78+
.reject { |f| File.directory?(f) }
79+
.sort
80+
81+
# Verify no new files were created
82+
expect(current_files).to eq(@initial_file_list)
83+
end
84+
85+
it "does not create new files when writing to existing keys with same values" do
86+
# Write same values to existing keys
87+
store.write("user:123:profile", { name: "John Doe", email: "[email protected]" })
88+
store.write("user:456:profile", { name: "Jane Smith", email: "[email protected]" })
89+
store.write("config:app:settings", { theme: "dark", language: "en" })
90+
91+
# Get current file list
92+
current_files = Dir.glob(File.join(committed_cache_path, "**", "*"), File::FNM_DOTMATCH)
93+
.reject { |f| File.directory?(f) }
94+
.sort
95+
96+
# Verify no new files were created (same files should exist)
97+
expect(current_files).to eq(@initial_file_list)
98+
end
99+
100+
it "has all expected cache files present" do
101+
# Verify that all expected keys exist
102+
expect(store.read("user:123:profile")).to eq({ name: "John Doe", email: "[email protected]" })
103+
expect(store.read("user:456:profile")).to eq({ name: "Jane Smith", email: "[email protected]" })
104+
expect(store.read("config:app:settings")).to eq({ theme: "dark", language: "en" })
105+
end
106+
107+
it "maintains the exact file count" do
108+
current_files = Dir.glob(File.join(committed_cache_path, "**", "*"), File::FNM_DOTMATCH)
109+
.reject { |f| File.directory?(f) }
110+
.sort
111+
112+
# Should have exactly 7 files (3 entries × 2 files each + 1 README.md)
113+
expect(current_files.length).to eq(7)
114+
end
115+
116+
it "does not create new files during multiple read operations" do
117+
# Perform multiple read operations
118+
10.times do
119+
store.read("user:123:profile")
120+
store.read("user:456:profile")
121+
store.read("config:app:settings")
122+
end
123+
124+
# Get current file list
125+
current_files = Dir.glob(File.join(committed_cache_path, "**", "*"), File::FNM_DOTMATCH)
126+
.reject { |f| File.directory?(f) }
127+
.sort
128+
129+
# Verify no new files were created
130+
expect(current_files).to eq(@initial_file_list)
131+
end
132+
end
133+
134+
describe "file content verification" do
135+
it "preserves original keys in .key files" do
136+
key_files = Dir.glob(File.join(committed_cache_path, "*.key"))
137+
expect(key_files.length).to eq(3)
138+
139+
# Read all key files and verify they contain expected keys
140+
key_contents = key_files.map { |f| File.read(f) }.sort
141+
expect(key_contents).to contain_exactly(
142+
"config:app:settings",
143+
"user:123:profile",
144+
"user:456:profile"
145+
)
146+
end
147+
148+
it "has valid value files that can be deserialized" do
149+
value_files = Dir.glob(File.join(committed_cache_path, "*.value"))
150+
expect(value_files.length).to eq(3)
151+
152+
# All value files should be readable and deserializable
153+
value_files.each do |value_file|
154+
expect(File.read(value_file).length).to be > 0
155+
end
156+
end
157+
158+
it "includes README.md documentation" do
159+
readme_path = File.join(committed_cache_path, "README.md")
160+
expect(File.exist?(readme_path)).to be true
161+
expect(File.read(readme_path)).to include("Committed Cache Directory")
162+
end
163+
end
164+
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)