groonga 0.0.6 → 0.0.7
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/AUTHORS +4 -0
- data/NEWS.ja.rdoc +10 -0
- data/NEWS.rdoc +10 -0
- data/README.ja.rdoc +9 -3
- data/README.rdoc +10 -4
- data/Rakefile +1 -1
- data/TUTORIAL.ja.rdoc +3 -6
- data/example/bookmark.rb +1 -1
- data/example/search/config.ru +52 -28
- data/ext/rb-grn-column.c +24 -18
- data/ext/rb-grn-context.c +165 -17
- data/ext/rb-grn-encoding.c +37 -0
- data/ext/rb-grn-expression.c +286 -51
- data/ext/rb-grn-object.c +27 -8
- data/ext/rb-grn-operation.c +128 -22
- data/ext/rb-grn-patricia-trie.c +62 -0
- data/ext/rb-grn-snippet.c +7 -17
- data/ext/rb-grn-table.c +101 -31
- data/ext/rb-grn-utils.c +87 -22
- data/ext/rb-grn-variable-size-column.c +1 -1
- data/ext/rb-grn.h +27 -4
- data/ext/rb-groonga.c +12 -2
- data/extconf.rb +2 -1
- data/html/index.html +2 -2
- data/lib/groonga.rb +1 -0
- data/lib/groonga/expression-builder.rb +47 -12
- data/lib/groonga/patricia-trie.rb +40 -0
- data/lib/groonga/record.rb +17 -13
- data/misc/grnop2ruby.rb +49 -0
- data/pkg-config.rb +1 -1
- data/test-unit/lib/test/unit/assertions.rb +5 -2
- data/test-unit/lib/test/unit/autorunner.rb +19 -4
- data/test-unit/lib/test/unit/collector/load.rb +3 -1
- data/test-unit/lib/test/unit/color-scheme.rb +5 -1
- data/test-unit/lib/test/unit/error.rb +7 -5
- data/test-unit/lib/test/unit/runner/tap.rb +8 -0
- data/test-unit/lib/test/unit/ui/console/testrunner.rb +63 -8
- data/test-unit/lib/test/unit/ui/tap/testrunner.rb +92 -0
- data/test-unit/test/collector/test-load.rb +1 -5
- data/test-unit/test/test-color-scheme.rb +4 -0
- data/test/groonga-test-utils.rb +10 -0
- data/test/run-test.rb +5 -1
- data/test/test-column.rb +58 -0
- data/test/test-database.rb +8 -1
- data/test/test-expression.rb +48 -6
- data/test/test-hash.rb +7 -0
- data/test/test-patricia-trie.rb +39 -0
- data/test/test-record.rb +2 -2
- data/test/test-remote.rb +52 -0
- data/test/test-schema.rb +1 -1
- data/test/test-table-select-normalize.rb +48 -0
- data/test/test-table-select.rb +101 -0
- data/test/test-table.rb +0 -9
- data/test/test-variable-size-column.rb +28 -0
- metadata +16 -5
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009 Kouhei Sutou <kou@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 version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
module Groonga
|
19
|
+
class PatriciaTrie
|
20
|
+
def tag_keys(text)
|
21
|
+
position = 0
|
22
|
+
result = ''
|
23
|
+
if text.respond_to?(:encoding)
|
24
|
+
encoding = text.encoding
|
25
|
+
bytes = text.dup.force_encoding("ascii-8bit")
|
26
|
+
else
|
27
|
+
encoding = nil
|
28
|
+
bytes = text
|
29
|
+
end
|
30
|
+
scan(text) do |record, word, start, length|
|
31
|
+
previous_text = bytes[position...start]
|
32
|
+
previous_text.force_encoding(encoding) if encoding
|
33
|
+
result << previous_text
|
34
|
+
result << yield(record, word)
|
35
|
+
position = start + length
|
36
|
+
end
|
37
|
+
result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/groonga/record.rb
CHANGED
@@ -34,27 +34,33 @@ module Groonga
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def [](column_name)
|
37
|
-
column(column_name
|
37
|
+
column(column_name)[@id]
|
38
38
|
end
|
39
39
|
|
40
40
|
def []=(column_name, value)
|
41
|
-
column(column_name
|
41
|
+
column(column_name)[@id] = value
|
42
42
|
end
|
43
43
|
|
44
44
|
def append(column_name, value)
|
45
|
-
column(column_name
|
45
|
+
column(column_name).append(@id, value)
|
46
|
+
end
|
47
|
+
|
48
|
+
def prepend(column_name, value)
|
49
|
+
column(column_name).prepend(@id, value)
|
46
50
|
end
|
47
51
|
|
48
52
|
def have_column?(name)
|
49
|
-
|
53
|
+
column(name).is_a?(Groonga::Column)
|
54
|
+
rescue Groonga::InvalidArgument
|
55
|
+
false
|
50
56
|
end
|
51
57
|
|
52
58
|
def reference_column?(name)
|
53
|
-
column(name
|
59
|
+
column(name).range.is_a?(Groonga::Table)
|
54
60
|
end
|
55
61
|
|
56
62
|
def search(name, query, options={})
|
57
|
-
column(name
|
63
|
+
column(name).search(query, options)
|
58
64
|
end
|
59
65
|
|
60
66
|
def key
|
@@ -74,11 +80,11 @@ module Groonga
|
|
74
80
|
end
|
75
81
|
|
76
82
|
def increment!(name, delta=nil)
|
77
|
-
column(name
|
83
|
+
column(name).increment!(@id, delta)
|
78
84
|
end
|
79
85
|
|
80
86
|
def decrement!(name, delta=nil)
|
81
|
-
column(name
|
87
|
+
column(name).decrement!(@id, delta)
|
82
88
|
end
|
83
89
|
|
84
90
|
def columns
|
@@ -90,7 +96,7 @@ module Groonga
|
|
90
96
|
table_name = @table.name
|
91
97
|
columns.each do |column|
|
92
98
|
next if column.is_a?(Groonga::IndexColumn)
|
93
|
-
attributes[column.
|
99
|
+
attributes[column.local_name] = column[@id]
|
94
100
|
end
|
95
101
|
attributes
|
96
102
|
end
|
@@ -116,11 +122,9 @@ module Groonga
|
|
116
122
|
end
|
117
123
|
|
118
124
|
private
|
119
|
-
def column(name
|
125
|
+
def column(name)
|
120
126
|
_column = @table.column(name.to_s)
|
121
|
-
if _column.nil?
|
122
|
-
raise Groonga::Error, "nonexistent column: <#{name.inspect}>"
|
123
|
-
end
|
127
|
+
raise InvalidArgument, "column(#{name.inspect}) is nil" if _column.nil?
|
124
128
|
_column
|
125
129
|
end
|
126
130
|
end
|
data/misc/grnop2ruby.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009 Yuto Hayamizu <y.hayamizu@gmail.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 version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
#
|
19
|
+
# This script expects "groonga.h" as a first argument, extracts the
|
20
|
+
# 'grn_operator', and write 'rb_define_const's of 'grn_operator' to
|
21
|
+
# standard outout.
|
22
|
+
#
|
23
|
+
# Usage:
|
24
|
+
# ruby grnop2ruby.rb /path/to/groonga.h
|
25
|
+
#
|
26
|
+
|
27
|
+
replace_dictionary = {
|
28
|
+
"VAR" => "VARIABLE",
|
29
|
+
"EXPR" => "EXPRESSION",
|
30
|
+
"NOP" => "NO_OPERATION",
|
31
|
+
"REF" => "REFERENCE",
|
32
|
+
"OBJ" => "OBJECT",
|
33
|
+
"INCR" => "INCREMENT",
|
34
|
+
"DECR" => "DECREMENT",
|
35
|
+
"MOD" => "MODULO",
|
36
|
+
"LCP" => "LONGEST_COMMON_PREFIX",
|
37
|
+
}
|
38
|
+
|
39
|
+
ARGF.each_line do |line|
|
40
|
+
case line
|
41
|
+
when /\A\s+(GRN_OP_\w+)/
|
42
|
+
operator = $1
|
43
|
+
rb_operator = operator.gsub(/\AGRN_OP_/, "").split("_").map{ |word|
|
44
|
+
replace_dictionary[word] || word
|
45
|
+
}.join("_")
|
46
|
+
puts " rb_define_const(rb_mGrnOperation, \"%s\",
|
47
|
+
UINT2NUM(%s));" % [rb_operator, operator]
|
48
|
+
end
|
49
|
+
end
|
data/pkg-config.rb
CHANGED
@@ -880,7 +880,7 @@ EOT
|
|
880
880
|
MaybeContainer.new(value, &formatter)
|
881
881
|
end
|
882
882
|
|
883
|
-
MAX_DIFF_TARGET_STRING_SIZE =
|
883
|
+
MAX_DIFF_TARGET_STRING_SIZE = 1000
|
884
884
|
def diff_target_string?(string)
|
885
885
|
if string.respond_to?(:bytesize)
|
886
886
|
string.bytesize < MAX_DIFF_TARGET_STRING_SIZE
|
@@ -930,7 +930,10 @@ EOM
|
|
930
930
|
if use_pp
|
931
931
|
begin
|
932
932
|
require 'pp' unless defined?(PP)
|
933
|
-
|
933
|
+
begin
|
934
|
+
return PP.pp(object, '').chomp
|
935
|
+
rescue NameError
|
936
|
+
end
|
934
937
|
rescue LoadError
|
935
938
|
self.use_pp = false
|
936
939
|
end
|
@@ -102,15 +102,23 @@ module Test
|
|
102
102
|
@to_run = []
|
103
103
|
@color_scheme = ColorScheme.default
|
104
104
|
@runner_options = {}
|
105
|
+
@default_arguments = []
|
105
106
|
@workdir = nil
|
106
|
-
|
107
|
-
|
107
|
+
config_file = "test-unit.yml"
|
108
|
+
if File.exist?(config_file)
|
109
|
+
load_config(config_file)
|
110
|
+
else
|
111
|
+
global_config_file = File.expand_path("~/.test-unit.xml")
|
112
|
+
load_config(global_config_file) if File.exist?(global_config_file)
|
113
|
+
end
|
108
114
|
yield(self) if block_given?
|
109
115
|
end
|
110
116
|
|
111
117
|
def process_args(args = ARGV)
|
118
|
+
default_arguments = @default_arguments.dup
|
112
119
|
begin
|
113
|
-
|
120
|
+
@default_arguments.concat(args)
|
121
|
+
options.order!(@default_arguments) {|arg| @to_run << arg}
|
114
122
|
rescue OptionParser::ParseError => e
|
115
123
|
puts e
|
116
124
|
puts options
|
@@ -119,6 +127,8 @@ module Test
|
|
119
127
|
@filters << proc{false} unless(@filters.empty?)
|
120
128
|
end
|
121
129
|
not @to_run.empty?
|
130
|
+
ensure
|
131
|
+
@default_arguments = default_arguments
|
122
132
|
end
|
123
133
|
|
124
134
|
def options
|
@@ -304,7 +314,11 @@ module Test
|
|
304
314
|
(config["#{runner_name}_options"] || {}).each do |key, value|
|
305
315
|
key = key.to_sym
|
306
316
|
value = ColorScheme[value] if key == :color_scheme
|
307
|
-
|
317
|
+
if key == :arguments
|
318
|
+
@default_arguments.concat(value.split)
|
319
|
+
else
|
320
|
+
runner_options[key.to_sym] = value
|
321
|
+
end
|
308
322
|
end
|
309
323
|
@runner_options = @runner_options.merge(runner_options)
|
310
324
|
end
|
@@ -327,3 +341,4 @@ end
|
|
327
341
|
|
328
342
|
require 'test/unit/runner/console'
|
329
343
|
require 'test/unit/runner/emacs'
|
344
|
+
require 'test/unit/runner/tap'
|
@@ -76,7 +76,9 @@ module Test
|
|
76
76
|
sub_test_suites << sub_test_suite unless sub_test_suite.empty?
|
77
77
|
end
|
78
78
|
else
|
79
|
-
|
79
|
+
unless excluded_file?(path.basename.to_s)
|
80
|
+
collect_file(path, sub_test_suites, already_gathered)
|
81
|
+
end
|
80
82
|
end
|
81
83
|
|
82
84
|
test_suite = TestSuite.new(path.basename.to_s)
|
@@ -14,7 +14,11 @@ module Test
|
|
14
14
|
"omission" => Color.new("blue", :bold => true),
|
15
15
|
"notification" => Color.new("cyan", :bold => true),
|
16
16
|
"error" => Color.new("yellow", :bold => true) +
|
17
|
-
Color.new("black", :foreground => false)
|
17
|
+
Color.new("black", :foreground => false),
|
18
|
+
"case" => Color.new("white", :bold => true) +
|
19
|
+
Color.new("blue", :foreground => false),
|
20
|
+
"suite" => Color.new("white", :bold => true) +
|
21
|
+
Color.new("green", :foreground => false))
|
18
22
|
end
|
19
23
|
|
20
24
|
@@schemes = {}
|
@@ -69,18 +69,20 @@ module Test
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
NOT_PASS_THROUGH_EXCEPTIONS = []
|
72
73
|
PASS_THROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
|
73
74
|
SystemExit]
|
74
75
|
private
|
75
76
|
def handle_all_exception(exception)
|
76
77
|
case exception
|
78
|
+
when *NOT_PASS_THROUGH_EXCEPTIONS
|
77
79
|
when *PASS_THROUGH_EXCEPTIONS
|
78
|
-
false
|
79
|
-
else
|
80
|
-
problem_occurred
|
81
|
-
add_error(exception)
|
82
|
-
true
|
80
|
+
return false
|
83
81
|
end
|
82
|
+
|
83
|
+
problem_occurred
|
84
|
+
add_error(exception)
|
85
|
+
true
|
84
86
|
end
|
85
87
|
|
86
88
|
def add_error(exception)
|
@@ -1,7 +1,9 @@
|
|
1
1
|
#--
|
2
2
|
#
|
3
3
|
# Author:: Nathaniel Talbott.
|
4
|
-
# Copyright::
|
4
|
+
# Copyright::
|
5
|
+
# * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
|
6
|
+
# * Copyright (c) 2008-2009 Kouhei Sutou <kou@clear-code.com>
|
5
7
|
# License:: Ruby license.
|
6
8
|
|
7
9
|
require 'test/unit/color-scheme'
|
@@ -36,6 +38,9 @@ module Test
|
|
36
38
|
@progress_row_max = @options[:progress_row_max]
|
37
39
|
@progress_row_max ||= guess_progress_row_max
|
38
40
|
@already_outputted = false
|
41
|
+
@n_successes = 0
|
42
|
+
@indent = 0
|
43
|
+
@top_level = true
|
39
44
|
@faults = []
|
40
45
|
end
|
41
46
|
|
@@ -68,6 +73,8 @@ module Test
|
|
68
73
|
@mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
|
69
74
|
@mediator.add_listener(TestCase::STARTED, &method(:test_started))
|
70
75
|
@mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
|
76
|
+
@mediator.add_listener(TestSuite::STARTED, &method(:test_suite_started))
|
77
|
+
@mediator.add_listener(TestSuite::FINISHED, &method(:test_suite_finished))
|
71
78
|
end
|
72
79
|
|
73
80
|
def start_mediator
|
@@ -91,8 +98,6 @@ module Test
|
|
91
98
|
|
92
99
|
def finished(elapsed_time)
|
93
100
|
nl if output?(NORMAL) and !output?(VERBOSE)
|
94
|
-
nl
|
95
|
-
output("Finished in #{elapsed_time} seconds.")
|
96
101
|
@faults.each_with_index do |fault, index|
|
97
102
|
nl
|
98
103
|
output_single("%3d) " % (index + 1))
|
@@ -101,25 +106,75 @@ module Test
|
|
101
106
|
output(detail)
|
102
107
|
end
|
103
108
|
nl
|
109
|
+
output("Finished in #{elapsed_time} seconds.")
|
110
|
+
nl
|
104
111
|
output(@result, result_color)
|
112
|
+
n_tests = @result.run_count
|
113
|
+
if n_tests.zero?
|
114
|
+
pass_percentage = 0
|
115
|
+
else
|
116
|
+
pass_percentage = 100.0 * (@n_successes / n_tests.to_f)
|
117
|
+
end
|
118
|
+
output("%g%% passed" % pass_percentage, result_color)
|
105
119
|
end
|
106
120
|
|
107
121
|
def format_fault(fault)
|
108
122
|
fault.long_display
|
109
123
|
end
|
110
|
-
|
124
|
+
|
111
125
|
def test_started(name)
|
112
|
-
|
126
|
+
return unless output?(VERBOSE)
|
127
|
+
|
128
|
+
name = name.sub(/\(.+?\)\z/, '')
|
129
|
+
right_space = 8 * 2
|
130
|
+
left_space = @progress_row_max - right_space
|
131
|
+
left_space = left_space - indent.size - name.size
|
132
|
+
tab_stop = "\t" * ((left_space - 1) / 8)
|
133
|
+
output_single("#{indent}#{name}:#{tab_stop}", nil, VERBOSE)
|
134
|
+
@test_start = Time.now
|
113
135
|
end
|
114
|
-
|
136
|
+
|
115
137
|
def test_finished(name)
|
116
138
|
unless @already_outputted
|
139
|
+
@n_successes += 1
|
117
140
|
output_progress(".", color("success"))
|
118
141
|
end
|
119
|
-
nl(VERBOSE)
|
120
142
|
@already_outputted = false
|
143
|
+
|
144
|
+
return unless output?(VERBOSE)
|
145
|
+
|
146
|
+
output(": (%f)" % (Time.now - @test_start), nil, VERBOSE)
|
121
147
|
end
|
122
|
-
|
148
|
+
|
149
|
+
def test_suite_started(name)
|
150
|
+
if @top_level
|
151
|
+
@top_level = false
|
152
|
+
return
|
153
|
+
end
|
154
|
+
|
155
|
+
output_single(indent, nil, VERBOSE)
|
156
|
+
if /\A[A-Z]/ =~ name
|
157
|
+
_color = color("case")
|
158
|
+
else
|
159
|
+
_color = color("suite")
|
160
|
+
end
|
161
|
+
output_single(name, _color, VERBOSE)
|
162
|
+
output(": ", nil, VERBOSE)
|
163
|
+
@indent += 2
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_suite_finished(name)
|
167
|
+
@indent -= 2
|
168
|
+
end
|
169
|
+
|
170
|
+
def indent
|
171
|
+
if output?(VERBOSE)
|
172
|
+
" " * @indent
|
173
|
+
else
|
174
|
+
""
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
123
178
|
def nl(level=NORMAL)
|
124
179
|
output("", nil, level)
|
125
180
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Author:: Kouhei Sutou.
|
4
|
+
# Copyright:: Copyright (c) 2009 Kouhei Sutou <kou@clear-code.com>.
|
5
|
+
# License:: Ruby license.
|
6
|
+
|
7
|
+
require 'test/unit/ui/testrunner'
|
8
|
+
require 'test/unit/ui/testrunnermediator'
|
9
|
+
|
10
|
+
module Test
|
11
|
+
module Unit
|
12
|
+
module UI
|
13
|
+
module Tap
|
14
|
+
|
15
|
+
# Runs a Test::Unit::TestSuite and outputs result
|
16
|
+
# as TAP format.
|
17
|
+
class TestRunner < UI::TestRunner
|
18
|
+
def initialize(suite, options={})
|
19
|
+
super
|
20
|
+
@output = @options[:output] || STDOUT
|
21
|
+
@n_tests = 0
|
22
|
+
@already_outputted = false
|
23
|
+
end
|
24
|
+
|
25
|
+
# Begins the test run.
|
26
|
+
def start
|
27
|
+
setup_mediator
|
28
|
+
result = start_mediator
|
29
|
+
def result.passed?
|
30
|
+
true # for prove commend :<
|
31
|
+
end
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def setup_mediator
|
37
|
+
@mediator = TestRunnerMediator.new(@suite)
|
38
|
+
attach_to_mediator
|
39
|
+
end
|
40
|
+
|
41
|
+
def attach_to_mediator
|
42
|
+
@mediator.add_listener(TestResult::FAULT, &method(:add_fault))
|
43
|
+
@mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
|
44
|
+
@mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
|
45
|
+
@mediator.add_listener(TestCase::STARTED, &method(:test_started))
|
46
|
+
@mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_mediator
|
50
|
+
@mediator.run_suite
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_fault(fault)
|
54
|
+
puts("not ok #{@n_tests} - #{fault.short_display}")
|
55
|
+
fault.long_display.each_line do |line|
|
56
|
+
puts("# #{line}")
|
57
|
+
end
|
58
|
+
@already_outputted = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def started(result)
|
62
|
+
@result = result
|
63
|
+
puts("1..#{@suite.size}")
|
64
|
+
end
|
65
|
+
|
66
|
+
def finished(elapsed_time)
|
67
|
+
puts("# Finished in #{elapsed_time} seconds.")
|
68
|
+
@result.to_s.each_line do |line|
|
69
|
+
puts("# #{line}")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_started(name)
|
74
|
+
@n_tests += 1
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_finished(name)
|
78
|
+
unless @already_outputted
|
79
|
+
puts("ok #{@n_tests} - #{name}")
|
80
|
+
end
|
81
|
+
@already_outputted = false
|
82
|
+
end
|
83
|
+
|
84
|
+
def puts(*args)
|
85
|
+
@output.puts(*args)
|
86
|
+
@output.flush
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|