groonga 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/AUTHORS +1 -0
  2. data/NEWS.ja.rdoc +5 -0
  3. data/NEWS.rdoc +5 -0
  4. data/README.ja.rdoc +53 -0
  5. data/README.rdoc +54 -0
  6. data/Rakefile +209 -0
  7. data/TUTORIAL.ja.rdoc +160 -0
  8. data/benchmark/small-many-items.rb +175 -0
  9. data/example/bookmark.rb +38 -0
  10. data/ext/.gitignore +2 -0
  11. data/ext/rb-grn-accessor.c +52 -0
  12. data/ext/rb-grn-array-cursor.c +28 -0
  13. data/ext/rb-grn-array.c +168 -0
  14. data/ext/rb-grn-column.c +273 -0
  15. data/ext/rb-grn-context.c +333 -0
  16. data/ext/rb-grn-database.c +128 -0
  17. data/ext/rb-grn-encoding.c +163 -0
  18. data/ext/rb-grn-exception.c +1014 -0
  19. data/ext/rb-grn-hash-cursor.c +30 -0
  20. data/ext/rb-grn-hash.c +40 -0
  21. data/ext/rb-grn-logger.c +277 -0
  22. data/ext/rb-grn-object.c +985 -0
  23. data/ext/rb-grn-patricia-trie-cursor.c +30 -0
  24. data/ext/rb-grn-patricia-trie.c +40 -0
  25. data/ext/rb-grn-procedure.c +52 -0
  26. data/ext/rb-grn-query.c +207 -0
  27. data/ext/rb-grn-record.c +33 -0
  28. data/ext/rb-grn-snippet.c +274 -0
  29. data/ext/rb-grn-table-cursor-key-support.c +55 -0
  30. data/ext/rb-grn-table-cursor.c +294 -0
  31. data/ext/rb-grn-table-key-support.c +299 -0
  32. data/ext/rb-grn-table.c +706 -0
  33. data/ext/rb-grn-type.c +114 -0
  34. data/ext/rb-grn-utils.c +578 -0
  35. data/ext/rb-grn.h +346 -0
  36. data/ext/rb-groonga.c +98 -0
  37. data/extconf.rb +171 -0
  38. data/html/bar.svg +153 -0
  39. data/html/developer.html +121 -0
  40. data/html/developer.svg +469 -0
  41. data/html/download.svg +253 -0
  42. data/html/footer.html.erb +28 -0
  43. data/html/head.html.erb +4 -0
  44. data/html/header.html.erb +17 -0
  45. data/html/index.html +153 -0
  46. data/html/install.svg +636 -0
  47. data/html/logo.xcf +0 -0
  48. data/html/ranguba.css +248 -0
  49. data/html/tutorial.svg +559 -0
  50. data/lib/groonga.rb +50 -0
  51. data/lib/groonga/record.rb +98 -0
  52. data/license/GPL +340 -0
  53. data/license/LGPL +504 -0
  54. data/license/RUBY +59 -0
  55. data/pkg-config.rb +328 -0
  56. data/test-unit/Rakefile +35 -0
  57. data/test-unit/TODO +5 -0
  58. data/test-unit/bin/testrb +5 -0
  59. data/test-unit/html/classic.html +15 -0
  60. data/test-unit/html/index.html +25 -0
  61. data/test-unit/html/index.html.ja +27 -0
  62. data/test-unit/lib/test/unit.rb +342 -0
  63. data/test-unit/lib/test/unit/assertionfailederror.rb +14 -0
  64. data/test-unit/lib/test/unit/assertions.rb +1149 -0
  65. data/test-unit/lib/test/unit/attribute.rb +125 -0
  66. data/test-unit/lib/test/unit/autorunner.rb +306 -0
  67. data/test-unit/lib/test/unit/collector.rb +43 -0
  68. data/test-unit/lib/test/unit/collector/descendant.rb +23 -0
  69. data/test-unit/lib/test/unit/collector/dir.rb +108 -0
  70. data/test-unit/lib/test/unit/collector/load.rb +135 -0
  71. data/test-unit/lib/test/unit/collector/objectspace.rb +34 -0
  72. data/test-unit/lib/test/unit/color-scheme.rb +86 -0
  73. data/test-unit/lib/test/unit/color.rb +96 -0
  74. data/test-unit/lib/test/unit/diff.rb +538 -0
  75. data/test-unit/lib/test/unit/error.rb +124 -0
  76. data/test-unit/lib/test/unit/exceptionhandler.rb +39 -0
  77. data/test-unit/lib/test/unit/failure.rb +110 -0
  78. data/test-unit/lib/test/unit/fixture.rb +176 -0
  79. data/test-unit/lib/test/unit/notification.rb +125 -0
  80. data/test-unit/lib/test/unit/omission.rb +143 -0
  81. data/test-unit/lib/test/unit/pending.rb +146 -0
  82. data/test-unit/lib/test/unit/priority.rb +161 -0
  83. data/test-unit/lib/test/unit/runner/console.rb +52 -0
  84. data/test-unit/lib/test/unit/runner/emacs.rb +8 -0
  85. data/test-unit/lib/test/unit/testcase.rb +360 -0
  86. data/test-unit/lib/test/unit/testresult.rb +89 -0
  87. data/test-unit/lib/test/unit/testsuite.rb +110 -0
  88. data/test-unit/lib/test/unit/ui/console/outputlevel.rb +14 -0
  89. data/test-unit/lib/test/unit/ui/console/testrunner.rb +220 -0
  90. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +49 -0
  91. data/test-unit/lib/test/unit/ui/testrunner.rb +20 -0
  92. data/test-unit/lib/test/unit/ui/testrunnermediator.rb +77 -0
  93. data/test-unit/lib/test/unit/ui/testrunnerutilities.rb +41 -0
  94. data/test-unit/lib/test/unit/util/backtracefilter.rb +41 -0
  95. data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
  96. data/test-unit/lib/test/unit/util/observable.rb +90 -0
  97. data/test-unit/lib/test/unit/util/procwrapper.rb +48 -0
  98. data/test-unit/lib/test/unit/version.rb +7 -0
  99. data/test-unit/sample/adder.rb +13 -0
  100. data/test-unit/sample/subtracter.rb +12 -0
  101. data/test-unit/sample/tc_adder.rb +18 -0
  102. data/test-unit/sample/tc_subtracter.rb +18 -0
  103. data/test-unit/sample/test_user.rb +22 -0
  104. data/test-unit/sample/ts_examples.rb +7 -0
  105. data/test-unit/test/collector/test-descendant.rb +135 -0
  106. data/test-unit/test/collector/test-load.rb +333 -0
  107. data/test-unit/test/collector/test_dir.rb +406 -0
  108. data/test-unit/test/collector/test_objectspace.rb +98 -0
  109. data/test-unit/test/run-test.rb +13 -0
  110. data/test-unit/test/test-attribute.rb +86 -0
  111. data/test-unit/test/test-color-scheme.rb +56 -0
  112. data/test-unit/test/test-color.rb +47 -0
  113. data/test-unit/test/test-diff.rb +477 -0
  114. data/test-unit/test/test-emacs-runner.rb +60 -0
  115. data/test-unit/test/test-fixture.rb +287 -0
  116. data/test-unit/test/test-notification.rb +33 -0
  117. data/test-unit/test/test-omission.rb +81 -0
  118. data/test-unit/test/test-pending.rb +70 -0
  119. data/test-unit/test/test-priority.rb +119 -0
  120. data/test-unit/test/test_assertions.rb +1082 -0
  121. data/test-unit/test/test_error.rb +26 -0
  122. data/test-unit/test/test_failure.rb +33 -0
  123. data/test-unit/test/test_testcase.rb +478 -0
  124. data/test-unit/test/test_testresult.rb +113 -0
  125. data/test-unit/test/test_testsuite.rb +129 -0
  126. data/test-unit/test/testunit-test-util.rb +14 -0
  127. data/test-unit/test/ui/test_testrunmediator.rb +20 -0
  128. data/test-unit/test/util/test-method-owner-finder.rb +38 -0
  129. data/test-unit/test/util/test_backtracefilter.rb +41 -0
  130. data/test-unit/test/util/test_observable.rb +102 -0
  131. data/test-unit/test/util/test_procwrapper.rb +36 -0
  132. data/test/.gitignore +1 -0
  133. data/test/groonga-test-utils.rb +90 -0
  134. data/test/run-test.rb +54 -0
  135. data/test/test-column.rb +190 -0
  136. data/test/test-context.rb +90 -0
  137. data/test/test-database.rb +62 -0
  138. data/test/test-encoding.rb +33 -0
  139. data/test/test-exception.rb +85 -0
  140. data/test/test-procedure.rb +35 -0
  141. data/test/test-query.rb +22 -0
  142. data/test/test-record.rb +188 -0
  143. data/test/test-snippet.rb +121 -0
  144. data/test/test-table-cursor.rb +51 -0
  145. data/test/test-table.rb +447 -0
  146. data/test/test-type.rb +52 -0
  147. data/test/test-version.rb +31 -0
  148. metadata +213 -0
@@ -0,0 +1,125 @@
1
+ module Test
2
+ module Unit
3
+ module Attribute
4
+ class << self
5
+ def included(base)
6
+ base.extend(BaseClassMethods)
7
+ base.extend(ClassMethods)
8
+ end
9
+ end
10
+
11
+ module BaseClassMethods
12
+ def attributes_table
13
+ {}
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ def method_added(name)
19
+ super
20
+ return unless defined?(@current_attributes)
21
+
22
+ attributes = {}
23
+ kept_attributes = {}
24
+ @current_attributes.each do |attribute_name, attribute|
25
+ attributes[attribute_name] = attribute[:value]
26
+ kept_attributes[attribute_name] = attribute if attribute[:keep]
27
+ end
28
+ set_attributes(name, attributes)
29
+ @current_attributes = kept_attributes
30
+ end
31
+
32
+ def attribute(name, value, options={}, *method_names)
33
+ unless options.is_a?(Hash)
34
+ method_names << options
35
+ options = {}
36
+ end
37
+ @current_attributes ||= {}
38
+ if method_names.empty?
39
+ @current_attributes[name] = options.merge(:value => value)
40
+ else
41
+ method_names.each do |method_name|
42
+ set_attributes(method_name, {name => value})
43
+ end
44
+ end
45
+ end
46
+
47
+ def attributes_table
48
+ @attributes_table ||= {}
49
+ super.merge(@attributes_table)
50
+ end
51
+
52
+ def set_attributes(method_name, new_attributes)
53
+ return if new_attributes.empty?
54
+ method_name = normalize_method_name(method_name)
55
+ @attributes_table ||= {}
56
+ @attributes_table[method_name] ||= {}
57
+ current_attributes = @attributes_table[method_name]
58
+ new_attributes.each do |key, value|
59
+ key = normalize_attribute_name(key)
60
+ observers = attribute_observers(key) || []
61
+ observers.each do |observer|
62
+ observer.call(self,
63
+ key,
64
+ (attributes(method_name) || {})[key],
65
+ value,
66
+ method_name)
67
+ end
68
+ current_attributes[key] = value
69
+ end
70
+ end
71
+
72
+ def attributes(method_name)
73
+ method_name = normalize_method_name(method_name)
74
+ attributes = attributes_table[method_name]
75
+ ancestors[1..-1].each do |ancestor|
76
+ if ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute
77
+ parent_attributes = ancestor.attributes(method_name)
78
+ if attributes
79
+ attributes = (parent_attributes || {}).merge(attributes)
80
+ else
81
+ attributes = parent_attributes
82
+ end
83
+ break
84
+ end
85
+ end
86
+ attributes
87
+ end
88
+
89
+ def get_attribute(method_name, attribute_name)
90
+ attribute_name = normalize_attribute_name(attribute_name)
91
+ (attributes(method_name) || {})[attribute_name]
92
+ end
93
+
94
+ @@attribute_observers = {}
95
+ def register_attribute_observer(attribute_name, observer=Proc.new)
96
+ attribute_name = normalize_attribute_name(attribute_name)
97
+ @@attribute_observers[attribute_name] ||= []
98
+ @@attribute_observers[attribute_name] << observer
99
+ end
100
+
101
+ def attribute_observers(attribute_name)
102
+ attribute_name = normalize_attribute_name(attribute_name)
103
+ @@attribute_observers[attribute_name]
104
+ end
105
+
106
+ private
107
+ def normalize_attribute_name(name)
108
+ name.to_s
109
+ end
110
+
111
+ def normalize_method_name(name)
112
+ name.to_s
113
+ end
114
+ end
115
+
116
+ def attributes
117
+ self.class.attributes(@method_name) || {}
118
+ end
119
+
120
+ def [](name)
121
+ self.class.get_attribute(@method_name, name)
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,306 @@
1
+ require 'test/unit/color-scheme'
2
+ require 'optparse'
3
+
4
+ module Test
5
+ module Unit
6
+ class AutoRunner
7
+ RUNNERS = {}
8
+ COLLECTORS = {}
9
+ ADDITIONAL_OPTIONS = []
10
+
11
+ class << self
12
+ def register_runner(id, runner_builder=Proc.new)
13
+ RUNNERS[id] = runner_builder
14
+ RUNNERS[id.to_s] = runner_builder
15
+ end
16
+
17
+ def runner(id)
18
+ RUNNERS[id.to_s]
19
+ end
20
+
21
+ def register_collector(id, collector_builder=Proc.new)
22
+ COLLECTORS[id] = collector_builder
23
+ COLLECTORS[id.to_s] = collector_builder
24
+ end
25
+
26
+ def collector(id)
27
+ COLLECTORS[id.to_s]
28
+ end
29
+
30
+ def register_color_scheme(id, scheme)
31
+ ColorScheme[id] = scheme
32
+ end
33
+
34
+ def setup_option(option_builder=Proc.new)
35
+ ADDITIONAL_OPTIONS << option_builder
36
+ end
37
+ end
38
+
39
+ def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
40
+ r = new(force_standalone || standalone?, &block)
41
+ r.base = default_dir
42
+ r.process_args(argv)
43
+ r.run
44
+ end
45
+
46
+ def self.standalone?
47
+ return false unless("-e" == $0)
48
+ ObjectSpace.each_object(Class) do |klass|
49
+ return false if(klass < TestCase)
50
+ end
51
+ true
52
+ end
53
+
54
+ register_collector(:descendant) do |auto_runner|
55
+ require 'test/unit/collector/descendant'
56
+ collector = Collector::Descendant.new
57
+ collector.filter = auto_runner.filters
58
+ collector.collect($0.sub(/\.rb\Z/, ''))
59
+ end
60
+
61
+ register_collector(:load) do |auto_runner|
62
+ require 'test/unit/collector/load'
63
+ collector = Collector::Load.new
64
+ collector.patterns.concat(auto_runner.pattern) if auto_runner.pattern
65
+ collector.excludes.concat(auto_runner.exclude) if auto_runner.exclude
66
+ collector.base = auto_runner.base
67
+ collector.filter = auto_runner.filters
68
+ collector.collect(*auto_runner.to_run)
69
+ end
70
+
71
+ # deprecated
72
+ register_collector(:object_space) do |auto_runner|
73
+ require 'test/unit/collector/objectspace'
74
+ c = Collector::ObjectSpace.new
75
+ c.filter = auto_runner.filters
76
+ c.collect($0.sub(/\.rb\Z/, ''))
77
+ end
78
+
79
+ # deprecated
80
+ register_collector(:dir) do |auto_runner|
81
+ require 'test/unit/collector/dir'
82
+ c = Collector::Dir.new
83
+ c.filter = auto_runner.filters
84
+ c.pattern.concat(auto_runner.pattern) if auto_runner.pattern
85
+ c.exclude.concat(auto_runner.exclude) if auto_runner.exclude
86
+ c.base = auto_runner.base
87
+ $:.push(auto_runner.base) if auto_runner.base
88
+ c.collect(*(auto_runner.to_run.empty? ? ['.'] : auto_runner.to_run))
89
+ end
90
+
91
+ attr_reader :suite, :runner_options
92
+ attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
93
+ attr_accessor :color_scheme
94
+ attr_writer :runner, :collector
95
+
96
+ def initialize(standalone)
97
+ Unit.run = true
98
+ @standalone = standalone
99
+ @runner = default_runner
100
+ @collector = default_collector
101
+ @filters = []
102
+ @to_run = []
103
+ @color_scheme = ColorScheme.default
104
+ @runner_options = {}
105
+ @workdir = nil
106
+ default_config_file = "test-unit.yml"
107
+ load_config(default_config_file) if File.exist?(default_config_file)
108
+ yield(self) if block_given?
109
+ end
110
+
111
+ def process_args(args = ARGV)
112
+ begin
113
+ options.order!(args) {|arg| @to_run << arg}
114
+ rescue OptionParser::ParseError => e
115
+ puts e
116
+ puts options
117
+ exit(false)
118
+ else
119
+ @filters << proc{false} unless(@filters.empty?)
120
+ end
121
+ not @to_run.empty?
122
+ end
123
+
124
+ def options
125
+ @options ||= OptionParser.new do |o|
126
+ o.banner = "Test::Unit automatic runner."
127
+ o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
128
+
129
+ o.on
130
+ o.on('-r', '--runner=RUNNER', RUNNERS,
131
+ "Use the given RUNNER.",
132
+ "(" + keyword_display(RUNNERS) + ")") do |r|
133
+ @runner = r
134
+ end
135
+
136
+ if (@standalone)
137
+ o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
138
+ @base = b
139
+ end
140
+
141
+ o.on('-w', '--workdir=DIR', "Working directory to run tests.") do |w|
142
+ @workdir = w
143
+ end
144
+
145
+ o.on('-a', '--add=TORUN', Array,
146
+ "Add TORUN to the list of things to run;",
147
+ "can be a file or a directory.") do |a|
148
+ @to_run.concat(a)
149
+ end
150
+
151
+ @pattern = []
152
+ o.on('-p', '--pattern=PATTERN', Regexp,
153
+ "Match files to collect against PATTERN.") do |e|
154
+ @pattern << e
155
+ end
156
+
157
+ @exclude = []
158
+ o.on('-x', '--exclude=PATTERN', Regexp,
159
+ "Ignore files to collect against PATTERN.") do |e|
160
+ @exclude << e
161
+ end
162
+ end
163
+
164
+ o.on('-n', '--name=NAME', String,
165
+ "Runs tests matching NAME.",
166
+ "(patterns may be used).") do |n|
167
+ n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
168
+ case n
169
+ when Regexp
170
+ @filters << proc{|t| n =~ t.method_name ? true : nil}
171
+ else
172
+ @filters << proc{|t| n == t.method_name ? true : nil}
173
+ end
174
+ end
175
+
176
+ o.on('-t', '--testcase=TESTCASE', String,
177
+ "Runs tests in TestCases matching TESTCASE.",
178
+ "(patterns may be used).") do |n|
179
+ n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
180
+ case n
181
+ when Regexp
182
+ @filters << proc{|t| n =~ t.class.name ? true : nil}
183
+ else
184
+ @filters << proc{|t| n == t.class.name ? true : nil}
185
+ end
186
+ end
187
+
188
+ priority_filter = Proc.new do |test|
189
+ if @filters.size > 2
190
+ nil
191
+ else
192
+ Priority::Checker.new(test).need_to_run? or nil
193
+ end
194
+ end
195
+ o.on("--[no-]priority-mode",
196
+ "Runs some tests based on their priority.") do |priority_mode|
197
+ if priority_mode
198
+ Priority.enable
199
+ @filters |= [priority_filter]
200
+ else
201
+ Priority.disable
202
+ @filters -= [priority_filter]
203
+ end
204
+ end
205
+
206
+ o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
207
+ "Appends directory list to $LOAD_PATH.") do |dirs|
208
+ $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
209
+ end
210
+
211
+ color_schemes = ColorScheme.all
212
+ o.on("--color-scheme=SCHEME", color_schemes,
213
+ "Use SCHEME as color scheme.",
214
+ "(#{keyword_display(color_schemes)})") do |scheme|
215
+ @color_scheme = scheme
216
+ end
217
+
218
+ o.on("--config=FILE",
219
+ "Use YAML fomat FILE content as configuration file.") do |file|
220
+ load_config(file)
221
+ end
222
+
223
+ ADDITIONAL_OPTIONS.each do |option_builder|
224
+ option_builder.call(self, o)
225
+ end
226
+
227
+ o.on('--',
228
+ "Stop processing options so that the",
229
+ "remaining options will be passed to the",
230
+ "test."){o.terminate}
231
+
232
+ o.on('-h', '--help', 'Display this help.'){puts o; exit}
233
+
234
+ o.on_tail
235
+ o.on_tail('Deprecated options:')
236
+
237
+ o.on_tail('--console', 'Console runner (use --runner).') do
238
+ warn("Deprecated option (--console).")
239
+ @runner = self.class.runner(:console)
240
+ end
241
+
242
+ if RUNNERS[:fox]
243
+ o.on_tail('--fox', 'Fox runner (use --runner).') do
244
+ warn("Deprecated option (--fox).")
245
+ @runner = self.class.runner(:fox)
246
+ end
247
+ end
248
+
249
+ o.on_tail
250
+ end
251
+ end
252
+
253
+ def keyword_display(keywords)
254
+ keywords.collect do |keyword, _|
255
+ keyword.to_s
256
+ end.uniq.sort.collect do |keyword|
257
+ keyword.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')
258
+ end.join(", ")
259
+ end
260
+
261
+ def run
262
+ suite = @collector[self]
263
+ return false if suite.nil?
264
+ runner = @runner[self]
265
+ return false if runner.nil?
266
+ @runner_options[:color_scheme] ||= @color_scheme
267
+ Dir.chdir(@workdir) if @workdir
268
+ runner.run(suite, @runner_options).passed?
269
+ end
270
+
271
+ def load_config(file)
272
+ require 'yaml'
273
+ config = YAML.load(File.read(file))
274
+ runner_name = config["runner"]
275
+ @runner = self.class.runner(runner_name) || @runner
276
+ @collector = self.class.collector(config["collector"]) || @collector
277
+ (config["color_schemes"] || {}).each do |name, options|
278
+ ColorScheme[name] = options
279
+ end
280
+ runner_options = {}
281
+ (config["#{runner_name}_options"] || {}).each do |key, value|
282
+ key = key.to_sym
283
+ value = ColorScheme[value] if key == :color_scheme
284
+ runner_options[key.to_sym] = value
285
+ end
286
+ @runner_options = @runner_options.merge(runner_options)
287
+ end
288
+
289
+ private
290
+ def default_runner
291
+ if ENV["EMACS"] == "t"
292
+ self.class.runner(:emacs)
293
+ else
294
+ self.class.runner(:console)
295
+ end
296
+ end
297
+
298
+ def default_collector
299
+ self.class.collector(@standalone ? :load : :descendant)
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ require 'test/unit/runner/console'
306
+ require 'test/unit/runner/emacs'
@@ -0,0 +1,43 @@
1
+ module Test
2
+ module Unit
3
+ module Collector
4
+ def initialize
5
+ @filters = []
6
+ end
7
+
8
+ def filter=(filters)
9
+ @filters = case(filters)
10
+ when Proc
11
+ [filters]
12
+ when Array
13
+ filters
14
+ end
15
+ end
16
+
17
+ def add_suite(destination, suite)
18
+ to_delete = suite.tests.find_all{|t| !include?(t)}
19
+ to_delete.each{|t| suite.delete(t)}
20
+ destination << suite unless(suite.size == 0)
21
+ end
22
+
23
+ def include?(test)
24
+ return true if(@filters.empty?)
25
+ @filters.each do |filter|
26
+ result = filter[test]
27
+ if(result.nil?)
28
+ next
29
+ elsif(!result)
30
+ return false
31
+ else
32
+ return true
33
+ end
34
+ end
35
+ true
36
+ end
37
+
38
+ def sort(suites)
39
+ suites.sort_by {|suite| suite.name || suite.to_s}
40
+ end
41
+ end
42
+ end
43
+ end