groonga-query-log 1.4.4 → 1.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/groonga-query-log-check-performance-regression +22 -0
- data/doc/text/news.md +14 -0
- data/lib/groonga-query-log/command/check-performance-regression.rb +447 -0
- data/lib/groonga-query-log/command/run-regression-test.rb +1 -1
- data/lib/groonga-query-log/statistic.rb +6 -0
- data/lib/groonga-query-log/version.rb +1 -1
- data/test/command/test-check-performance-regression.rb +311 -0
- data/test/fixtures/check-performance-regression/cache.log +3 -0
- data/test/fixtures/check-performance-regression/nquery.log +10 -0
- data/test/fixtures/check-performance-regression/nquery2.log +10 -0
- data/test/fixtures/check-performance-regression/query1.log +4 -0
- data/test/fixtures/check-performance-regression/query2.log +4 -0
- metadata +45 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bc397a48e26c377cab3315458cc8da30cb80cd7efd00bdea36595d7f6cb8bd7
|
4
|
+
data.tar.gz: 142b467fd6d1b809e4ca2c8b06c826084488dc6cf48aabc387e2dbe22edf0688
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49862f644474605b03c770c8bd88ca4469a1d234f6b13fc707147ea6ff3c1d82b3f8aa883b35e9fefc09e6c4f58b12c66e9f899a1daf96f4342cc03ffa4969fd
|
7
|
+
data.tar.gz: cd8283475cab0a4cfdd4f3d2ae6d8d5b42ecc9b09b8877185a07a660fd44819910a372cb472620e0e65444ac762ec729387c5d53dee299eba1f3dbade445b2d5
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Kentaro hayashi <hayashi@clear-code.com>
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
|
19
|
+
require "groonga-query-log/command/check-performance-regression"
|
20
|
+
|
21
|
+
checker = GroongaQueryLog::Command::CheckPerformanceRegression.new
|
22
|
+
exit(checker.run(ARGV))
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 1.4.5: 2019-08-15
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* `groonga-query-log-check-performance-regression`:
|
8
|
+
|
9
|
+
* Added feature for checking deterioration of performance.
|
10
|
+
|
11
|
+
### Fixes
|
12
|
+
|
13
|
+
* `groonga-query-log-run-regression-test`:
|
14
|
+
|
15
|
+
* Fixed a bug that `--rewrite-and-not-operator` option doesn't work.
|
16
|
+
|
3
17
|
## 1.4.4: 2019-08-05
|
4
18
|
|
5
19
|
### Improvements
|
@@ -0,0 +1,447 @@
|
|
1
|
+
# Copyright (C) 2019 Kentaro Hayashi <hayashi@clear-code.com>
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License as published by the Free Software Foundation; either
|
6
|
+
# version 2.1 of the License, or (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This library is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
+
# Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public
|
14
|
+
# License along with this library; if not, write to the Free Software
|
15
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
16
|
+
|
17
|
+
require "optparse"
|
18
|
+
require "json"
|
19
|
+
|
20
|
+
require "groonga-query-log"
|
21
|
+
require "groonga-query-log/command-line"
|
22
|
+
|
23
|
+
require "groonga-query-log/command/analyzer"
|
24
|
+
require "groonga-query-log/command/analyzer/sized-statistics"
|
25
|
+
|
26
|
+
module GroongaQueryLog
|
27
|
+
module Command
|
28
|
+
class CheckPerformanceRegression < CommandLine
|
29
|
+
NSEC_IN_SECONDS = (1000 * 1000 * 1000)
|
30
|
+
USEC_IN_SECONDS = (1000 * 1000)
|
31
|
+
MSEC_IN_SECONDS = 1000
|
32
|
+
|
33
|
+
def initialize(options={})
|
34
|
+
setup_options(options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def run(arguments)
|
38
|
+
paths = []
|
39
|
+
begin
|
40
|
+
paths = @option_parser.parse!(arguments)
|
41
|
+
rescue OptionParser::InvalidOption => error
|
42
|
+
$stderr.puts(error)
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
|
46
|
+
if paths.size != 2
|
47
|
+
$stderr.puts("old query log and new query log must be specified.")
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
51
|
+
old_query_paths = resolve_path(paths[0])
|
52
|
+
return false if old_query_paths.nil?
|
53
|
+
new_query_paths = resolve_path(paths[1])
|
54
|
+
return false if new_query_paths.nil?
|
55
|
+
|
56
|
+
old_statistics = analyze(old_query_paths)
|
57
|
+
return false if old_statistics.nil?
|
58
|
+
new_statistics = analyze(new_query_paths)
|
59
|
+
return false if new_statistics.nil?
|
60
|
+
|
61
|
+
open_output do |output|
|
62
|
+
checker = Checker.new(old_statistics,
|
63
|
+
new_statistics,
|
64
|
+
output,
|
65
|
+
@threshold,
|
66
|
+
@target_queries)
|
67
|
+
checker.check
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def resolve_path(path)
|
73
|
+
if File.directory?(path)
|
74
|
+
Dir.glob("#{path}/*.log")
|
75
|
+
elsif File.exist?(path)
|
76
|
+
[path]
|
77
|
+
else
|
78
|
+
$stderr.puts("query log path doesn't exist: <#{path}>")
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def open_output(&block)
|
84
|
+
case @output
|
85
|
+
when "-"
|
86
|
+
yield($stdout)
|
87
|
+
when String
|
88
|
+
File.open(@output, "w", &block)
|
89
|
+
else
|
90
|
+
yield(@output)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def setup_options(options)
|
95
|
+
@output = options[:output] || "-"
|
96
|
+
@n_entries = 1000
|
97
|
+
@threshold = Threshold.new
|
98
|
+
@target_queries = []
|
99
|
+
|
100
|
+
@option_parser = OptionParser.new do |parser|
|
101
|
+
parser.version = VERSION
|
102
|
+
parser.banner += " OLD_QUERY_LOG NEW_QUERY_LOG"
|
103
|
+
|
104
|
+
parser.on("-n", "--n-entries=N",
|
105
|
+
Integer,
|
106
|
+
"Analyze N query log entries",
|
107
|
+
"(#{@n_entries})") do |n|
|
108
|
+
@n_entries = n
|
109
|
+
end
|
110
|
+
|
111
|
+
if @output == "-"
|
112
|
+
default_output = "stdout"
|
113
|
+
else
|
114
|
+
default_output = @output
|
115
|
+
end
|
116
|
+
parser.on("--output=PATH",
|
117
|
+
"Output to PATH.",
|
118
|
+
"(#{default_output})") do |output|
|
119
|
+
@output = output
|
120
|
+
end
|
121
|
+
|
122
|
+
parser.on("--target-query-file=TARGET_QUERY_FILE",
|
123
|
+
"Analyze matched queries which are listed " +
|
124
|
+
"in specified TARGET_QUERY_FILE.") do |path|
|
125
|
+
if File.exist?(path)
|
126
|
+
@target_queries = File.readlines(path, chomp: true)
|
127
|
+
else
|
128
|
+
message = "target query file doesn't exist: <#{path}>"
|
129
|
+
raise OptionParser::InvalidOption.new(message)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
parser.on("--slow-query-ratio=RATIO",
|
134
|
+
Float,
|
135
|
+
"Use RATIO as threshold to detect slow queries.",
|
136
|
+
"If MEAN_NEW_ELAPSED_TIME / MEAN_OLD_ELAPSED_TIME AVERAGE",
|
137
|
+
"is larger than RATIO, the query is slow.",
|
138
|
+
"(#{@threshold.query_ratio})") do |ratio|
|
139
|
+
@threshold.query_ratio = ratio
|
140
|
+
end
|
141
|
+
|
142
|
+
parser.on("--slow-query-second=SECOND",
|
143
|
+
Float,
|
144
|
+
"Use SECOND as threshold to detect slow queries.",
|
145
|
+
"If MEAN_NEW_ELAPSED_TIME - MEAN_OLD_ELAPSED_TIME AVERAGE",
|
146
|
+
"is larger than SECOND, the query is slow.",
|
147
|
+
"(#{@threshold.query_second})") do |second|
|
148
|
+
@threshold.query_second = second
|
149
|
+
end
|
150
|
+
|
151
|
+
parser.on("--slow-operation-ratio=RATIO",
|
152
|
+
Float,
|
153
|
+
"Use RATIO as threshold to detect slow operations.",
|
154
|
+
"If MEAN_NEW_ELAPSED_TIME / MEAN_OLD_ELAPSED_TIME AVERAGE",
|
155
|
+
"is larger than RATIO, the operation is slow.",
|
156
|
+
"(#{@threshold.operation_ratio})") do |ratio|
|
157
|
+
@threshold.operation_ratio = ratio
|
158
|
+
end
|
159
|
+
|
160
|
+
parser.on("--slow-operation-second=SECOND",
|
161
|
+
Float,
|
162
|
+
"Use SECOND as threshold to detect slow operations.",
|
163
|
+
"If MEAN_NEW_ELAPSED_TIME - MEAN_OLD_ELAPSED_TIME AVERAGE",
|
164
|
+
"is larger than SECOND, the operation is slow.",
|
165
|
+
"(#{@threshold.operation_second})") do |second|
|
166
|
+
@threshold.operation_second = second
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def analyze(log_paths)
|
173
|
+
full_statistics = []
|
174
|
+
begin
|
175
|
+
n = 1
|
176
|
+
parser = Parser.new
|
177
|
+
parse_log(parser, log_paths) do |statistic|
|
178
|
+
next if n > @n_entries
|
179
|
+
full_statistics << statistic
|
180
|
+
n += 1
|
181
|
+
end
|
182
|
+
rescue Error
|
183
|
+
$stderr.puts($!.message)
|
184
|
+
return nil
|
185
|
+
end
|
186
|
+
full_statistics
|
187
|
+
end
|
188
|
+
|
189
|
+
class Threshold
|
190
|
+
attr_accessor :query_ratio
|
191
|
+
attr_accessor :query_second
|
192
|
+
attr_accessor :operation_ratio
|
193
|
+
attr_accessor :operation_second
|
194
|
+
def initialize
|
195
|
+
@query_ratio = 0
|
196
|
+
@query_second = 0.2
|
197
|
+
@operation_ratio = 0.1
|
198
|
+
@operation_second = 0.1
|
199
|
+
end
|
200
|
+
|
201
|
+
def slow_query?(diff_sec, diff_ratio)
|
202
|
+
return false if diff_sec.zero?
|
203
|
+
(diff_sec >= @query_second) and
|
204
|
+
(diff_ratio >= @query_ratio)
|
205
|
+
end
|
206
|
+
|
207
|
+
def slow_operation?(diff_sec, diff_ratio)
|
208
|
+
return false if diff_sec.zero?
|
209
|
+
(diff_sec >= @operation_second) and
|
210
|
+
(diff_ratio >= @operation_ratio)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
class Statistic
|
215
|
+
def initialize(old, new, threshold)
|
216
|
+
@old = old
|
217
|
+
@new = new
|
218
|
+
@threshold = threshold
|
219
|
+
end
|
220
|
+
|
221
|
+
def old_elapsed_time
|
222
|
+
@old_elapsed_time ||= compute_mean(@old)
|
223
|
+
end
|
224
|
+
|
225
|
+
def new_elapsed_time
|
226
|
+
@new_elapsed_time ||= compute_mean(@new)
|
227
|
+
end
|
228
|
+
|
229
|
+
def diff_elapsed_time
|
230
|
+
new_elapsed_time - old_elapsed_time
|
231
|
+
end
|
232
|
+
|
233
|
+
def ratio
|
234
|
+
@ratio ||= compute_ratio
|
235
|
+
end
|
236
|
+
|
237
|
+
private
|
238
|
+
def compute_ratio
|
239
|
+
if old_elapsed_time.zero?
|
240
|
+
if new_elapsed_time.zero?
|
241
|
+
0.0
|
242
|
+
else
|
243
|
+
Float::INIFINITY
|
244
|
+
end
|
245
|
+
else
|
246
|
+
new_elapsed_time / old_elapsed_time
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class OperationStatistic < Statistic
|
252
|
+
attr_reader :index
|
253
|
+
def initialize(operation, index, old, new, threshold)
|
254
|
+
super(old, new, threshold)
|
255
|
+
@operation = operation
|
256
|
+
@index = index
|
257
|
+
end
|
258
|
+
|
259
|
+
def name
|
260
|
+
@operation[:name]
|
261
|
+
end
|
262
|
+
|
263
|
+
def context
|
264
|
+
@operation[:context]
|
265
|
+
end
|
266
|
+
|
267
|
+
def slow?
|
268
|
+
@threshold.slow_operation?(diff_elapsed_time, ratio)
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
272
|
+
def compute_mean(operations)
|
273
|
+
elapsed_times = operations.collect do |operation|
|
274
|
+
operation[:relative_elapsed] / 1000.0 / 1000.0 / 1000.0
|
275
|
+
end
|
276
|
+
elapsed_times.inject(:+) / elapsed_times.size
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
class QueryStatistic < Statistic
|
281
|
+
attr_reader :query
|
282
|
+
def initialize(query, old, new, threshold)
|
283
|
+
super(old, new, threshold)
|
284
|
+
@query = query
|
285
|
+
end
|
286
|
+
|
287
|
+
def slow?
|
288
|
+
@threshold.slow_query?(diff_elapsed_time, ratio)
|
289
|
+
end
|
290
|
+
|
291
|
+
def each_operation_statistic
|
292
|
+
@old.first.operations.each_with_index do |operation, i|
|
293
|
+
old_operations = @old.collect do |statistic|
|
294
|
+
statistic.operations[i]
|
295
|
+
end
|
296
|
+
# TODO: old and new may use different index
|
297
|
+
new_operations = @new.collect do |statistic|
|
298
|
+
statistic.operations[i]
|
299
|
+
end
|
300
|
+
operation_statistic = OperationStatistic.new(operation,
|
301
|
+
i,
|
302
|
+
old_operations,
|
303
|
+
new_operations,
|
304
|
+
@threshold)
|
305
|
+
yield(operation_statistic)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
private
|
310
|
+
def compute_mean(statistics)
|
311
|
+
elapsed_times = statistics.collect do |statistic|
|
312
|
+
statistic.elapsed / 1000.0 / 1000.0 / 1000.0
|
313
|
+
end
|
314
|
+
elapsed_times.inject(:+) / elapsed_times.size
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
class Checker
|
319
|
+
def initialize(old_statistics,
|
320
|
+
new_statistics,
|
321
|
+
output,
|
322
|
+
threshold,
|
323
|
+
target_queries)
|
324
|
+
@old_statistics = old_statistics
|
325
|
+
@new_statistics = new_statistics
|
326
|
+
@output = output
|
327
|
+
@threshold = threshold
|
328
|
+
@target_queries = target_queries
|
329
|
+
end
|
330
|
+
|
331
|
+
def check
|
332
|
+
old_statistics = filter_statistics(@old_statistics)
|
333
|
+
new_statistics = filter_statistics(@new_statistics)
|
334
|
+
old_queries = old_statistics.group_by(&:raw_command)
|
335
|
+
new_queries = new_statistics.group_by(&:raw_command)
|
336
|
+
|
337
|
+
query_statistics = []
|
338
|
+
old_queries.each_key do |query|
|
339
|
+
query_statistic = QueryStatistic.new(query,
|
340
|
+
old_queries[query],
|
341
|
+
new_queries[query],
|
342
|
+
@threshold)
|
343
|
+
next unless query_statistic.slow?
|
344
|
+
query_statistics << query_statistic
|
345
|
+
end
|
346
|
+
|
347
|
+
n_slow_queries = 0
|
348
|
+
n_target_operations = 0
|
349
|
+
n_slow_operations = 0
|
350
|
+
query_statistics.sort_by(&:ratio).each do |query_statistic|
|
351
|
+
n_slow_queries += 1
|
352
|
+
@output.puts(<<-REPORT)
|
353
|
+
Query: #{query_statistic.query}
|
354
|
+
Mean (old): #{format_elapsed_time(query_statistic.old_elapsed_time)}
|
355
|
+
Mean (new): #{format_elapsed_time(query_statistic.new_elapsed_time)}
|
356
|
+
Diff: #{format_diff(query_statistic)}
|
357
|
+
Operations:
|
358
|
+
REPORT
|
359
|
+
query_statistic.each_operation_statistic do |operation_statistic|
|
360
|
+
n_target_operations += 1
|
361
|
+
next unless operation_statistic.slow?
|
362
|
+
|
363
|
+
n_slow_operations += 1
|
364
|
+
index = operation_statistic.index
|
365
|
+
name = operation_statistic.name
|
366
|
+
context = operation_statistic.context
|
367
|
+
label = [name, context].compact.join(" ")
|
368
|
+
old_elapsed_time = operation_statistic.old_elapsed_time
|
369
|
+
new_elapsed_time = operation_statistic.new_elapsed_time
|
370
|
+
@output.puts(<<-REPORT)
|
371
|
+
Operation[#{index}]: #{label}
|
372
|
+
Mean (old): #{format_elapsed_time(old_elapsed_time)}
|
373
|
+
Mean (new): #{format_elapsed_time(new_elapsed_time)}
|
374
|
+
Diff: #{format_diff(operation_statistic)}
|
375
|
+
REPORT
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
n_all_queries = @old_statistics.size
|
380
|
+
n_target_queries = old_queries.size
|
381
|
+
n_old_cached_queries = count_cached_queries(@old_statistics)
|
382
|
+
n_new_cached_queries = count_cached_queries(@new_statistics)
|
383
|
+
@output.puts(<<-REPORT)
|
384
|
+
Summary:
|
385
|
+
Slow queries: #{format_summary(n_slow_queries, n_target_queries)}
|
386
|
+
Slow operations: #{format_summary(n_slow_operations, n_target_operations)}
|
387
|
+
Caches (old): #{format_summary(n_old_cached_queries, n_all_queries)}
|
388
|
+
Caches (new): #{format_summary(n_new_cached_queries, n_all_queries)}
|
389
|
+
REPORT
|
390
|
+
true
|
391
|
+
end
|
392
|
+
|
393
|
+
private
|
394
|
+
def count_cached_queries(statistics)
|
395
|
+
n_cached_queries = 0
|
396
|
+
statistics.each do |statistic|
|
397
|
+
n_cached_queries += 1 if statistic.cache_used?
|
398
|
+
end
|
399
|
+
n_cached_queries
|
400
|
+
end
|
401
|
+
|
402
|
+
def filter_statistics(statistics)
|
403
|
+
statistics.find_all do |statistic|
|
404
|
+
target_statistic?(statistic)
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def target_statistic?(statistic)
|
409
|
+
return false if statistic.cache_used?
|
410
|
+
return true if @target_queries.empty?
|
411
|
+
@target_queries.include?(statistic.raw_command)
|
412
|
+
end
|
413
|
+
|
414
|
+
def format_elapsed_time(elapsed_time)
|
415
|
+
if elapsed_time < (1 / 1000.0 / 1000.0)
|
416
|
+
"%.1fnsec" % (elapsed_time * 1000 * 1000)
|
417
|
+
elsif elapsed_time < (1 / 1000.0)
|
418
|
+
"%.1fusec" % (elapsed_time * 1000 * 1000)
|
419
|
+
elsif elapsed_time < 1
|
420
|
+
"%.1fmsec" % (elapsed_time * 1000)
|
421
|
+
elsif elapsed_time < 60
|
422
|
+
"%.1fsec" % elapsed_time
|
423
|
+
else
|
424
|
+
"%.1fmin" % (elapsed_time / 60)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def format_diff(statistic)
|
429
|
+
"%s%s/%+.2f" % [
|
430
|
+
statistic.diff_elapsed_time < 0 ? "-" : "+",
|
431
|
+
format_elapsed_time(statistic.diff_elapsed_time),
|
432
|
+
statistic.ratio,
|
433
|
+
]
|
434
|
+
end
|
435
|
+
|
436
|
+
def format_summary(n_slows, total)
|
437
|
+
if total.zero?
|
438
|
+
percentage = 0.0
|
439
|
+
else
|
440
|
+
percentage = (n_slows / total.to_f) * 100
|
441
|
+
end
|
442
|
+
"%d/%d(%6.2f%%)" % [n_slows, total, percentage]
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
@@ -338,7 +338,7 @@ module GroongaQueryLog
|
|
338
338
|
@nullable_reference_number_accessors,
|
339
339
|
:rewrite_not_or_regular_expression =>
|
340
340
|
@rewrite_not_or_regular_expression,
|
341
|
-
:
|
341
|
+
:rewrite_and_not_operator =>
|
342
342
|
@rewrite_and_not_operator,
|
343
343
|
:target_command_names => @target_command_names,
|
344
344
|
:read_timeout => @read_timeout,
|
@@ -61,6 +61,12 @@ module GroongaQueryLog
|
|
61
61
|
elapsed_in_seconds >= @slow_response_threshold
|
62
62
|
end
|
63
63
|
|
64
|
+
def cache_used?
|
65
|
+
each_operation.any? do |operation|
|
66
|
+
operation[:name] == "cache"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
64
70
|
def each_operation
|
65
71
|
return to_enum(__method__) unless block_given?
|
66
72
|
|
@@ -0,0 +1,311 @@
|
|
1
|
+
# Copyright (C) 2019 Kentaro Hayashi <hayashi@clear-code.com>
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License as published by the Free Software Foundation; either
|
6
|
+
# version 2.1 of the License, or (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This library is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
+
# Lesser General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Lesser General Public
|
14
|
+
# License along with this library; if not, write to the Free Software
|
15
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
16
|
+
|
17
|
+
require "groonga-query-log/command/check-performance-regression"
|
18
|
+
|
19
|
+
class CheckPerformanceRegressionCommandTest < Test::Unit::TestCase
|
20
|
+
include Helper::Path
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@command = GroongaQueryLog::Command::CheckPerformanceRegression.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def fixture_path(*components)
|
27
|
+
super("check-performance-regression", *components)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_command(*arguments)
|
31
|
+
output = StringIO.new
|
32
|
+
options = {:output => output}
|
33
|
+
command = GroongaQueryLog::Command::CheckPerformanceRegression.new(options)
|
34
|
+
command.run(arguments)
|
35
|
+
output.string
|
36
|
+
end
|
37
|
+
|
38
|
+
sub_test_case("options") do
|
39
|
+
MISSING_QUERY_LOG_ERROR = <<-OUTPUT
|
40
|
+
old query log and new query log must be specified.
|
41
|
+
OUTPUT
|
42
|
+
|
43
|
+
def run_command_with_stderr
|
44
|
+
begin
|
45
|
+
output = StringIO.new
|
46
|
+
$stderr = output
|
47
|
+
yield
|
48
|
+
output.string
|
49
|
+
ensure
|
50
|
+
$stderr = STDERR
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_no_option
|
55
|
+
actual = run_command_with_stderr do
|
56
|
+
@command.run([])
|
57
|
+
end
|
58
|
+
assert_equal(MISSING_QUERY_LOG_ERROR, actual)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_too_few_query_logs
|
62
|
+
actual = run_command_with_stderr do
|
63
|
+
@command.run([
|
64
|
+
fixture_path("query1.log")
|
65
|
+
])
|
66
|
+
end
|
67
|
+
assert_equal(MISSING_QUERY_LOG_ERROR, actual)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_too_many_query_logs
|
71
|
+
actual = run_command_with_stderr do
|
72
|
+
@command.run([
|
73
|
+
fixture_path("query1.log"),
|
74
|
+
fixture_path("query2.log"),
|
75
|
+
fixture_path("query1.log")
|
76
|
+
])
|
77
|
+
end
|
78
|
+
assert_equal(MISSING_QUERY_LOG_ERROR, actual)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_nonexistent_input_old_query
|
82
|
+
actual = run_command_with_stderr do
|
83
|
+
@command.run([
|
84
|
+
fixture_path("nonexsistent.log"),
|
85
|
+
fixture_path("query2.log")
|
86
|
+
])
|
87
|
+
end
|
88
|
+
assert_equal(<<-OUTPUT, actual)
|
89
|
+
query log path doesn't exist: <#{fixture_path("nonexsistent.log")}>
|
90
|
+
OUTPUT
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_nonexistent_input_new_query
|
94
|
+
actual = run_command_with_stderr do
|
95
|
+
@command.run([
|
96
|
+
fixture_path("query1.log"),
|
97
|
+
fixture_path("nonexsistent.log")
|
98
|
+
])
|
99
|
+
end
|
100
|
+
assert_equal(<<-OUTPUT, actual)
|
101
|
+
query log path doesn't exist: <#{fixture_path("nonexsistent.log")}>
|
102
|
+
OUTPUT
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_output
|
106
|
+
Tempfile.open('test_output') do |output|
|
107
|
+
@command.run([
|
108
|
+
"--slow-query-ratio=0",
|
109
|
+
"--slow-query-second=0",
|
110
|
+
"--slow-operation-ratio=0",
|
111
|
+
"--slow-operation-second=0",
|
112
|
+
"--output=#{output.path}",
|
113
|
+
fixture_path("query1.log"),
|
114
|
+
fixture_path("query2.log")
|
115
|
+
])
|
116
|
+
expected = <<-OUTPUT
|
117
|
+
Query: select --table Site --limit 0
|
118
|
+
Mean (old): 12.0msec
|
119
|
+
Mean (new): 14.0msec
|
120
|
+
Diff: +2.0msec/+1.17
|
121
|
+
Operations:
|
122
|
+
Operation[0]: select
|
123
|
+
Mean (old): 5.0msec
|
124
|
+
Mean (new): 6.0msec
|
125
|
+
Diff: +1.0msec/+1.20
|
126
|
+
Summary:
|
127
|
+
Slow queries: 1/1(100.00%)
|
128
|
+
Slow operations: 1/2( 50.00%)
|
129
|
+
Caches (old): 0/1( 0.00%)
|
130
|
+
Caches (new): 0/1( 0.00%)
|
131
|
+
OUTPUT
|
132
|
+
assert_equal(expected, output.read)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_n_query
|
137
|
+
actual = run_command("--n-entries=1",
|
138
|
+
"--slow-query-ratio=0",
|
139
|
+
"--slow-query-second=0",
|
140
|
+
"--slow-operation-ratio=0",
|
141
|
+
"--slow-operation-second=0",
|
142
|
+
fixture_path("nquery.log"),
|
143
|
+
fixture_path("nquery2.log"))
|
144
|
+
expected = <<-OUTPUT
|
145
|
+
Query: select --table Site --filter "_id >= 4 && _id <= 6"
|
146
|
+
Mean (old): 70.0msec
|
147
|
+
Mean (new): 90.0msec
|
148
|
+
Diff: +20.0msec/+1.29
|
149
|
+
Operations:
|
150
|
+
Operation[0]: filter #<accessor _id(Site)> greater_equal 4
|
151
|
+
Mean (old): 40.0msec
|
152
|
+
Mean (new): 80.0msec
|
153
|
+
Diff: +40.0msec/+2.00
|
154
|
+
Operation[1]: filter #<accessor _id(Site)> less_equal 6
|
155
|
+
Mean (old): 10.0msec
|
156
|
+
Mean (new): 20.0msec
|
157
|
+
Diff: +10.0msec/+2.00
|
158
|
+
Operation[2]: select
|
159
|
+
Mean (old): 10.0msec
|
160
|
+
Mean (new): 20.0msec
|
161
|
+
Diff: +10.0msec/+2.00
|
162
|
+
Operation[3]: output
|
163
|
+
Mean (old): 10.0msec
|
164
|
+
Mean (new): 20.0msec
|
165
|
+
Diff: +10.0msec/+2.00
|
166
|
+
Summary:
|
167
|
+
Slow queries: 1/1(100.00%)
|
168
|
+
Slow operations: 4/4(100.00%)
|
169
|
+
Caches (old): 0/1( 0.00%)
|
170
|
+
Caches (new): 0/1( 0.00%)
|
171
|
+
OUTPUT
|
172
|
+
assert_equal(expected, actual)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
sub_test_case(".new") do
|
177
|
+
def test_output
|
178
|
+
actual = run_command("--slow-query-ratio=0.0",
|
179
|
+
"--slow-query-second=0.0",
|
180
|
+
"--slow-operation-ratio=0.0",
|
181
|
+
"--slow-operation-second=0.0",
|
182
|
+
fixture_path("query1.log"),
|
183
|
+
fixture_path("query2.log"))
|
184
|
+
expected = <<-OUTPUT
|
185
|
+
Query: select --table Site --limit 0
|
186
|
+
Mean (old): 12.0msec
|
187
|
+
Mean (new): 14.0msec
|
188
|
+
Diff: +2.0msec/+1.17
|
189
|
+
Operations:
|
190
|
+
Operation[0]: select
|
191
|
+
Mean (old): 5.0msec
|
192
|
+
Mean (new): 6.0msec
|
193
|
+
Diff: +1.0msec/+1.20
|
194
|
+
Summary:
|
195
|
+
Slow queries: 1/1(100.00%)
|
196
|
+
Slow operations: 1/2( 50.00%)
|
197
|
+
Caches (old): 0/1( 0.00%)
|
198
|
+
Caches (new): 0/1( 0.00%)
|
199
|
+
OUTPUT
|
200
|
+
assert_equal(expected, actual)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
sub_test_case("query-ratio") do
|
205
|
+
def test_filtered
|
206
|
+
actual = run_command("--slow-query-ratio=2",
|
207
|
+
"--slow-query-second=0",
|
208
|
+
"--slow-operation-ratio=0",
|
209
|
+
"--slow-operation-second=0",
|
210
|
+
fixture_path("query1.log"),
|
211
|
+
fixture_path("query2.log"))
|
212
|
+
expected = <<-OUTPUT
|
213
|
+
Summary:
|
214
|
+
Slow queries: 0/1( 0.00%)
|
215
|
+
Slow operations: 0/0( 0.00%)
|
216
|
+
Caches (old): 0/1( 0.00%)
|
217
|
+
Caches (new): 0/1( 0.00%)
|
218
|
+
OUTPUT
|
219
|
+
assert_equal(expected, actual)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
sub_test_case("operation-ratio") do
|
224
|
+
def test_filtered
|
225
|
+
actual = run_command("--slow-query-ratio=0",
|
226
|
+
"--slow-query-second=0",
|
227
|
+
"--slow-operation-ratio=2",
|
228
|
+
"--slow-operation-second=0",
|
229
|
+
fixture_path("query1.log"),
|
230
|
+
fixture_path("query2.log"))
|
231
|
+
expected = <<-OUTPUT
|
232
|
+
Query: select --table Site --limit 0
|
233
|
+
Mean (old): 12.0msec
|
234
|
+
Mean (new): 14.0msec
|
235
|
+
Diff: +2.0msec/+1.17
|
236
|
+
Operations:
|
237
|
+
Summary:
|
238
|
+
Slow queries: 1/1(100.00%)
|
239
|
+
Slow operations: 0/2( 0.00%)
|
240
|
+
Caches (old): 0/1( 0.00%)
|
241
|
+
Caches (new): 0/1( 0.00%)
|
242
|
+
OUTPUT
|
243
|
+
assert_equal(expected, actual)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
sub_test_case("query-second") do
|
248
|
+
def test_filtered
|
249
|
+
actual = run_command("--slow-query-ratio=0",
|
250
|
+
"--slow-query-second=0.02",
|
251
|
+
"--slow-operation-ratio=0",
|
252
|
+
"--slow-operation-second=0",
|
253
|
+
fixture_path("query1.log"),
|
254
|
+
fixture_path("query2.log"))
|
255
|
+
expected = <<-OUTPUT
|
256
|
+
Summary:
|
257
|
+
Slow queries: 0/1( 0.00%)
|
258
|
+
Slow operations: 0/0( 0.00%)
|
259
|
+
Caches (old): 0/1( 0.00%)
|
260
|
+
Caches (new): 0/1( 0.00%)
|
261
|
+
OUTPUT
|
262
|
+
assert_equal(expected, actual)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
sub_test_case("operation-second") do
|
267
|
+
def test_filtered
|
268
|
+
actual = run_command("--slow-query-ratio=0",
|
269
|
+
"--slow-query-second=0",
|
270
|
+
"--slow-operation-ratio=0",
|
271
|
+
"--slow-operation-second=0.001",
|
272
|
+
fixture_path("query1.log"),
|
273
|
+
fixture_path("query2.log"))
|
274
|
+
expected = <<-OUTPUT
|
275
|
+
Query: select --table Site --limit 0
|
276
|
+
Mean (old): 12.0msec
|
277
|
+
Mean (new): 14.0msec
|
278
|
+
Diff: +2.0msec/+1.17
|
279
|
+
Operations:
|
280
|
+
Operation[0]: select
|
281
|
+
Mean (old): 5.0msec
|
282
|
+
Mean (new): 6.0msec
|
283
|
+
Diff: +1.0msec/+1.20
|
284
|
+
Summary:
|
285
|
+
Slow queries: 1/1(100.00%)
|
286
|
+
Slow operations: 1/2( 50.00%)
|
287
|
+
Caches (old): 0/1( 0.00%)
|
288
|
+
Caches (new): 0/1( 0.00%)
|
289
|
+
OUTPUT
|
290
|
+
assert_equal(expected, actual)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
sub_test_case("cache") do
|
295
|
+
def test_ignored_cache
|
296
|
+
actual = run_command("--slow-query-ratio=0",
|
297
|
+
"--slow-operation-ratio=0",
|
298
|
+
"--slow-query-second=0",
|
299
|
+
fixture_path("cache.log"),
|
300
|
+
fixture_path("cache.log"))
|
301
|
+
expected = <<-OUTPUT
|
302
|
+
Summary:
|
303
|
+
Slow queries: 0/0( 0.00%)
|
304
|
+
Slow operations: 0/0( 0.00%)
|
305
|
+
Caches (old): 1/1(100.00%)
|
306
|
+
Caches (new): 1/1(100.00%)
|
307
|
+
OUTPUT
|
308
|
+
assert_equal(expected, actual)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
2019-01-24 08:18:33.921596|0x7ffd9e258a40|>select --table Site --filter "_id >= 4 && _id <= 6"
|
2
|
+
2019-01-24 08:18:33.968258|0x7ffd9e258a40|:000000040000000 filter(6): #<accessor _id(Site)> greater_equal 4
|
3
|
+
2019-01-24 08:18:33.968917|0x7ffd9e258a40|:000000050000000 filter(3): #<accessor _id(Site)> less_equal 6
|
4
|
+
2019-01-24 08:18:33.968940|0x7ffd9e258a40|:000000060000000 select(3)
|
5
|
+
2019-01-24 08:18:33.969085|0x7ffd9e258a40|:000000070000000 output(3)
|
6
|
+
2019-01-24 08:18:33.969311|0x7ffd9e258a40|<000000070000000 rc=0
|
7
|
+
2019-01-24 08:19:05.449799|0x7ffe40eafa50|>select --table Site
|
8
|
+
2019-01-24 08:19:05.450416|0x7ffe40eafa50|:000000000600000 select(9)
|
9
|
+
2019-01-24 08:19:05.450706|0x7ffe40eafa50|:000000000900000 output(9)
|
10
|
+
2019-01-24 08:19:05.451271|0x7ffe40eafa50|<000000001400000 rc=0
|
@@ -0,0 +1,10 @@
|
|
1
|
+
2019-01-24 08:18:33.921596|0x7ffd9e258a40|>select --table Site --filter "_id >= 4 && _id <= 6"
|
2
|
+
2019-01-24 08:18:33.968258|0x7ffd9e258a40|:000000080000000 filter(6): #<accessor _id(Site)> greater_equal 4
|
3
|
+
2019-01-24 08:18:33.968917|0x7ffd9e258a40|:000000100000000 filter(3): #<accessor _id(Site)> less_equal 6
|
4
|
+
2019-01-24 08:18:33.968940|0x7ffd9e258a40|:000000120000000 select(3)
|
5
|
+
2019-01-24 08:18:33.969085|0x7ffd9e258a40|:000000140000000 output(3)
|
6
|
+
2019-01-24 08:18:33.969311|0x7ffd9e258a40|<000000090000000 rc=0
|
7
|
+
2019-01-24 08:19:05.449799|0x7ffe40eafa50|>select --table Site
|
8
|
+
2019-01-24 08:19:05.450416|0x7ffe40eafa50|:000000000600000 select(9)
|
9
|
+
2019-01-24 08:19:05.450706|0x7ffe40eafa50|:000000000900000 output(9)
|
10
|
+
2019-01-24 08:19:05.451271|0x7ffe40eafa50|<000000001400000 rc=0
|
@@ -0,0 +1,4 @@
|
|
1
|
+
2019-01-22 15:00:57.466438|0x7ffc70f60080|>select --table Site --limit 0
|
2
|
+
2019-01-22 15:00:57.472248|0x7ffc70f60080|:000000005000000 select(1)
|
3
|
+
2019-01-22 15:00:57.475195|0x7ffc70f60080|:000000007000000 output(0)
|
4
|
+
2019-01-22 15:00:57.475480|0x7ffc70f60080|<000000012000000 rc=0
|
@@ -0,0 +1,4 @@
|
|
1
|
+
2019-01-22 16:00:00.000000|0x7ffc70f60080|>select --table Site --limit 0
|
2
|
+
2019-01-22 16:00:01.500000|0x7ffc70f60080|:000000006000000 select(1)
|
3
|
+
2019-01-22 16:00:02.000000|0x7ffc70f60080|:000000008000000 output(0)
|
4
|
+
2019-01-22 16:00:03.000000|0x7ffc70f60080|<000000014000000 rc=0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groonga-query-log
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kouhei Sutou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: groonga-command-parser
|
@@ -154,17 +154,18 @@ description: ''
|
|
154
154
|
email:
|
155
155
|
- kou@clear-code.com
|
156
156
|
executables:
|
157
|
-
- groonga-query-log-
|
158
|
-
- groonga-query-log-
|
157
|
+
- groonga-query-log-detect-memory-leak
|
158
|
+
- groonga-query-log-analyze
|
159
159
|
- groonga-query-log-check-crash
|
160
160
|
- groonga-query-log-replay
|
161
|
+
- groonga-query-log-extract
|
162
|
+
- groonga-query-log-show-running-queries
|
161
163
|
- groonga-query-log-check-command-version-compatibility
|
164
|
+
- groonga-query-log-run-regression-test
|
162
165
|
- groonga-query-log-verify-server
|
163
|
-
- groonga-query-log-show-running-queries
|
164
|
-
- groonga-query-log-analyze
|
165
|
-
- groonga-query-log-extract
|
166
|
-
- groonga-query-log-detect-memory-leak
|
167
166
|
- groonga-query-log-analyze-load
|
167
|
+
- groonga-query-log-format-regression-test-logs
|
168
|
+
- groonga-query-log-check-performance-regression
|
168
169
|
extensions: []
|
169
170
|
extra_rdoc_files: []
|
170
171
|
files:
|
@@ -176,6 +177,7 @@ files:
|
|
176
177
|
- bin/groonga-query-log-analyze-load
|
177
178
|
- bin/groonga-query-log-check-command-version-compatibility
|
178
179
|
- bin/groonga-query-log-check-crash
|
180
|
+
- bin/groonga-query-log-check-performance-regression
|
179
181
|
- bin/groonga-query-log-detect-memory-leak
|
180
182
|
- bin/groonga-query-log-extract
|
181
183
|
- bin/groonga-query-log-format-regression-test-logs
|
@@ -203,6 +205,7 @@ files:
|
|
203
205
|
- lib/groonga-query-log/command/analyzer/streamer.rb
|
204
206
|
- lib/groonga-query-log/command/check-command-version-compatibility.rb
|
205
207
|
- lib/groonga-query-log/command/check-crash.rb
|
208
|
+
- lib/groonga-query-log/command/check-performance-regression.rb
|
206
209
|
- lib/groonga-query-log/command/detect-memory-leak.rb
|
207
210
|
- lib/groonga-query-log/command/extract.rb
|
208
211
|
- lib/groonga-query-log/command/format-regression-test-logs.rb
|
@@ -230,9 +233,15 @@ files:
|
|
230
233
|
- lib/groonga/query-log/command/show-running-queries.rb
|
231
234
|
- lib/groonga/query-log/command/verify-server.rb
|
232
235
|
- test/command/test-analyzer.rb
|
236
|
+
- test/command/test-check-performance-regression.rb
|
233
237
|
- test/command/test-extract.rb
|
234
238
|
- test/command/test-format-regression-test-logs.rb
|
235
239
|
- test/command/test-run-regression-test.rb
|
240
|
+
- test/fixtures/check-performance-regression/cache.log
|
241
|
+
- test/fixtures/check-performance-regression/nquery.log
|
242
|
+
- test/fixtures/check-performance-regression/nquery2.log
|
243
|
+
- test/fixtures/check-performance-regression/query1.log
|
244
|
+
- test/fixtures/check-performance-regression/query2.log
|
236
245
|
- test/fixtures/multi.expected
|
237
246
|
- test/fixtures/n_entries.expected
|
238
247
|
- test/fixtures/no-report-summary.expected
|
@@ -289,36 +298,42 @@ summary: Groonga-query-log is a collection of library and tools to process [Groo
|
|
289
298
|
as a library. You can analyze your Groonga's queries and test with your Groonga's
|
290
299
|
query log by using groonga-query-log as a tool.
|
291
300
|
test_files:
|
292
|
-
- test/
|
293
|
-
- test/fixtures/
|
294
|
-
- test/fixtures/
|
295
|
-
- test/fixtures/
|
296
|
-
- test/fixtures/
|
301
|
+
- test/run-test.rb
|
302
|
+
- test/fixtures/n_entries.expected
|
303
|
+
- test/fixtures/check-performance-regression/query1.log
|
304
|
+
- test/fixtures/check-performance-regression/cache.log
|
305
|
+
- test/fixtures/check-performance-regression/nquery2.log
|
306
|
+
- test/fixtures/check-performance-regression/nquery.log
|
307
|
+
- test/fixtures/check-performance-regression/query2.log
|
308
|
+
- test/fixtures/target-tables.expected
|
309
|
+
- test/fixtures/no-report-summary.expected
|
297
310
|
- test/fixtures/order/-start-time.expected
|
298
311
|
- test/fixtures/order/-elapsed.expected
|
312
|
+
- test/fixtures/order/start-time.expected
|
299
313
|
- test/fixtures/order/elapsed.expected
|
300
|
-
- test/fixtures/no-report-summary.expected
|
301
|
-
- test/fixtures/target-commands.expected
|
302
|
-
- test/fixtures/run-regression-test/data/data.grn
|
303
|
-
- test/fixtures/run-regression-test/query-logs/query.log
|
304
|
-
- test/fixtures/run-regression-test/indexes/indexes.grn
|
305
|
-
- test/fixtures/run-regression-test/schema/schema.grn
|
306
|
-
- test/fixtures/other-query.log
|
307
|
-
- test/fixtures/query.log
|
308
|
-
- test/fixtures/target-tables.expected
|
309
|
-
- test/fixtures/n_entries.expected
|
310
|
-
- test/fixtures/multi.expected
|
311
|
-
- test/fixtures/regression-test-logs/command-format.log
|
312
314
|
- test/fixtures/regression-test-logs/url-format.log
|
315
|
+
- test/fixtures/regression-test-logs/command-format.log
|
313
316
|
- test/fixtures/regression-test-logs/error.log
|
317
|
+
- test/fixtures/multi.expected
|
318
|
+
- test/fixtures/query.log
|
319
|
+
- test/fixtures/other-query.log
|
320
|
+
- test/fixtures/reporter/json-stream.expected
|
321
|
+
- test/fixtures/reporter/console.expected
|
322
|
+
- test/fixtures/reporter/json.expected
|
323
|
+
- test/fixtures/reporter/html.expected
|
324
|
+
- test/fixtures/run-regression-test/schema/schema.grn
|
325
|
+
- test/fixtures/run-regression-test/data/data.grn
|
326
|
+
- test/fixtures/run-regression-test/indexes/indexes.grn
|
327
|
+
- test/fixtures/run-regression-test/query-logs/query.log
|
328
|
+
- test/fixtures/target-commands.expected
|
329
|
+
- test/test-parser.rb
|
330
|
+
- test/helper.rb
|
331
|
+
- test/test-replayer.rb
|
332
|
+
- test/test-response-comparer.rb
|
314
333
|
- test/command/test-run-regression-test.rb
|
334
|
+
- test/command/test-check-performance-regression.rb
|
315
335
|
- test/command/test-format-regression-test-logs.rb
|
316
336
|
- test/command/test-analyzer.rb
|
317
337
|
- test/command/test-extract.rb
|
318
|
-
- test/test-response-comparer.rb
|
319
|
-
- test/test-replayer.rb
|
320
338
|
- test/test-incompatibility-detector.rb
|
321
339
|
- test/test-filter-rewriter.rb
|
322
|
-
- test/test-parser.rb
|
323
|
-
- test/helper.rb
|
324
|
-
- test/run-test.rb
|