Skip to content

Commit 6b8226c

Browse files
Make the request property tests portable across release lines
Calls pass only the keywords the formatter on this line accepts, so an unsupported keyword is never mistaken for a rejected input and the test can't pass vacuously. Also shrinks the gzip bomb test's payload. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
1 parent 62d5ad1 commit 6b8226c

2 files changed

Lines changed: 38 additions & 16 deletions

File tree

‎test/protocol/test_request_formatter_properties.rb‎

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,28 @@
9191
end
9292
end
9393

94+
# The formatter's methods and keywords differ between release lines. Calls go
95+
# through call_formatter, which passes only the keywords this version
96+
# accepts, so an unsupported keyword never looks like a rejected input.
97+
keyword_types = %i[key keyreq].freeze
98+
99+
define_method(:keywords_for) do |name|
100+
formatter.method(name).parameters.filter_map { |type, param| param if keyword_types.include?(type) }
101+
end
102+
103+
define_method(:call_formatter) do |name, *positional, **keywords|
104+
formatter.public_send(name, *positional, **keywords.slice(*keywords_for(name)))
105+
end
106+
107+
# Routing tokens only count when this version's method accepts them
108+
define_method(:tokens_for) do |name, tokens|
109+
keywords_for(name).include?(:p_token) ? tokens : {}
110+
end
111+
112+
define_method(:available) do |names|
113+
names.select { |name| formatter.respond_to?(name) }
114+
end
115+
94116
# Runs one formatter call; returns nil when the input was rejected
95117
define_method(:attempt) do |&blk|
96118
blk.call
@@ -104,8 +126,8 @@
104126
p_token = random_token
105127
l_token = random_token
106128
tokens = { 'P' => p_token, 'L' => l_token }
107-
case_name = %i[meta_get meta_set meta_delete meta_arithmetic plain_meta_get plain_meta_set
108-
plain_meta_delete].sample(random: rng)
129+
case_name = available(%i[meta_get meta_set meta_delete meta_arithmetic plain_meta_get plain_meta_set
130+
plain_meta_delete]).sample(random: rng)
109131
args = nil
110132

111133
out = attempt do
@@ -115,33 +137,33 @@
115137
recache_ttl: maybe(lambda {
116138
random_numeric
117139
}), quiet: rng.rand < 0.5, p_token: p_token, l_token: l_token }
118-
formatter.meta_get(**args)
140+
call_formatter(:meta_get, **args)
119141
when :meta_set
120142
args = { key: key, value: random_string(key_chars, 30), bitflags: rng.rand(0..5), cas: maybe(lambda {
121143
random_numeric
122144
}),
123145
ttl: maybe(-> { random_numeric }), quiet: rng.rand < 0.5, p_token: p_token, l_token: l_token }
124-
formatter.meta_set(**args)
146+
call_formatter(:meta_set, **args)
125147
when :meta_delete
126148
args = { key: key, cas: maybe(-> { random_numeric }), stale: true, ttl: maybe(-> { random_numeric }),
127149
p_token: p_token, l_token: l_token }
128-
formatter.meta_delete(**args)
150+
call_formatter(:meta_delete, **args)
129151
when :meta_arithmetic
130152
args = { key: key, delta: maybe(-> { random_numeric }), initial: maybe(-> { random_numeric }),
131153
ttl: maybe(-> { random_numeric }), p_token: p_token, l_token: l_token }
132-
formatter.meta_arithmetic(**args)
154+
call_formatter(:meta_arithmetic, **args)
133155
when :plain_meta_get
134156
tokens = {}
135157
args = [key, rng.rand < 0.5]
136-
formatter.plain_meta_get(*args)
158+
call_formatter(:plain_meta_get, *args)
137159
when :plain_meta_set
138160
tokens = {}
139161
args = [key, rng.rand(0..1000), rng.rand(0..5), maybe(-> { random_numeric })]
140-
formatter.plain_meta_set(*args)
162+
call_formatter(:plain_meta_set, *args)
141163
when :plain_meta_delete
142164
tokens = {}
143165
args = [key]
144-
formatter.plain_meta_delete(*args)
166+
call_formatter(:plain_meta_delete, *args)
145167
end
146168
end
147169
next if out.nil?
@@ -152,7 +174,7 @@
152174
commands = frame(bytes)
153175

154176
assert_equal 1, commands.size, "#{context} produced #{commands.size} commands: #{out.inspect}"
155-
assert_command_line(commands[0][0], key, tokens)
177+
assert_command_line(commands[0][0], key, tokens_for(case_name, tokens))
156178
rescue Minitest::Assertion => e
157179
raise e.class, "#{e.message}\n#{context || "seed=#{seed} iteration=#{i}"}"
158180
end
@@ -164,21 +186,21 @@
164186
p_token = random_token
165187
l_token = random_token
166188
tokens = { 'P' => p_token, 'L' => l_token }
167-
case_name = %i[multi_meta_get multi_meta_delete multi_meta_set].sample(random: rng)
189+
case_name = available(%i[multi_meta_get multi_meta_delete multi_meta_set]).sample(random: rng)
168190
args = nil
169191

170192
out = attempt do
171193
case case_name
172194
when :multi_meta_get
173195
args = [keys, { return_cas: rng.rand < 0.5, p_token: p_token, l_token: l_token }]
174-
formatter.multi_meta_get(keys, **args[1])
196+
call_formatter(:multi_meta_get, keys, **args[1])
175197
when :multi_meta_delete
176198
args = [keys, { stale: true, ttl: maybe(-> { random_numeric }), p_token: p_token, l_token: l_token }]
177-
formatter.multi_meta_delete(keys, **args[1])
199+
call_formatter(:multi_meta_delete, keys, **args[1])
178200
when :multi_meta_set
179201
entries = keys.to_h { |k| [k, [random_string(key_chars, 30), rng.rand(0..5)]] }
180202
args = [entries, { ttl: maybe(-> { random_numeric }), p_token: p_token, l_token: l_token }]
181-
formatter.multi_meta_set(entries, **args[1])
203+
call_formatter(:multi_meta_set, entries, **args[1])
182204
end
183205
end
184206
next if out.nil?
@@ -189,7 +211,7 @@
189211
assert_equal keys.size + 1, commands.size, "#{context} produced #{commands.size} commands"
190212
assert_equal 'mn', commands.last[0], context
191213
commands[0...-1].each_with_index do |(header, _), idx|
192-
assert_command_line(header, keys[idx], tokens)
214+
assert_command_line(header, keys[idx], tokens_for(case_name, tokens))
193215
end
194216
rescue Minitest::Assertion => e
195217
raise e.class, "#{e.message}\n#{context || "seed=#{seed} iteration=#{i}"}"

‎test/test_compressor.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
end
3838

3939
it 'stops a decompression bomb without inflating it fully' do
40-
bomb = compressor.compress("\0" * (64 * 1024 * 1024))
40+
bomb = compressor.compress("\0" * (16 * 1024 * 1024))
4141

4242
assert_raises(Dalli::UnmarshalError) { compressor.decompress(bomb, max_bytes: 1024 * 1024) }
4343
end

0 commit comments

Comments
 (0)