groonga-query-log 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/doc/text/news.md +31 -0
- data/lib/groonga-query-log/command/check-crash.rb +7 -1
- data/lib/groonga-query-log/command/run-regression-test.rb +366 -341
- data/lib/groonga-query-log/command/verify-server.rb +120 -104
- data/lib/groonga-query-log/response-comparer.rb +220 -153
- data/lib/groonga-query-log/server-verifier.rb +189 -175
- data/lib/groonga-query-log/version.rb +1 -1
- data/test/test-response-comparer.rb +136 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f93f3372ace5058cc9f8b7eb9f4799ad841862ca62bb7a7045564dd509b700c
|
4
|
+
data.tar.gz: 274f551095b12c0d7ce61f8f3c7be8d3b55531fcf7acf06df74fedc034f918ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 927ce37d21309f8def6a273c01b6b16a2c21d125a4db976f35bc16df211f81393a14cef1148ff9ac79d6488aa84ea3fdcdba26a69744ec32d605c66726bf3266
|
7
|
+
data.tar.gz: e509b9cfa830dcaf232ab4bf6692741afc44acc03b0fbe78c0135e52dc19a8911e12a18e61581925eb2d448790226ea93dc0c5b6821d06459176d6b7a8ae1e83
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,36 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 1.3.1: 2018-06-18
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* `groonga-query-log-check-crash`:
|
8
|
+
|
9
|
+
* Added more crash detection patterns.
|
10
|
+
|
11
|
+
* `groonga-query-log-run-regression-test`:
|
12
|
+
|
13
|
+
* Added support for floating number accuracy difference since
|
14
|
+
Groonga 6.0.4.
|
15
|
+
|
16
|
+
* Added support for `sort_keys` parameter.
|
17
|
+
|
18
|
+
* Added support for drilldown.
|
19
|
+
|
20
|
+
* Added `--ignore-drilldown-key` option.
|
21
|
+
|
22
|
+
* Changed to return non-zero on failure.
|
23
|
+
|
24
|
+
* Added `--stop-on-failure` option.
|
25
|
+
|
26
|
+
* `groonga-query-log-verify-server`:
|
27
|
+
|
28
|
+
* Added `--ignore-drilldown-key` option.
|
29
|
+
|
30
|
+
* Changed to return non-zero on failure.
|
31
|
+
|
32
|
+
* Added `--stop-on-failure` option.
|
33
|
+
|
3
34
|
## 1.3.0: 2018-06-11
|
4
35
|
|
5
36
|
### Improvements
|
@@ -147,7 +147,7 @@ module GroongaQueryLog
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
unless @unflushed_statistics.empty?
|
150
|
-
puts("Unflushed
|
150
|
+
puts("Unflushed commands in #{start.iso8601}/#{last.iso8601}")
|
151
151
|
@unflushed_statistics.each do |statistic|
|
152
152
|
puts("#{statistic.start_time.iso8601}: #{statistic.raw_command}")
|
153
153
|
end
|
@@ -176,13 +176,19 @@ module GroongaQueryLog
|
|
176
176
|
when "load"
|
177
177
|
@flushed = false
|
178
178
|
@unflushed_statistics << statistic
|
179
|
+
when "delete"
|
180
|
+
@flushed = false
|
181
|
+
@unflushed_statistics << statistic
|
179
182
|
when "io_flush"
|
183
|
+
# TODO: Improve flushed target detection.
|
180
184
|
@flushed = true
|
181
185
|
@unflushed_statistics.clear
|
182
186
|
when "database_unmap"
|
183
187
|
@unflushed_statistics.reject! do |statistic|
|
184
188
|
statistic.command.name == "load"
|
185
189
|
end
|
190
|
+
when "table_list", "column_list"
|
191
|
+
# ignore
|
186
192
|
when /\Atable_/
|
187
193
|
@flushed = false
|
188
194
|
@unflushed_statistics << statistic
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2014-
|
1
|
+
# Copyright (C) 2014-2018 Kouhei Sutou <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -25,408 +25,433 @@ require "groonga-query-log"
|
|
25
25
|
require "groonga-query-log/command/verify-server"
|
26
26
|
|
27
27
|
module GroongaQueryLog
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
def run(command_line)
|
52
|
-
option_parser = create_option_parser
|
53
|
-
begin
|
54
|
-
option_parser.parse!(command_line)
|
55
|
-
rescue OptionParser::ParseError => error
|
56
|
-
$stderr.puts(error.message)
|
57
|
-
return false
|
58
|
-
end
|
28
|
+
module Command
|
29
|
+
class RunRegressionTest
|
30
|
+
def initialize
|
31
|
+
@input_directory = Pathname.new(".")
|
32
|
+
@working_directory = Pathname.new(".")
|
33
|
+
|
34
|
+
@old_groonga = "groonga"
|
35
|
+
@old_database = "db.old/db"
|
36
|
+
@old_groonga_options = []
|
37
|
+
|
38
|
+
@new_groonga = "groonga"
|
39
|
+
@new_database = "db.new/db"
|
40
|
+
@new_groonga_options = []
|
41
|
+
|
42
|
+
@recreate_database = false
|
43
|
+
@load_data = true
|
44
|
+
@run_queries = true
|
45
|
+
@skip_finished_queries = false
|
46
|
+
@output_query_log = false
|
47
|
+
@care_order = true
|
48
|
+
@ignored_drilldown_keys = []
|
49
|
+
@stop_on_failure = false
|
50
|
+
end
|
59
51
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
52
|
+
def run(command_line)
|
53
|
+
option_parser = create_option_parser
|
54
|
+
begin
|
55
|
+
option_parser.parse!(command_line)
|
56
|
+
rescue OptionParser::ParseError => error
|
57
|
+
$stderr.puts(error.message)
|
58
|
+
return false
|
64
59
|
end
|
65
60
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
parser.separator("")
|
72
|
-
parser.separator("Path:")
|
73
|
-
parser.on("--input-directory=DIRECTORY",
|
74
|
-
"Load schema and data from DIRECTORY.",
|
75
|
-
"(#{@input_directory})") do |directory|
|
76
|
-
@input_directory = Pathname.new(directory)
|
77
|
-
end
|
78
|
-
parser.on("--working-directory=DIRECTORY",
|
79
|
-
"Use DIRECTORY as working directory.",
|
80
|
-
"(#{@working_directory})") do |directory|
|
81
|
-
@working_directory = Pathname.new(directory)
|
82
|
-
end
|
83
|
-
|
84
|
-
parser.separator("")
|
85
|
-
parser.separator("Throughput:")
|
86
|
-
parser.on("--n-clients=N", Integer,
|
87
|
-
"Use N clients concurrently.",
|
88
|
-
"(#{@n_clients})") do |n|
|
89
|
-
@n_clients = n
|
90
|
-
end
|
91
|
-
|
92
|
-
parser.separator("")
|
93
|
-
parser.separator("Old Groonga:")
|
94
|
-
parser.on("--old-groonga=GROONGA",
|
95
|
-
"Old groonga command",
|
96
|
-
"(#{@old_groonga})") do |groonga|
|
97
|
-
@old_groonga = groonga
|
98
|
-
end
|
99
|
-
|
100
|
-
parser.on("--old-groonga-option=OPTION",
|
101
|
-
"Add an additional old groonga option",
|
102
|
-
"You can specify this option multiple times to specify multiple groonga options",
|
103
|
-
"(no options)") do |groonga_option|
|
104
|
-
@old_groonga_options << groonga_option
|
105
|
-
end
|
106
|
-
|
107
|
-
parser.separator("")
|
108
|
-
parser.separator("New Groonga:")
|
109
|
-
parser.on("--new-groonga=GROONGA",
|
110
|
-
"New groonga command",
|
111
|
-
"(#{@new_groonga})") do |groonga|
|
112
|
-
@new_groonga = groonga
|
113
|
-
end
|
114
|
-
|
115
|
-
parser.on("--new-groonga-option=OPTION",
|
116
|
-
"Add an additional new groonga option",
|
117
|
-
"You can specify this option multiple times to specify multiple groonga options",
|
118
|
-
"(no options)") do |groonga_option|
|
119
|
-
@new_groonga_options << groonga_option
|
120
|
-
end
|
61
|
+
tester = Tester.new(old_groonga_server,
|
62
|
+
new_groonga_server,
|
63
|
+
tester_options)
|
64
|
+
tester.run
|
65
|
+
end
|
121
66
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
parser.on("--output-query-log",
|
141
|
-
"Output query log in verified target Groonga servers") do
|
142
|
-
@output_query_log = true
|
143
|
-
end
|
144
|
-
parser.on("--no-care-order",
|
145
|
-
"Don't care order of select response records") do
|
146
|
-
@care_order = false
|
147
|
-
end
|
67
|
+
private
|
68
|
+
def create_option_parser
|
69
|
+
parser = OptionParser.new
|
70
|
+
parser.version = VERSION
|
71
|
+
|
72
|
+
parser.separator("")
|
73
|
+
parser.separator("Path:")
|
74
|
+
parser.on("--input-directory=DIRECTORY",
|
75
|
+
"Load schema and data from DIRECTORY.",
|
76
|
+
"(#{@input_directory})") do |directory|
|
77
|
+
@input_directory = Pathname.new(directory)
|
78
|
+
end
|
79
|
+
parser.on("--working-directory=DIRECTORY",
|
80
|
+
"Use DIRECTORY as working directory.",
|
81
|
+
"(#{@working_directory})") do |directory|
|
82
|
+
@working_directory = Pathname.new(directory)
|
83
|
+
end
|
148
84
|
|
149
|
-
|
85
|
+
parser.separator("")
|
86
|
+
parser.separator("Throughput:")
|
87
|
+
parser.on("--n-clients=N", Integer,
|
88
|
+
"Use N clients concurrently.",
|
89
|
+
"(#{@n_clients})") do |n|
|
90
|
+
@n_clients = n
|
150
91
|
end
|
151
92
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
93
|
+
parser.separator("")
|
94
|
+
parser.separator("Old Groonga:")
|
95
|
+
parser.on("--old-groonga=GROONGA",
|
96
|
+
"Old groonga command",
|
97
|
+
"(#{@old_groonga})") do |groonga|
|
98
|
+
@old_groonga = groonga
|
157
99
|
end
|
158
100
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
:output_query_log => @output_query_log,
|
165
|
-
}
|
166
|
-
directory_options.merge(options)
|
101
|
+
parser.on("--old-groonga-option=OPTION",
|
102
|
+
"Add an additional old groonga option",
|
103
|
+
"You can specify this option multiple times to specify multiple groonga options",
|
104
|
+
"(no options)") do |groonga_option|
|
105
|
+
@old_groonga_options << groonga_option
|
167
106
|
end
|
168
107
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
directory_options.merge(options)
|
108
|
+
parser.separator("")
|
109
|
+
parser.separator("New Groonga:")
|
110
|
+
parser.on("--new-groonga=GROONGA",
|
111
|
+
"New groonga command",
|
112
|
+
"(#{@new_groonga})") do |groonga|
|
113
|
+
@new_groonga = groonga
|
176
114
|
end
|
177
115
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
116
|
+
parser.on("--new-groonga-option=OPTION",
|
117
|
+
"Add an additional new groonga option",
|
118
|
+
"You can specify this option multiple times to specify multiple groonga options",
|
119
|
+
"(no options)") do |groonga_option|
|
120
|
+
@new_groonga_options << groonga_option
|
183
121
|
end
|
184
122
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
123
|
+
parser.separator("")
|
124
|
+
parser.separator("Operations:")
|
125
|
+
parser.on("--recreate-database",
|
126
|
+
"Always recreate Groonga database") do
|
127
|
+
@recreate_database = true
|
128
|
+
end
|
129
|
+
parser.on("--no-load-data",
|
130
|
+
"Don't load data. Just loads schema to Groonga database") do
|
131
|
+
@load_data = false
|
132
|
+
end
|
133
|
+
parser.on("--no-run-queries",
|
134
|
+
"Don't run queries. Just creates Groonga database") do
|
135
|
+
@run_queries = false
|
136
|
+
end
|
137
|
+
parser.on("--skip-finished-queries",
|
138
|
+
"Don't run finished query logs.") do
|
139
|
+
@skip_finished_queries = true
|
140
|
+
end
|
141
|
+
parser.on("--output-query-log",
|
142
|
+
"Output query log in verified target Groonga servers") do
|
143
|
+
@output_query_log = true
|
144
|
+
end
|
145
|
+
parser.on("--no-care-order",
|
146
|
+
"Don't care order of select response records") do
|
147
|
+
@care_order = false
|
148
|
+
end
|
149
|
+
parser.on("--ignore-drilldown-key=KEY",
|
150
|
+
"Don't compare drilldown result for KEY",
|
151
|
+
"You can specify multiple drilldown keys by",
|
152
|
+
"specifying this option multiple times") do |key|
|
153
|
+
@ignored_drilldown_keys << key
|
154
|
+
end
|
155
|
+
parser.on("--[no-]stop-on-failure",
|
156
|
+
"Stop execution on the first failure",
|
157
|
+
"(#{@stop_on_failure})") do |boolean|
|
158
|
+
@stop_on_failure = boolean
|
190
159
|
end
|
191
160
|
|
192
|
-
|
193
|
-
|
194
|
-
def initialize(groonga, groonga_options, database_path, options)
|
195
|
-
@input_directory = options[:input_directory] || Pathname.new(".")
|
196
|
-
@working_directory = options[:working_directory] || Pathname.new(".")
|
197
|
-
@groonga = groonga
|
198
|
-
@groonga_options = groonga_options
|
199
|
-
@database_path = @working_directory + database_path
|
200
|
-
@host = "127.0.0.1"
|
201
|
-
@port = find_unused_port
|
202
|
-
@options = options
|
203
|
-
end
|
161
|
+
parser
|
162
|
+
end
|
204
163
|
|
205
|
-
|
206
|
-
|
164
|
+
def directory_options
|
165
|
+
{
|
166
|
+
:input_directory => @input_directory,
|
167
|
+
:working_directory => @working_directory,
|
168
|
+
}
|
169
|
+
end
|
207
170
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
arguments << @database_path.to_s
|
218
|
-
@pid = spawn(@groonga, *arguments)
|
171
|
+
def server_options
|
172
|
+
options = {
|
173
|
+
:load_data => @load_data,
|
174
|
+
:run_queries => @run_queries,
|
175
|
+
:recreate_database => @recreate_database,
|
176
|
+
:output_query_log => @output_query_log,
|
177
|
+
}
|
178
|
+
directory_options.merge(options)
|
179
|
+
end
|
219
180
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
181
|
+
def tester_options
|
182
|
+
options = {
|
183
|
+
:n_clients => @n_clients,
|
184
|
+
:care_order => @care_order,
|
185
|
+
:skip_finished_queries => @skip_finished_queries,
|
186
|
+
:ignored_drilldown_keys => @ignored_drilldown_keys,
|
187
|
+
:stop_on_failure => @stop_on_failure,
|
188
|
+
}
|
189
|
+
directory_options.merge(options)
|
190
|
+
end
|
229
191
|
|
230
|
-
|
231
|
-
|
192
|
+
def old_groonga_server
|
193
|
+
GroongaServer.new(@old_groonga,
|
194
|
+
@old_groonga_options,
|
195
|
+
@old_database,
|
196
|
+
server_options)
|
197
|
+
end
|
232
198
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
199
|
+
def new_groonga_server
|
200
|
+
GroongaServer.new(@new_groonga,
|
201
|
+
@new_groonga_options,
|
202
|
+
@new_database,
|
203
|
+
server_options)
|
204
|
+
end
|
237
205
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
206
|
+
class GroongaServer
|
207
|
+
attr_reader :host, :port
|
208
|
+
def initialize(groonga, groonga_options, database_path, options)
|
209
|
+
@input_directory = options[:input_directory] || Pathname.new(".")
|
210
|
+
@working_directory = options[:working_directory] || Pathname.new(".")
|
211
|
+
@groonga = groonga
|
212
|
+
@groonga_options = groonga_options
|
213
|
+
@database_path = @working_directory + database_path
|
214
|
+
@host = "127.0.0.1"
|
215
|
+
@port = find_unused_port
|
216
|
+
@options = options
|
217
|
+
end
|
218
|
+
|
219
|
+
def run
|
220
|
+
return unless @options[:run_queries]
|
221
|
+
|
222
|
+
arguments = @groonga_options.dup
|
223
|
+
arguments.concat(["--bind-address", @host])
|
224
|
+
arguments.concat(["--port", @port.to_s])
|
225
|
+
arguments.concat(["--protocol", "http"])
|
226
|
+
arguments.concat(["--log-path", log_path.to_s])
|
227
|
+
if @options[:output_query_log]
|
228
|
+
arguments.concat(["--query-log-path", query_log_path.to_s])
|
261
229
|
end
|
230
|
+
arguments << "-s"
|
231
|
+
arguments << @database_path.to_s
|
232
|
+
@pid = spawn(@groonga, *arguments)
|
262
233
|
|
263
|
-
|
264
|
-
|
234
|
+
n_retries = 10
|
235
|
+
begin
|
236
|
+
send_command("status")
|
237
|
+
rescue SystemCallError
|
238
|
+
sleep(1)
|
239
|
+
n_retries -= 1
|
240
|
+
raise if n_retries.zero?
|
241
|
+
retry
|
265
242
|
end
|
266
243
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
244
|
+
yield if block_given?
|
245
|
+
end
|
246
|
+
|
247
|
+
def ensure_database
|
248
|
+
if @options[:recreate_database]
|
249
|
+
FileUtils.rm_rf(@database_path.dirname.to_s)
|
273
250
|
end
|
274
251
|
|
275
|
-
|
276
|
-
|
277
|
-
|
252
|
+
return if @database_path.exist?
|
253
|
+
FileUtils.mkdir_p(@database_path.dirname.to_s)
|
254
|
+
system(@groonga, "-n", @database_path.to_s, "quit")
|
255
|
+
grn_files.each do |grn_file|
|
256
|
+
command = [
|
257
|
+
@groonga,
|
258
|
+
"--log-path", log_path.to_s,
|
259
|
+
"--file", grn_file.to_s,
|
260
|
+
@database_path.to_s,
|
261
|
+
]
|
262
|
+
command_line = command.join(" ")
|
263
|
+
puts("Running...: #{command_line}")
|
264
|
+
pid = spawn(*command)
|
278
265
|
begin
|
279
|
-
|
280
|
-
|
281
|
-
|
266
|
+
pid, status = Process.waitpid2(pid)
|
267
|
+
rescue Interrupt
|
268
|
+
Process.kill(:TERM, pid)
|
269
|
+
pid, status = Process.waitpid2(pid)
|
270
|
+
end
|
271
|
+
unless status.success?
|
272
|
+
raise "Failed to run: #{command_line}"
|
282
273
|
end
|
283
274
|
end
|
275
|
+
end
|
284
276
|
|
285
|
-
|
286
|
-
|
287
|
-
|
277
|
+
def use_persistent_cache?
|
278
|
+
@groonga_options.include?("--cache-base-path")
|
279
|
+
end
|
288
280
|
|
289
|
-
|
290
|
-
|
281
|
+
def shutdown
|
282
|
+
begin
|
283
|
+
send_command("shutdown")
|
284
|
+
rescue SystemCallError
|
291
285
|
end
|
286
|
+
Process.waitpid(@pid)
|
287
|
+
end
|
292
288
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
289
|
+
private
|
290
|
+
def find_unused_port
|
291
|
+
server = TCPServer.new(@host, 0)
|
292
|
+
begin
|
293
|
+
server.addr[1]
|
294
|
+
ensure
|
295
|
+
server.close
|
298
296
|
end
|
297
|
+
end
|
299
298
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
files += index_files
|
304
|
-
files
|
305
|
-
end
|
299
|
+
def log_path
|
300
|
+
@database_path.dirname + "groonga.log"
|
301
|
+
end
|
306
302
|
|
307
|
-
|
308
|
-
|
309
|
-
|
303
|
+
def query_log_path
|
304
|
+
@database_path.dirname + "query.log"
|
305
|
+
end
|
310
306
|
|
311
|
-
|
312
|
-
|
307
|
+
def send_command(name)
|
308
|
+
Net::HTTP.start(@host, @port) do |http|
|
309
|
+
response = http.get("/d/#{name}")
|
310
|
+
response.body
|
313
311
|
end
|
312
|
+
end
|
314
313
|
|
315
|
-
|
316
|
-
|
317
|
-
|
314
|
+
def grn_files
|
315
|
+
files = schema_files
|
316
|
+
files += data_files if @options[:load_data]
|
317
|
+
files += index_files
|
318
|
+
files
|
318
319
|
end
|
319
320
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
@new = new
|
324
|
-
@input_directory = options[:input_directory] || Pathname.new(".")
|
325
|
-
@working_directory = options[:working_directory] || Pathname.new(".")
|
326
|
-
@n_clients = options[:n_clients] || 1
|
327
|
-
@options = options
|
328
|
-
@n_ready_waits = 2
|
329
|
-
end
|
321
|
+
def schema_files
|
322
|
+
Pathname.glob("#{@input_directory}/schema/**/*.grn").sort
|
323
|
+
end
|
330
324
|
|
331
|
-
|
332
|
-
|
333
|
-
|
325
|
+
def index_files
|
326
|
+
Pathname.glob("#{@input_directory}/indexes/**/*.grn").sort
|
327
|
+
end
|
334
328
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
end
|
340
|
-
new_thread = Thread.new do
|
341
|
-
@new.run do
|
342
|
-
run_test
|
343
|
-
end
|
344
|
-
end
|
329
|
+
def data_files
|
330
|
+
Pathname.glob("#{@input_directory}/data/**/*.grn").sort
|
331
|
+
end
|
332
|
+
end
|
345
333
|
|
346
|
-
|
347
|
-
|
334
|
+
class Tester
|
335
|
+
def initialize(old, new, options)
|
336
|
+
@old = old
|
337
|
+
@new = new
|
338
|
+
@input_directory = options[:input_directory] || Pathname.new(".")
|
339
|
+
@working_directory = options[:working_directory] || Pathname.new(".")
|
340
|
+
@n_clients = options[:n_clients] || 1
|
341
|
+
@stop_on_failure = options[:stop_on_failure]
|
342
|
+
@options = options
|
343
|
+
@n_ready_waits = 2
|
344
|
+
end
|
345
|
+
|
346
|
+
def run
|
347
|
+
@old.ensure_database
|
348
|
+
@new.ensure_database
|
348
349
|
|
349
|
-
|
350
|
+
old_thread = Thread.new do
|
351
|
+
@old.run do
|
352
|
+
run_test
|
353
|
+
end
|
354
|
+
end
|
355
|
+
new_thread = Thread.new do
|
356
|
+
@new.run do
|
357
|
+
run_test
|
358
|
+
end
|
350
359
|
end
|
351
360
|
|
352
|
-
|
353
|
-
|
354
|
-
@n_ready_waits -= 1
|
355
|
-
return true unless @n_ready_waits.zero?
|
361
|
+
old_thread_success = old_thread.value
|
362
|
+
new_thread_success = new_thread.value
|
356
363
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
364
|
+
old_thread_success and new_thread_success
|
365
|
+
end
|
366
|
+
|
367
|
+
private
|
368
|
+
def run_test
|
369
|
+
@n_ready_waits -= 1
|
370
|
+
return true unless @n_ready_waits.zero?
|
371
|
+
|
372
|
+
same = true
|
373
|
+
query_log_paths.each do |query_log_path|
|
374
|
+
log_path = test_log_path(query_log_path)
|
375
|
+
if @options[:skip_finished_queries] and log_path.exist?
|
376
|
+
puts("Skip query log: #{query_log_path}")
|
377
|
+
next
|
378
|
+
else
|
379
|
+
puts("Running test against query log...: #{query_log_path}")
|
380
|
+
end
|
381
|
+
begin
|
382
|
+
if use_persistent_cache?
|
383
|
+
callback = lambda do
|
384
|
+
if @old.use_persistent_cache?
|
385
|
+
@old.shutdown
|
386
|
+
@old.run
|
387
|
+
end
|
388
|
+
if @new.use_persistent_cache?
|
389
|
+
@new.shutdown
|
390
|
+
@new.run
|
376
391
|
end
|
377
|
-
else
|
378
|
-
callback = nil
|
379
392
|
end
|
380
|
-
|
381
|
-
|
382
|
-
puts("Interrupt: #{query_log_path}")
|
393
|
+
else
|
394
|
+
callback = nil
|
383
395
|
end
|
396
|
+
unless verify_server(log_path, query_log_path, &callback)
|
397
|
+
same = false
|
398
|
+
break if @stop_on_failure
|
399
|
+
end
|
400
|
+
rescue Interrupt
|
401
|
+
puts("Interrupt: #{query_log_path}")
|
384
402
|
end
|
385
|
-
|
386
|
-
old_thread = Thread.new do
|
387
|
-
@old.shutdown
|
388
|
-
end
|
389
|
-
new_thread = Thread.new do
|
390
|
-
@new.shutdown
|
391
|
-
end
|
392
|
-
old_thread.join
|
393
|
-
new_thread.join
|
394
|
-
|
395
|
-
true
|
396
403
|
end
|
397
404
|
|
398
|
-
|
399
|
-
|
400
|
-
"--n-clients=#{@n_clients}",
|
401
|
-
"--groonga1-host=#{@old.host}",
|
402
|
-
"--groonga1-port=#{@old.port}",
|
403
|
-
"--groonga1-protocol=http",
|
404
|
-
"--groonga2-host=#{@new.host}",
|
405
|
-
"--groonga2-port=#{@new.port}",
|
406
|
-
"--groonga2-protocol=http",
|
407
|
-
"--output", test_log_path.to_s,
|
408
|
-
]
|
409
|
-
command_line << "--no-care-order" if @options[:care_order] == false
|
410
|
-
command_line << query_log_path.to_s
|
411
|
-
if use_persistent_cache?
|
412
|
-
command_line << "--verify-cache"
|
413
|
-
end
|
414
|
-
verify_server = VerifyServer.new
|
415
|
-
verify_server.run(command_line, &callback)
|
405
|
+
old_thread = Thread.new do
|
406
|
+
@old.shutdown
|
416
407
|
end
|
417
|
-
|
418
|
-
|
419
|
-
Pathname.glob("#{@input_directory}/query-logs/**/*.log").sort
|
408
|
+
new_thread = Thread.new do
|
409
|
+
@new.shutdown
|
420
410
|
end
|
411
|
+
old_thread.join
|
412
|
+
new_thread.join
|
421
413
|
|
422
|
-
|
423
|
-
|
424
|
-
end
|
414
|
+
same
|
415
|
+
end
|
425
416
|
|
426
|
-
|
427
|
-
|
428
|
-
|
417
|
+
def verify_server(test_log_path, query_log_path, &callback)
|
418
|
+
command_line = [
|
419
|
+
"--n-clients=#{@n_clients}",
|
420
|
+
"--groonga1-host=#{@old.host}",
|
421
|
+
"--groonga1-port=#{@old.port}",
|
422
|
+
"--groonga1-protocol=http",
|
423
|
+
"--groonga2-host=#{@new.host}",
|
424
|
+
"--groonga2-port=#{@new.port}",
|
425
|
+
"--groonga2-protocol=http",
|
426
|
+
"--output", test_log_path.to_s,
|
427
|
+
]
|
428
|
+
command_line << "--no-care-order" if @options[:care_order] == false
|
429
|
+
@options[:ignored_drilldown_keys].each do |key|
|
430
|
+
command_line.concat(["--ignore-drilldown-key", key])
|
431
|
+
end
|
432
|
+
command_line << query_log_path.to_s
|
433
|
+
if use_persistent_cache?
|
434
|
+
command_line << "--verify-cache"
|
435
|
+
end
|
436
|
+
if @stop_on_failure
|
437
|
+
command_line << "--stop-on-failure"
|
438
|
+
end
|
439
|
+
verify_server = VerifyServer.new
|
440
|
+
verify_server.run(command_line, &callback)
|
441
|
+
end
|
442
|
+
|
443
|
+
def query_log_paths
|
444
|
+
Pathname.glob("#{@input_directory}/query-logs/**/*.log").sort
|
445
|
+
end
|
446
|
+
|
447
|
+
def test_log_path(query_log_path)
|
448
|
+
@working_directory + "results" + query_log_path.basename
|
449
|
+
end
|
450
|
+
|
451
|
+
def use_persistent_cache?
|
452
|
+
@old.use_persistent_cache? or @new.use_persistent_cache?
|
429
453
|
end
|
430
454
|
end
|
431
455
|
end
|
456
|
+
end
|
432
457
|
end
|