grntest 1.0.0 → 1.0.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.
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 groonga by writing groonga commands and expected result.
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
- ## Usage
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.1667s [not checked]
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
- 5.96 tests/sec: 1 tests, 0 passes, 0 failures, 1 not checked_tests
59
- 0% passed in 0.1678s.
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
- 6.12 tests/sec: 1 tests, 1 passes, 0 failures, 0 not checked_tests
76
- 100% passed in 0.1635s.
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.1445s [failed]
107
+ select 0.1767s [failed]
107
108
  ================================================================================
108
- --- (actual)
109
- +++ (expected)
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:Bob'
115
- -[[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[2,"Bob"]]]]
116
- +select Users --query '_key:Alice'
117
- +[[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[1,"Alice"]]]]
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
- 6.68 tests/sec: 1 tests, 0 passes, 1 failures, 0 not checked_tests
122
- 0% passed in 0.1497s.
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
- 6.97 tests/sec: 1 tests, 1 passes, 0 failures, 0 not checked_tests
144
- 100% passed in 0.1434s.
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
- ### Advanced usage
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
- See `grntest --help`. It contains many usuful features.
208
+ Here are available `NAME` s:
152
209
 
153
- Some important features are described in this section.
210
+ * `disable-logging`
211
+ * `enable-logging`
212
+ * `suggest-create-dataset`
213
+ * `include`
214
+ * `copy-path`
154
215
 
155
- #### `--n-workers`
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
- 8.60 tests/sec: 4 tests, 4 passes, 0 failures, 0 not checked_tests
435
+ 9.95 | 5 | 5 | 0 | 0 | 0 |
168
436
  [1] [finished]
169
- 9.85 tests/sec: 5 tests, 5 passes, 0 failures, 0 not checked_tests
437
+ 9.22 | 4 | 4 | 0 | 0 | 0 |
170
438
  [2] [finished]
171
- 8.63 tests/sec: 4 tests, 4 passes, 0 failures, 0 not checked_tests
439
+ 9.11 | 4 | 4 | 0 | 0 | 0 |
172
440
  [3] [finished]
173
- 9.68 tests/sec: 5 tests, 5 passes, 0 failures, 0 not checked_tests
441
+ 10.10 | 5 | 5 | 0 | 0 | 0 |
174
442
  |-----------------------------------------------------------------------| [100%]
175
443
 
176
- 34.43 tests/sec: 18 tests, 18 passes, 0 failures, 0 not checked_tests
177
- 100% passed in 0.5228s.
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
- ### Examples
477
+ ## Examples
181
478
 
182
- See [test/function/ directory in groonga's
183
- source](https://github.com/groonga/groonga/tree/master/test/function). It
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
- ### Mailing list
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 patches.)
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!!!
@@ -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.all? do |pattern|
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.all? do |pattern|
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, :n_not_checked_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 not_check_test(result)
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.not_check_test(self, result)
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
- :success
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
- :not_checked
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
- result.actual = normalize_result(result.actual)
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.not_check_test(result)
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
- db_dir = directory_path + "db"
699
- FileUtils.mkdir_p(db_dir.to_s)
700
- db_path = db_dir + "db"
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 normalize_result(result)
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
- comment_content = $POSTMATCH
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 execute_comment(content)
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
- dataset_name = options.first
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
- path = options.first
1207
- return if path.nil?
1208
- execute_script(Pathname(path))
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
- if script_path.relative?
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
- "#{result.n_tests} tests",
1526
- "#{result.n_passed_tests} passes",
1527
- "#{result.n_failed_tests} failures",
1528
- "#{result.n_not_checked_tests} not checked_tests",
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
- "#{throughput(result)}: " + items.join(", ")
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
- "%.2f tests/sec" % tests_per_second
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", "(actual)", actual_file.path,
1563
- "--label", "(expected)", expected_file.path])
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 not_check_test(worker, result)
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 not_check_test(worker, result)
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 not_check_test(worker, result)
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 = " #{statistics(worker.result)}"
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
- finished_test_ratio = n_done_tests.to_f / n_total_tests
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
@@ -14,5 +14,5 @@
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
16
  module Grntest
17
- VERSION = "1.0.0"
17
+ VERSION = "1.0.1"
18
18
  end
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.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-08-29 00:00:00.000000000 Z
13
+ date: 2012-10-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json