grntest 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +334 -35
- data/doc/text/news.md +33 -0
- data/lib/grntest/tester.rb +214 -47
- data/lib/grntest/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -6,7 +6,8 @@ grntest
|
|
6
6
|
|
7
7
|
## Description
|
8
8
|
|
9
|
-
Grntest is a testing framework for groonga. You can write a test for
|
9
|
+
Grntest is a testing framework for groonga. You can write a test for
|
10
|
+
groonga by writing groonga commands and expected result.
|
10
11
|
|
11
12
|
## Install
|
12
13
|
|
@@ -14,9 +15,7 @@ Grntest is a testing framework for groonga. You can write a test for groonga by
|
|
14
15
|
% gem install grntest
|
15
16
|
```
|
16
17
|
|
17
|
-
##
|
18
|
-
|
19
|
-
### Basic usage
|
18
|
+
## Basic usage
|
20
19
|
|
21
20
|
Write a test script that extension is `.test`. Here is a sample test
|
22
21
|
script `select.test`:
|
@@ -40,7 +39,7 @@ Run `grntest` with `select.test` as command line argument:
|
|
40
39
|
N
|
41
40
|
================================================================================
|
42
41
|
.
|
43
|
-
select 0.
|
42
|
+
select 0.3866s [not checked]
|
44
43
|
================================================================================
|
45
44
|
table_create Users TABLE_HASH_KEY ShortText
|
46
45
|
[[0,0.0,0.0],true]
|
@@ -55,8 +54,9 @@ select Users --query '_key:Alice'
|
|
55
54
|
================================================================================
|
56
55
|
|
57
56
|
|
58
|
-
|
59
|
-
0
|
57
|
+
tests/sec | tests | passes | failures | leaked | !checked |
|
58
|
+
2.57 | 1 | 0 | 0 | 0 | 1 |
|
59
|
+
0% passed in 0.3885s.
|
60
60
|
```
|
61
61
|
|
62
62
|
It generates `select.actual` file that contains actual result. If it
|
@@ -72,8 +72,9 @@ Run `grntest` again:
|
|
72
72
|
% grntest select.test
|
73
73
|
.
|
74
74
|
|
75
|
-
|
76
|
-
|
75
|
+
tests/sec | tests | passes | failures | leaked | !checked |
|
76
|
+
5.76 | 1 | 1 | 0 | 0 | 0 |
|
77
|
+
100% passed in 0.1736s.
|
77
78
|
```
|
78
79
|
|
79
80
|
It compares actual result and content of `select.expected` and
|
@@ -103,23 +104,24 @@ Run `grntest` again:
|
|
103
104
|
F
|
104
105
|
================================================================================
|
105
106
|
.
|
106
|
-
select 0.
|
107
|
+
select 0.1767s [failed]
|
107
108
|
================================================================================
|
108
|
-
--- (
|
109
|
-
+++ (
|
109
|
+
--- (expected)
|
110
|
+
+++ (actual)
|
110
111
|
@@ -6,5 +6,5 @@
|
111
112
|
{"_key": "Bob"}
|
112
113
|
]
|
113
114
|
[[0,0.0,0.0],2]
|
114
|
-
-select Users --query '_key:
|
115
|
-
-[[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[
|
116
|
-
+select Users --query '_key:
|
117
|
-
+[[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[
|
115
|
+
-select Users --query '_key:Alice'
|
116
|
+
-[[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[1,"Alice"]]]]
|
117
|
+
+select Users --query '_key:Bob'
|
118
|
+
+[[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[2,"Bob"]]]]
|
118
119
|
================================================================================
|
119
120
|
|
120
121
|
|
121
|
-
|
122
|
-
0
|
122
|
+
tests/sec | tests | passes | failures | leaked | !checked |
|
123
|
+
4.65 | 1 | 0 | 1 | 0 | 0 |
|
124
|
+
0% passed in 0.2153s.
|
123
125
|
```
|
124
126
|
|
125
127
|
It says the expected result that is read from `select.expected` and
|
@@ -140,19 +142,284 @@ Run `grntest` again:
|
|
140
142
|
% grntest select.test
|
141
143
|
.
|
142
144
|
|
143
|
-
|
144
|
-
|
145
|
+
tests/sec | tests | passes | failures | leaked | !checked |
|
146
|
+
6.20 | 1 | 1 | 0 | 0 | 0 |
|
147
|
+
100% passed in 0.1613s.
|
145
148
|
```
|
146
149
|
|
147
150
|
The test is succeeded again.
|
148
151
|
|
149
|
-
|
152
|
+
## Advanced usage
|
153
|
+
|
154
|
+
There are more useful features. They are not needed for normal
|
155
|
+
users but they are very useful for advanced users.
|
156
|
+
|
157
|
+
There are advanced features:
|
158
|
+
|
159
|
+
* Comment
|
160
|
+
* Continuation line
|
161
|
+
* Directives
|
162
|
+
|
163
|
+
### Comment
|
164
|
+
|
165
|
+
Groonga supports comment line by `#`.
|
166
|
+
|
167
|
+
Example:
|
168
|
+
|
169
|
+
```
|
170
|
+
# This line is comment line.
|
171
|
+
select Users
|
172
|
+
```
|
173
|
+
|
174
|
+
Grntest also supports the syntax. You can use `#` as comment mark.
|
175
|
+
|
176
|
+
### Continuation line
|
177
|
+
|
178
|
+
You can break a long line by escaping new line with `\`.
|
179
|
+
|
180
|
+
Example:
|
181
|
+
|
182
|
+
```
|
183
|
+
select Users \
|
184
|
+
--match_columns name \
|
185
|
+
--query Ken
|
186
|
+
```
|
187
|
+
|
188
|
+
The command is processed as the following command:
|
189
|
+
|
190
|
+
```
|
191
|
+
select Users --match_columns name --query Ken
|
192
|
+
```
|
193
|
+
|
194
|
+
You can make your test readable with this feature.
|
195
|
+
|
196
|
+
Groogna doesn't support this feature.
|
197
|
+
|
198
|
+
### Directives
|
199
|
+
|
200
|
+
Grntest supports directives that control grntest behavior.
|
201
|
+
|
202
|
+
Here is directive syntax:
|
203
|
+
|
204
|
+
```
|
205
|
+
#@NAME [ARGUMENTS...]
|
206
|
+
```
|
150
207
|
|
151
|
-
|
208
|
+
Here are available `NAME` s:
|
152
209
|
|
153
|
-
|
210
|
+
* `disable-logging`
|
211
|
+
* `enable-logging`
|
212
|
+
* `suggest-create-dataset`
|
213
|
+
* `include`
|
214
|
+
* `copy-path`
|
154
215
|
|
155
|
-
|
216
|
+
`ARGUMENTS...` are depends on directive. A directive doesn't require
|
217
|
+
any arguments but a directive requires arguments.
|
218
|
+
|
219
|
+
#### `disable-logging`
|
220
|
+
|
221
|
+
Usage:
|
222
|
+
|
223
|
+
```
|
224
|
+
#@disable-logging
|
225
|
+
```
|
226
|
+
|
227
|
+
It disables logging executed command and executed result until
|
228
|
+
`enable-logging` directive is used. It is useful for executing
|
229
|
+
commands that isn't important for test.
|
230
|
+
|
231
|
+
Example:
|
232
|
+
|
233
|
+
```
|
234
|
+
#@disable-logging
|
235
|
+
load --table Users
|
236
|
+
[
|
237
|
+
{"_key": "User1"},
|
238
|
+
{"_key": "..."},
|
239
|
+
{"_key": "User9999999"}
|
240
|
+
]
|
241
|
+
#@enable-logging
|
242
|
+
|
243
|
+
select Users --query _key:User29
|
244
|
+
```
|
245
|
+
|
246
|
+
See also: `enable-logging`
|
247
|
+
|
248
|
+
### `enable-logging`
|
249
|
+
|
250
|
+
Usage:
|
251
|
+
|
252
|
+
```
|
253
|
+
#@enable-logging
|
254
|
+
```
|
255
|
+
|
256
|
+
It enables logging that is disabled by `disable-logging` directive.
|
257
|
+
|
258
|
+
See also: `disable-logging`
|
259
|
+
|
260
|
+
### suggest-create-dataset
|
261
|
+
|
262
|
+
Usage:
|
263
|
+
|
264
|
+
```
|
265
|
+
#@suggest-create-dataset DATASET_NAME
|
266
|
+
```
|
267
|
+
|
268
|
+
It creates dataset `DATASET_NAME` for suggest feature. It is useful
|
269
|
+
for testing suggest feature.
|
270
|
+
|
271
|
+
Example:
|
272
|
+
|
273
|
+
```
|
274
|
+
#@suggest-create-dataset rurema
|
275
|
+
load --table event_rurema --each 'suggest_preparer(_id, type, item, sequence, time, pair_rurema)'
|
276
|
+
[
|
277
|
+
["sequence", "time", "item", "type"],
|
278
|
+
["21e80fd5e5bc2126469db1c927b7a48fb3353dd9",1312134098.0,"f",null],
|
279
|
+
["21e80fd5e5bc2126469db1c927b7a48fb3353dd9",1312134105.0,"er",null],
|
280
|
+
["21e80fd5e5bc2126469db1c927b7a48fb3353dd9",1312134106.0,"erb",null],
|
281
|
+
["21e80fd5e5bc2126469db1c927b7a48fb3353dd9",1312134107.0,"erb","submit"]
|
282
|
+
]
|
283
|
+
```
|
284
|
+
|
285
|
+
See also: `--groonga-suggest-create-dataset` option
|
286
|
+
|
287
|
+
### include
|
288
|
+
|
289
|
+
Usage:
|
290
|
+
|
291
|
+
```
|
292
|
+
#@include SUB_TEST_FILE_PATH
|
293
|
+
```
|
294
|
+
|
295
|
+
It includes `SUB_TEST_FILE_PATH` content. It is useful for sharing
|
296
|
+
commands by many tests.
|
297
|
+
|
298
|
+
You can use `include` in included file. It means that an included file
|
299
|
+
is processed in the same way as a test file.
|
300
|
+
|
301
|
+
If `SUB_TEST_FILE_PATH` is relative path, `SUB_TEST_FILE_PATH` is
|
302
|
+
found from base directory. Base directory can be specified by
|
303
|
+
`--base-directory` option.
|
304
|
+
|
305
|
+
Example:
|
306
|
+
|
307
|
+
init.grn:
|
308
|
+
|
309
|
+
```
|
310
|
+
#@disable-logging
|
311
|
+
#@include ddl.grn
|
312
|
+
#@include data.grn
|
313
|
+
#@enable-logging
|
314
|
+
```
|
315
|
+
|
316
|
+
ddl.grn:
|
317
|
+
|
318
|
+
```
|
319
|
+
table_create Users TABLE_HASH_KEY ShortText
|
320
|
+
```
|
321
|
+
|
322
|
+
data.grn:
|
323
|
+
|
324
|
+
```
|
325
|
+
load --table Users
|
326
|
+
[
|
327
|
+
["_key"],
|
328
|
+
["Alice"],
|
329
|
+
["Bob"]
|
330
|
+
]
|
331
|
+
```
|
332
|
+
|
333
|
+
user.test:
|
334
|
+
|
335
|
+
```
|
336
|
+
#@include init.grn
|
337
|
+
select Users --query _key:Alice
|
338
|
+
```
|
339
|
+
|
340
|
+
See also: `--base-directory` option
|
341
|
+
|
342
|
+
### `copy-path`
|
343
|
+
|
344
|
+
Usage
|
345
|
+
|
346
|
+
```
|
347
|
+
#@copy-path SOURCE DESTINATION
|
348
|
+
```
|
349
|
+
|
350
|
+
It copies a path from `SOURCE` to `DESTINATION`. You can use it for
|
351
|
+
both file and directory. It is useful for using fixture data.
|
352
|
+
|
353
|
+
Example:
|
354
|
+
|
355
|
+
```
|
356
|
+
#@copy-path fixture/query_expander/tsv/japanese_synonyms.tsv tmp/synonyms.tsv
|
357
|
+
register "query_expanders/tsv"
|
358
|
+
```
|
359
|
+
|
360
|
+
## Options
|
361
|
+
|
362
|
+
Grntest has many options. You don't need to specify many of them
|
363
|
+
because they use suitable default values.
|
364
|
+
|
365
|
+
This section describes some important options. You can see all options
|
366
|
+
by `grntest --help`. You will find many usuful features from it.
|
367
|
+
|
368
|
+
### `--test`
|
369
|
+
|
370
|
+
Usage:
|
371
|
+
|
372
|
+
```
|
373
|
+
% grntest --test TEST_NAME ...
|
374
|
+
% grntest --test /TEST_NAME_REGEXP/ ...
|
375
|
+
% grntest --test TEST_NAME1 --test TEST_NAME2 ...
|
376
|
+
% grntest --test /TEST_NAME_REGEXP1/ --test /TEST_NAME_REGEXP2/ ...
|
377
|
+
```
|
378
|
+
|
379
|
+
`--test` option specifies tests that should be ran. It is useful when
|
380
|
+
you are interested in only one test.
|
381
|
+
|
382
|
+
For example, the following command line runs only `vector-geo-point`
|
383
|
+
test.
|
384
|
+
|
385
|
+
```
|
386
|
+
% grntest --test vector-geo-point ...
|
387
|
+
```
|
388
|
+
|
389
|
+
You can use `--test` option multiple times to run only multiple
|
390
|
+
interested tests.
|
391
|
+
|
392
|
+
For example, the following command line runs only `vector-geo-point`
|
393
|
+
and `hash` tests.
|
394
|
+
|
395
|
+
```
|
396
|
+
% grntest --test vector-geo-point --test hash ...
|
397
|
+
```
|
398
|
+
|
399
|
+
You can use regular expression to select tests by `/.../` syntax.
|
400
|
+
|
401
|
+
For example, the following command line runs tests that have `geo` in
|
402
|
+
its name.
|
403
|
+
|
404
|
+
```
|
405
|
+
% grntest --test /geo/ ...
|
406
|
+
```
|
407
|
+
|
408
|
+
You can also use multiple --test options with regular expression.
|
409
|
+
|
410
|
+
See also: `--exclude-test` option
|
411
|
+
|
412
|
+
### `--exclude-test`
|
413
|
+
|
414
|
+
### `--test-suite`
|
415
|
+
|
416
|
+
### `--exclude-test-suite`
|
417
|
+
|
418
|
+
### `--gdb`
|
419
|
+
|
420
|
+
### `--keep-database`
|
421
|
+
|
422
|
+
### `--n-workers`
|
156
423
|
|
157
424
|
`--n-workers` option is very useful. You can run many test scripts at
|
158
425
|
once. Tests are finished quickly. You should specify one or more
|
@@ -163,31 +430,62 @@ Here is a sample command line to use `--n-workers`:
|
|
163
430
|
|
164
431
|
```
|
165
432
|
% grntest --n-workers 4 test/function/suite/suggest
|
433
|
+
tests/sec | tests | passes | failures | leaked | !checked |
|
166
434
|
[0] [finished]
|
167
|
-
|
435
|
+
9.95 | 5 | 5 | 0 | 0 | 0 |
|
168
436
|
[1] [finished]
|
169
|
-
|
437
|
+
9.22 | 4 | 4 | 0 | 0 | 0 |
|
170
438
|
[2] [finished]
|
171
|
-
|
439
|
+
9.11 | 4 | 4 | 0 | 0 | 0 |
|
172
440
|
[3] [finished]
|
173
|
-
|
441
|
+
10.10 | 5 | 5 | 0 | 0 | 0 |
|
174
442
|
|-----------------------------------------------------------------------| [100%]
|
175
443
|
|
176
|
-
|
177
|
-
|
444
|
+
tests/sec | tests | passes | failures | leaked | !checked |
|
445
|
+
34.61 | 18 | 18 | 0 | 0 | 0 |
|
446
|
+
100% passed in 0.5201s.
|
447
|
+
```
|
448
|
+
|
449
|
+
### `--base-directory`
|
450
|
+
|
451
|
+
### `--database=PATH`
|
452
|
+
|
453
|
+
Usage:
|
454
|
+
|
178
455
|
```
|
456
|
+
% grntest --database /PATH/TO/EXISTING/DATABASE ...
|
457
|
+
```
|
458
|
+
|
459
|
+
`--database` option specifies an existing database that is used for
|
460
|
+
test. Normally, grntest uses a new empty database for test.
|
461
|
+
|
462
|
+
`--database` option is very useful for testing against existing
|
463
|
+
database.
|
464
|
+
|
465
|
+
### `--groonga`
|
466
|
+
|
467
|
+
### `--groonga-httpd`
|
468
|
+
|
469
|
+
### `--groonga-suggest-create-dataset`
|
470
|
+
|
471
|
+
### `--interface`
|
472
|
+
|
473
|
+
### `--output-type`
|
474
|
+
|
475
|
+
### `--testee`
|
179
476
|
|
180
|
-
|
477
|
+
## Examples
|
181
478
|
|
182
|
-
See [test/
|
183
|
-
source](https://github.com/groonga/groonga/tree/master/test/
|
479
|
+
See [test/command/ directory in groonga's
|
480
|
+
source](https://github.com/groonga/groonga/tree/master/test/command). It
|
184
481
|
has many test scripts and uses many useful features. They will help you.
|
185
482
|
|
186
483
|
## Dependencies
|
187
484
|
|
188
485
|
* Ruby 1.9.3
|
486
|
+
* msgpack gem
|
189
487
|
|
190
|
-
|
488
|
+
## Mailing list
|
191
489
|
|
192
490
|
* English: [groonga-talk@lists.sourceforge.net](https://lists.sourceforge.net/lists/listinfo/groonga-talk)
|
193
491
|
* Japanese: [groonga-dev@lists.sourceforge.jp](http://lists.sourceforge.jp/mailman/listinfo/groonga-dev)
|
@@ -205,4 +503,5 @@ has many test scripts and uses many useful features. They will help you.
|
|
205
503
|
|
206
504
|
GPLv3 or later. See doc/text/gpl-3.0.txt for details.
|
207
505
|
|
208
|
-
(Kouhei Sutou has a right to change the license including contributed
|
506
|
+
(Kouhei Sutou has a right to change the license including contributed
|
507
|
+
patches.)
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,38 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 1.0.1: 2012-10-15
|
4
|
+
|
5
|
+
This has a backward incompatible change. It is directive syntax.
|
6
|
+
|
7
|
+
Old:
|
8
|
+
|
9
|
+
# NAME ARGUMENT
|
10
|
+
|
11
|
+
New:
|
12
|
+
|
13
|
+
#@NAME ARGUMENT
|
14
|
+
|
15
|
+
This change is for easy to debug. Conssider about we have a typo in
|
16
|
+
`NAME`. It is just ignored in old syntax because it is also a comment
|
17
|
+
line. It is reported in new syntax because it syntax is only for
|
18
|
+
directive. Grntest can know that user want to use a directive. If
|
19
|
+
grntest knows that user want to use a directive, grntest can report an
|
20
|
+
error for an unknown directive name.
|
21
|
+
|
22
|
+
### Improvements
|
23
|
+
|
24
|
+
* Inverted expected and actual in diff.
|
25
|
+
* Added memory leak check.
|
26
|
+
* Documented many features.
|
27
|
+
* Changed directive syntax.
|
28
|
+
* Added `copy-path` directive.
|
29
|
+
* Supported multiple `--test` and `--test-suite` options.
|
30
|
+
* Added `--database` option.
|
31
|
+
|
32
|
+
### Fixes
|
33
|
+
|
34
|
+
* Fixed a problem that test report can't be shown for no tests.
|
35
|
+
|
3
36
|
## 1.0.0: 2012-08-29
|
4
37
|
|
5
38
|
The first release!!!
|
data/lib/grntest/tester.rb
CHANGED
@@ -122,6 +122,13 @@ module Grntest
|
|
122
122
|
tester.base_directory = Pathname(directory)
|
123
123
|
end
|
124
124
|
|
125
|
+
parser.on("--database=PATH",
|
126
|
+
"Use existing database at PATH " +
|
127
|
+
"instead of creating a new database",
|
128
|
+
"(creating a new database)") do |path|
|
129
|
+
tester.database_path = path
|
130
|
+
end
|
131
|
+
|
125
132
|
parser.on("--diff=DIFF",
|
126
133
|
"Use DIFF as diff command",
|
127
134
|
"(#{tester.diff})") do |diff|
|
@@ -224,7 +231,7 @@ module Grntest
|
|
224
231
|
|
225
232
|
attr_accessor :groonga, :groonga_httpd, :groonga_suggest_create_dataset
|
226
233
|
attr_accessor :interface, :output_type, :testee
|
227
|
-
attr_accessor :base_directory, :diff, :diff_options
|
234
|
+
attr_accessor :base_directory, :database_path, :diff, :diff_options
|
228
235
|
attr_accessor :n_workers
|
229
236
|
attr_accessor :output
|
230
237
|
attr_accessor :gdb, :default_gdb
|
@@ -239,6 +246,7 @@ module Grntest
|
|
239
246
|
@output_type = "json"
|
240
247
|
@testee = "groonga"
|
241
248
|
@base_directory = Pathname(".")
|
249
|
+
@database_path = nil
|
242
250
|
@reporter = nil
|
243
251
|
@n_workers = 1
|
244
252
|
@output = $stdout
|
@@ -288,7 +296,8 @@ module Grntest
|
|
288
296
|
end
|
289
297
|
|
290
298
|
def selected_test?(test_name)
|
291
|
-
@test_patterns.
|
299
|
+
return true if @test_patterns.empty?
|
300
|
+
@test_patterns.any? do |pattern|
|
292
301
|
pattern === test_name
|
293
302
|
end
|
294
303
|
end
|
@@ -305,7 +314,8 @@ module Grntest
|
|
305
314
|
end
|
306
315
|
|
307
316
|
def selected_test_suite?(test_suite_name)
|
308
|
-
@test_suite_patterns.
|
317
|
+
return true if @test_suite_patterns.empty?
|
318
|
+
@test_suite_patterns.any? do |pattern|
|
309
319
|
pattern === test_suite_name
|
310
320
|
end
|
311
321
|
end
|
@@ -396,12 +406,14 @@ module Grntest
|
|
396
406
|
end
|
397
407
|
|
398
408
|
class WorkerResult < Result
|
399
|
-
attr_reader :n_tests, :n_passed_tests, :
|
409
|
+
attr_reader :n_tests, :n_passed_tests, :n_leaked_tests
|
410
|
+
attr_reader :n_not_checked_tests
|
400
411
|
attr_reader :failed_tests
|
401
412
|
def initialize
|
402
413
|
super
|
403
414
|
@n_tests = 0
|
404
415
|
@n_passed_tests = 0
|
416
|
+
@n_leaked_tests = 0
|
405
417
|
@n_not_checked_tests = 0
|
406
418
|
@failed_tests = []
|
407
419
|
end
|
@@ -422,6 +434,10 @@ module Grntest
|
|
422
434
|
@failed_tests << name
|
423
435
|
end
|
424
436
|
|
437
|
+
def test_leaked(name)
|
438
|
+
@n_leaked_tests += 1
|
439
|
+
end
|
440
|
+
|
425
441
|
def test_not_checked
|
426
442
|
@n_not_checked_tests += 1
|
427
443
|
end
|
@@ -501,10 +517,16 @@ module Grntest
|
|
501
517
|
@reporter.fail_test(self, result)
|
502
518
|
end
|
503
519
|
|
504
|
-
def
|
520
|
+
def leaked_test(result)
|
521
|
+
@status = "leaked(#{result.n_leaked_objects})"
|
522
|
+
@result.test_leaked(test_name)
|
523
|
+
@reporter.leaked_test(self, result)
|
524
|
+
end
|
525
|
+
|
526
|
+
def not_checked_test(result)
|
505
527
|
@status = "not checked"
|
506
528
|
@result.test_not_checked
|
507
|
-
@reporter.
|
529
|
+
@reporter.not_checked_test(self, result)
|
508
530
|
end
|
509
531
|
|
510
532
|
def finish_test(result)
|
@@ -545,6 +567,10 @@ module Grntest
|
|
545
567
|
collect_count(:n_failed_tests)
|
546
568
|
end
|
547
569
|
|
570
|
+
def n_leaked_tests
|
571
|
+
collect_count(:n_leaked_tests)
|
572
|
+
end
|
573
|
+
|
548
574
|
def n_not_checked_tests
|
549
575
|
collect_count(:n_not_checked_tests)
|
550
576
|
end
|
@@ -633,24 +659,33 @@ module Grntest
|
|
633
659
|
|
634
660
|
class TestResult < Result
|
635
661
|
attr_accessor :worker_id, :test_name
|
636
|
-
attr_accessor :expected, :actual
|
662
|
+
attr_accessor :expected, :actual, :n_leaked_objects
|
637
663
|
def initialize(worker)
|
638
664
|
super()
|
639
665
|
@worker_id = worker.id
|
640
666
|
@test_name = worker.test_name
|
641
667
|
@actual = nil
|
642
668
|
@expected = nil
|
669
|
+
@n_leaked_objects = 0
|
643
670
|
end
|
644
671
|
|
645
672
|
def status
|
646
673
|
if @expected
|
647
674
|
if @actual == @expected
|
648
|
-
|
675
|
+
if @n_leaked_objects.zero?
|
676
|
+
:success
|
677
|
+
else
|
678
|
+
:leaked
|
679
|
+
end
|
649
680
|
else
|
650
681
|
:failure
|
651
682
|
end
|
652
683
|
else
|
653
|
-
|
684
|
+
if @n_leaked_objects.zero?
|
685
|
+
:not_checked
|
686
|
+
else
|
687
|
+
:leaked
|
688
|
+
end
|
654
689
|
end
|
655
690
|
end
|
656
691
|
end
|
@@ -673,7 +708,7 @@ module Grntest
|
|
673
708
|
result.measure do
|
674
709
|
result.actual = execute_groonga_script
|
675
710
|
end
|
676
|
-
|
711
|
+
normalize_actual_result(result)
|
677
712
|
result.expected = read_expected_result
|
678
713
|
case result.status
|
679
714
|
when :success
|
@@ -683,8 +718,11 @@ module Grntest
|
|
683
718
|
@worker.fail_test(result)
|
684
719
|
output_reject_file(result.actual)
|
685
720
|
succeeded = false
|
721
|
+
when :leaked
|
722
|
+
@worker.leaked_test(result)
|
723
|
+
succeeded = false
|
686
724
|
else
|
687
|
-
@worker.
|
725
|
+
@worker.not_checked_test(result)
|
688
726
|
output_actual_file(result.actual)
|
689
727
|
end
|
690
728
|
@worker.finish_test(result)
|
@@ -695,9 +733,13 @@ module Grntest
|
|
695
733
|
private
|
696
734
|
def execute_groonga_script
|
697
735
|
create_temporary_directory do |directory_path|
|
698
|
-
|
699
|
-
|
700
|
-
|
736
|
+
if @tester.database_path
|
737
|
+
db_path = Pathname(@tester.database_path).expand_path
|
738
|
+
else
|
739
|
+
db_dir = directory_path + "db"
|
740
|
+
FileUtils.mkdir_p(db_dir.to_s)
|
741
|
+
db_path = db_dir + "db"
|
742
|
+
end
|
701
743
|
context = Executor::Context.new
|
702
744
|
context.temporary_directory_path = directory_path
|
703
745
|
context.db_path = db_path
|
@@ -708,6 +750,7 @@ module Grntest
|
|
708
750
|
run_groonga(context) do |executor|
|
709
751
|
executor.execute(test_script_path)
|
710
752
|
end
|
753
|
+
check_memory_leak(context)
|
711
754
|
context.result
|
712
755
|
end
|
713
756
|
end
|
@@ -734,6 +777,10 @@ module Grntest
|
|
734
777
|
end
|
735
778
|
|
736
779
|
def run_groonga(context, &block)
|
780
|
+
unless @tester.database_path
|
781
|
+
create_empty_database(context.db_path.to_s)
|
782
|
+
end
|
783
|
+
|
737
784
|
case @tester.interface
|
738
785
|
when :stdio
|
739
786
|
run_groonga_stdio(context, &block)
|
@@ -760,7 +807,6 @@ module Grntest
|
|
760
807
|
command_line += [
|
761
808
|
"--input-fd", input_fd.to_s,
|
762
809
|
"--output-fd", output_fd.to_s,
|
763
|
-
"-n",
|
764
810
|
context.relative_db_path.to_s,
|
765
811
|
]
|
766
812
|
pid = Process.spawn(env, *command_line, spawn_options)
|
@@ -890,7 +936,6 @@ EOC
|
|
890
936
|
"--port", port.to_s,
|
891
937
|
"--protocol", "http",
|
892
938
|
"-s",
|
893
|
-
"-n",
|
894
939
|
context.relative_db_path.to_s,
|
895
940
|
]
|
896
941
|
when "groonga-httpd"
|
@@ -907,7 +952,6 @@ EOC
|
|
907
952
|
end
|
908
953
|
|
909
954
|
def create_config_file(context, host, port, pid_file_path)
|
910
|
-
create_empty_database(context.db_path.to_s)
|
911
955
|
config_file_path =
|
912
956
|
context.temporary_directory_path + "groonga-httpd.conf"
|
913
957
|
config_file_path.open("w") do |config_file|
|
@@ -950,9 +994,9 @@ EOF
|
|
950
994
|
output_fd.close(true)
|
951
995
|
end
|
952
996
|
|
953
|
-
def
|
997
|
+
def normalize_actual_result(result)
|
954
998
|
normalized_result = ""
|
955
|
-
result.each do |tag, content, options|
|
999
|
+
result.actual.each do |tag, content, options|
|
956
1000
|
case tag
|
957
1001
|
when :input
|
958
1002
|
normalized_result << content
|
@@ -960,9 +1004,11 @@ EOF
|
|
960
1004
|
normalized_result << normalize_output(content, options)
|
961
1005
|
when :error
|
962
1006
|
normalized_result << normalize_raw_content(content)
|
1007
|
+
when :n_leaked_objects
|
1008
|
+
result.n_leaked_objects = content
|
963
1009
|
end
|
964
1010
|
end
|
965
|
-
normalized_result
|
1011
|
+
result.actual = normalized_result
|
966
1012
|
end
|
967
1013
|
|
968
1014
|
def normalize_raw_content(content)
|
@@ -1069,6 +1115,17 @@ EOF
|
|
1069
1115
|
result_file.print(actual_result)
|
1070
1116
|
end
|
1071
1117
|
end
|
1118
|
+
|
1119
|
+
def check_memory_leak(context)
|
1120
|
+
context.log.each_line do |line|
|
1121
|
+
timestamp, log_level, message = line.split(/\|\s*/, 3)
|
1122
|
+
_ = timestamp # suppress warning
|
1123
|
+
next unless /^grn_fin \((\d+)\)$/ =~ message
|
1124
|
+
n_leaked_objects = $1.to_i
|
1125
|
+
next if n_leaked_objects.zero?
|
1126
|
+
context.result << [:n_leaked_objects, n_leaked_objects, {}]
|
1127
|
+
end
|
1128
|
+
end
|
1072
1129
|
end
|
1073
1130
|
|
1074
1131
|
class Executor
|
@@ -1181,17 +1238,64 @@ EOF
|
|
1181
1238
|
|
1182
1239
|
def execute_line(line)
|
1183
1240
|
case line
|
1241
|
+
when /\A\#@/
|
1242
|
+
directive_content = $POSTMATCH
|
1243
|
+
execute_directive(line, directive_content)
|
1184
1244
|
when /\A\s*\z/
|
1185
1245
|
# do nothing
|
1186
1246
|
when /\A\s*\#/
|
1187
|
-
|
1188
|
-
execute_comment(comment_content)
|
1247
|
+
# ignore comment
|
1189
1248
|
else
|
1190
1249
|
execute_command_line(line)
|
1191
1250
|
end
|
1192
1251
|
end
|
1193
1252
|
|
1194
|
-
def
|
1253
|
+
def resolve_path(path)
|
1254
|
+
if path.relative?
|
1255
|
+
@context.base_directory + path
|
1256
|
+
else
|
1257
|
+
path
|
1258
|
+
end
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
def execute_directive_suggest_create_dataset(line, content, options)
|
1262
|
+
dataset_name = options.first
|
1263
|
+
if dataset_name.nil?
|
1264
|
+
log_input(line)
|
1265
|
+
log_error("#|e| [suggest-create-dataset] dataset name is missing")
|
1266
|
+
return
|
1267
|
+
end
|
1268
|
+
execute_suggest_create_dataset(dataset_name)
|
1269
|
+
end
|
1270
|
+
|
1271
|
+
def execute_directive_include(line, content, options)
|
1272
|
+
path = options.first
|
1273
|
+
if path.nil?
|
1274
|
+
log_input(line)
|
1275
|
+
log_error("#|e| [include] path is missing")
|
1276
|
+
return
|
1277
|
+
end
|
1278
|
+
execute_script(Pathname(path))
|
1279
|
+
end
|
1280
|
+
|
1281
|
+
def execute_directive_copy_path(line, content, options)
|
1282
|
+
source, destination, = options
|
1283
|
+
if source.nil? or destination.nil?
|
1284
|
+
log_input(line)
|
1285
|
+
if source.nil?
|
1286
|
+
log_error("#|e| [copy-path] source is missing")
|
1287
|
+
end
|
1288
|
+
if destiantion.nil?
|
1289
|
+
log_error("#|e| [copy-path] destination is missing")
|
1290
|
+
end
|
1291
|
+
return
|
1292
|
+
end
|
1293
|
+
source = resolve_path(Pathname(source))
|
1294
|
+
destination = resolve_path(Pathname(destination))
|
1295
|
+
FileUtils.cp_r(source.to_s, destination.to_s)
|
1296
|
+
end
|
1297
|
+
|
1298
|
+
def execute_directive(line, content)
|
1195
1299
|
command, *options = Shellwords.split(content)
|
1196
1300
|
case command
|
1197
1301
|
when "disable-logging"
|
@@ -1199,13 +1303,14 @@ EOF
|
|
1199
1303
|
when "enable-logging"
|
1200
1304
|
@context.logging = true
|
1201
1305
|
when "suggest-create-dataset"
|
1202
|
-
|
1203
|
-
return if dataset_name.nil?
|
1204
|
-
execute_suggest_create_dataset(dataset_name)
|
1306
|
+
execute_directive_suggest_create_dataset(line, content, options)
|
1205
1307
|
when "include"
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1308
|
+
execute_directive_include(line, content, options)
|
1309
|
+
when "copy-path"
|
1310
|
+
execute_directive_copy_path(line, content, options)
|
1311
|
+
else
|
1312
|
+
log_input(line)
|
1313
|
+
log_error("#|e| unknown directive: <#{command}>")
|
1209
1314
|
end
|
1210
1315
|
end
|
1211
1316
|
|
@@ -1227,10 +1332,7 @@ EOF
|
|
1227
1332
|
|
1228
1333
|
def execute_script(script_path)
|
1229
1334
|
executor = create_sub_executor(@context)
|
1230
|
-
|
1231
|
-
script_path = @context.base_directory + script_path
|
1232
|
-
end
|
1233
|
-
executor.execute(script_path)
|
1335
|
+
executor.execute(resolve_path(script_path))
|
1234
1336
|
end
|
1235
1337
|
|
1236
1338
|
def execute_command_line(command_line)
|
@@ -1513,6 +1615,7 @@ EOF
|
|
1513
1615
|
end
|
1514
1616
|
|
1515
1617
|
def report_summary(result)
|
1618
|
+
puts(statistics_header)
|
1516
1619
|
puts(colorize(statistics(result), result))
|
1517
1620
|
pass_ratio = result.pass_ratio
|
1518
1621
|
elapsed_time = result.elapsed_time
|
@@ -1520,14 +1623,28 @@ EOF
|
|
1520
1623
|
puts(colorize(summary, result))
|
1521
1624
|
end
|
1522
1625
|
|
1626
|
+
def statistics_header
|
1627
|
+
items = [
|
1628
|
+
"tests/sec",
|
1629
|
+
"tests",
|
1630
|
+
"passes",
|
1631
|
+
"failures",
|
1632
|
+
"leaked",
|
1633
|
+
"!checked",
|
1634
|
+
]
|
1635
|
+
" " + ((["%-9s"] * items.size).join(" | ") % items) + " |"
|
1636
|
+
end
|
1637
|
+
|
1523
1638
|
def statistics(result)
|
1524
1639
|
items = [
|
1525
|
-
"
|
1526
|
-
"
|
1527
|
-
"
|
1528
|
-
"
|
1640
|
+
"%9.2f" % throughput(result),
|
1641
|
+
"%9d" % result.n_tests,
|
1642
|
+
"%9d" % result.n_passed_tests,
|
1643
|
+
"%9d" % result.n_failed_tests,
|
1644
|
+
"%9d" % result.n_leaked_tests,
|
1645
|
+
"%9d" % result.n_not_checked_tests,
|
1529
1646
|
]
|
1530
|
-
"
|
1647
|
+
" " + items.join(" | ") + " |"
|
1531
1648
|
end
|
1532
1649
|
|
1533
1650
|
def throughput(result)
|
@@ -1536,7 +1653,7 @@ EOF
|
|
1536
1653
|
else
|
1537
1654
|
tests_per_second = result.n_tests / result.elapsed_time
|
1538
1655
|
end
|
1539
|
-
|
1656
|
+
tests_per_second
|
1540
1657
|
end
|
1541
1658
|
|
1542
1659
|
def report_failure(result)
|
@@ -1559,8 +1676,8 @@ EOF
|
|
1559
1676
|
create_temporary_file("expected", expected) do |expected_file|
|
1560
1677
|
create_temporary_file("actual", actual) do |actual_file|
|
1561
1678
|
diff_options = @tester.diff_options.dup
|
1562
|
-
diff_options.concat(["--label", "(
|
1563
|
-
"--label", "(
|
1679
|
+
diff_options.concat(["--label", "(expected)", expected_file.path,
|
1680
|
+
"--label", "(actual)", actual_file.path])
|
1564
1681
|
system(@tester.diff, *diff_options)
|
1565
1682
|
end
|
1566
1683
|
end
|
@@ -1669,6 +1786,8 @@ EOF
|
|
1669
1786
|
else
|
1670
1787
|
if result.n_failed_tests > 0
|
1671
1788
|
:failure
|
1789
|
+
elsif result.n_leaked_tests > 0
|
1790
|
+
:leaked
|
1672
1791
|
elsif result.n_not_checked_tests > 0
|
1673
1792
|
:not_checked
|
1674
1793
|
else
|
@@ -1689,6 +1808,8 @@ EOF
|
|
1689
1808
|
"%s%s%s" % [success_color, message, reset_color]
|
1690
1809
|
when :failure
|
1691
1810
|
"%s%s%s" % [failure_color, message, reset_color]
|
1811
|
+
when :leaked
|
1812
|
+
"%s%s%s" % [leaked_color, message, reset_color]
|
1692
1813
|
when :not_checked
|
1693
1814
|
"%s%s%s" % [not_checked_color, message, reset_color]
|
1694
1815
|
else
|
@@ -1722,6 +1843,19 @@ EOF
|
|
1722
1843
|
})
|
1723
1844
|
end
|
1724
1845
|
|
1846
|
+
def leaked_color
|
1847
|
+
escape_sequence({
|
1848
|
+
:color => :magenta,
|
1849
|
+
:color_256 => [3, 0, 3],
|
1850
|
+
:background => true,
|
1851
|
+
},
|
1852
|
+
{
|
1853
|
+
:color => :white,
|
1854
|
+
:color_256 => [5, 5, 5],
|
1855
|
+
:bold => true,
|
1856
|
+
})
|
1857
|
+
end
|
1858
|
+
|
1725
1859
|
def not_checked_color
|
1726
1860
|
escape_sequence({
|
1727
1861
|
:color => :cyan,
|
@@ -1823,7 +1957,13 @@ EOF
|
|
1823
1957
|
end
|
1824
1958
|
end
|
1825
1959
|
|
1826
|
-
def
|
1960
|
+
def leaked_test(worker, result)
|
1961
|
+
synchronize do
|
1962
|
+
report_test_result_mark("L(#{result.n_leaked_objects})", result)
|
1963
|
+
end
|
1964
|
+
end
|
1965
|
+
|
1966
|
+
def not_checked_test(worker, result)
|
1827
1967
|
synchronize do
|
1828
1968
|
report_test_result_mark("N", result)
|
1829
1969
|
puts
|
@@ -1849,6 +1989,9 @@ EOF
|
|
1849
1989
|
|
1850
1990
|
private
|
1851
1991
|
def report_test_result_mark(mark, result)
|
1992
|
+
if @term_width < @current_column + mark.bytesize
|
1993
|
+
puts
|
1994
|
+
end
|
1852
1995
|
print(colorize(mark, result))
|
1853
1996
|
if @term_width <= @current_column
|
1854
1997
|
puts
|
@@ -1892,7 +2035,11 @@ EOF
|
|
1892
2035
|
report_failure(result)
|
1893
2036
|
end
|
1894
2037
|
|
1895
|
-
def
|
2038
|
+
def leaked_test(worker, result)
|
2039
|
+
report_test_result(result, worker.status)
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
def not_checked_test(worker, result)
|
1896
2043
|
report_test_result(result, worker.status)
|
1897
2044
|
report_actual(result)
|
1898
2045
|
end
|
@@ -1945,7 +2092,14 @@ EOF
|
|
1945
2092
|
end
|
1946
2093
|
end
|
1947
2094
|
|
1948
|
-
def
|
2095
|
+
def leaked_test(worker, result)
|
2096
|
+
redraw do
|
2097
|
+
report_test(worker, result)
|
2098
|
+
report_marker(result)
|
2099
|
+
end
|
2100
|
+
end
|
2101
|
+
|
2102
|
+
def not_checked_test(worker, result)
|
1949
2103
|
redraw do
|
1950
2104
|
report_test(worker, result)
|
1951
2105
|
report_actual(result)
|
@@ -1972,6 +2126,7 @@ EOF
|
|
1972
2126
|
|
1973
2127
|
private
|
1974
2128
|
def draw
|
2129
|
+
draw_statistics_header_line
|
1975
2130
|
@test_suites_result.workers.each do |worker|
|
1976
2131
|
draw_status_line(worker)
|
1977
2132
|
draw_test_line(worker)
|
@@ -1979,6 +2134,10 @@ EOF
|
|
1979
2134
|
draw_progress_line
|
1980
2135
|
end
|
1981
2136
|
|
2137
|
+
def draw_statistics_header_line
|
2138
|
+
puts(statistics_header)
|
2139
|
+
end
|
2140
|
+
|
1982
2141
|
def draw_status_line(worker)
|
1983
2142
|
clear_line
|
1984
2143
|
left = "[#{colorize(worker.id, worker.result)}] "
|
@@ -1994,7 +2153,7 @@ EOF
|
|
1994
2153
|
if worker.test_name
|
1995
2154
|
label = " #{worker.test_name}"
|
1996
2155
|
else
|
1997
|
-
label =
|
2156
|
+
label = statistics(worker.result)
|
1998
2157
|
end
|
1999
2158
|
puts(justify(label, @term_width))
|
2000
2159
|
end
|
@@ -2002,7 +2161,11 @@ EOF
|
|
2002
2161
|
def draw_progress_line
|
2003
2162
|
n_done_tests = @test_suites_result.n_tests
|
2004
2163
|
n_total_tests = @test_suites_result.n_total_tests
|
2005
|
-
|
2164
|
+
if n_total_tests.zero?
|
2165
|
+
finished_test_ratio = 0.0
|
2166
|
+
else
|
2167
|
+
finished_test_ratio = n_done_tests.to_f / n_total_tests
|
2168
|
+
end
|
2006
2169
|
|
2007
2170
|
start_mark = "|"
|
2008
2171
|
finish_mark = "|"
|
@@ -2054,7 +2217,11 @@ EOF
|
|
2054
2217
|
end
|
2055
2218
|
|
2056
2219
|
def n_using_lines
|
2057
|
-
n_worker_lines * n_workers + n_progress_lines
|
2220
|
+
n_statistics_header_line + n_worker_lines * n_workers + n_progress_lines
|
2221
|
+
end
|
2222
|
+
|
2223
|
+
def n_statistics_header_line
|
2224
|
+
1
|
2058
2225
|
end
|
2059
2226
|
|
2060
2227
|
def n_worker_lines
|
data/lib/grntest/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grntest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-10-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|