rdx 0.9.0.pre

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.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.rdx +20 -0
  3. data/README +19 -0
  4. data/bin/rdx +7 -0
  5. data/examples/minimal/.rdx +8 -0
  6. data/examples/minimal/README +10 -0
  7. data/examples/minimal/lib/other_conventions.rb +64 -0
  8. data/examples/minimal/lib/the_basics.rb +94 -0
  9. data/examples/minimal/lib/using_directives.rb +66 -0
  10. data/examples/minimal/rakefile +27 -0
  11. data/examples/ruby-2.0.0-p0/README +7 -0
  12. data/examples/ruby-2.0.0-p0/install/core/.rdx +6 -0
  13. data/examples/ruby-2.0.0-p0/install/core/README +19 -0
  14. data/examples/ruby-2.0.0-p0/install/core/Rakefile +61 -0
  15. data/examples/ruby-2.0.0-p0/install/core/diffs/array.c.diff +166 -0
  16. data/examples/ruby-2.0.0-p0/install/core/diffs/bignum.c.diff +11 -0
  17. data/examples/ruby-2.0.0-p0/install/core/diffs/class.c.diff +36 -0
  18. data/examples/ruby-2.0.0-p0/install/core/diffs/compar.c.diff +11 -0
  19. data/examples/ruby-2.0.0-p0/install/core/diffs/complex.c.diff +301 -0
  20. data/examples/ruby-2.0.0-p0/install/core/diffs/cont.c.diff +65 -0
  21. data/examples/ruby-2.0.0-p0/install/core/diffs/dir.c.diff +147 -0
  22. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/re.rdoc.diff +328 -0
  23. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/security.rdoc.diff +8 -0
  24. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/standard_library.rdoc.diff +0 -0
  25. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax.rdoc.diff +0 -0
  26. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/assignment.rdoc.diff +160 -0
  27. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/calling_methods.rdoc.diff +130 -0
  28. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/control_expressions.rdoc.diff +254 -0
  29. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/exceptions.rdoc.diff +0 -0
  30. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/literals.rdoc.diff +54 -0
  31. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/methods.rdoc.diff +157 -0
  32. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/miscellaneous.rdoc.diff +91 -0
  33. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/modules_and_classes.rdoc.diff +161 -0
  34. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/precedence.rdoc.diff +8 -0
  35. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/refinements.rdoc.diff +146 -0
  36. data/examples/ruby-2.0.0-p0/install/core/diffs/encoding.c.diff +276 -0
  37. data/examples/ruby-2.0.0-p0/install/core/diffs/enum.c.diff +281 -0
  38. data/examples/ruby-2.0.0-p0/install/core/diffs/enumerator.c.diff +479 -0
  39. data/examples/ruby-2.0.0-p0/install/core/diffs/error.c.diff +143 -0
  40. data/examples/ruby-2.0.0-p0/install/core/diffs/eval.c.diff +47 -0
  41. data/examples/ruby-2.0.0-p0/install/core/diffs/eval_jump.c.diff +23 -0
  42. data/examples/ruby-2.0.0-p0/install/core/diffs/file.c.diff +752 -0
  43. data/examples/ruby-2.0.0-p0/install/core/diffs/gc.c.diff +195 -0
  44. data/examples/ruby-2.0.0-p0/install/core/diffs/hash.c.diff +84 -0
  45. data/examples/ruby-2.0.0-p0/install/core/diffs/iseq.c.diff +354 -0
  46. data/examples/ruby-2.0.0-p0/install/core/diffs/load.c.diff +53 -0
  47. data/examples/ruby-2.0.0-p0/install/core/diffs/marshal.c.diff +98 -0
  48. data/examples/ruby-2.0.0-p0/install/core/diffs/math.c.diff +110 -0
  49. data/examples/ruby-2.0.0-p0/install/core/diffs/numeric.c.diff +103 -0
  50. data/examples/ruby-2.0.0-p0/install/core/diffs/object.c.diff +295 -0
  51. data/examples/ruby-2.0.0-p0/install/core/diffs/pack.c.diff +18 -0
  52. data/examples/ruby-2.0.0-p0/install/core/diffs/parse.y.diff +23 -0
  53. data/examples/ruby-2.0.0-p0/install/core/diffs/proc.c.diff +155 -0
  54. data/examples/ruby-2.0.0-p0/install/core/diffs/random.c.diff +126 -0
  55. data/examples/ruby-2.0.0-p0/install/core/diffs/range.c.diff +49 -0
  56. data/examples/ruby-2.0.0-p0/install/core/diffs/rational.c.diff +312 -0
  57. data/examples/ruby-2.0.0-p0/install/core/diffs/re.c.diff +207 -0
  58. data/examples/ruby-2.0.0-p0/install/core/diffs/ruby.c.diff +21 -0
  59. data/examples/ruby-2.0.0-p0/install/core/diffs/signal.c.diff +67 -0
  60. data/examples/ruby-2.0.0-p0/install/core/diffs/sprintf.c.diff +29 -0
  61. data/examples/ruby-2.0.0-p0/install/core/diffs/string.c.diff +73 -0
  62. data/examples/ruby-2.0.0-p0/install/core/diffs/struct.c.diff +20 -0
  63. data/examples/ruby-2.0.0-p0/install/core/diffs/time.c.diff +691 -0
  64. data/examples/ruby-2.0.0-p0/install/core/diffs/transcode.c.diff +435 -0
  65. data/examples/ruby-2.0.0-p0/install/core/diffs/variable.c.diff +62 -0
  66. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_backtrace.c.diff +164 -0
  67. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_eval.c.diff +99 -0
  68. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_method.c.diff +17 -0
  69. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_trace.c.diff +393 -0
  70. data/examples/ruby-2.0.0-p0/install/stdlib/.rdx +6 -0
  71. data/examples/ruby-2.0.0-p0/install/stdlib/README +19 -0
  72. data/examples/ruby-2.0.0-p0/install/stdlib/Rakefile +53 -0
  73. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/abbrev.rb.diff +77 -0
  74. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/base64.rb.diff +42 -0
  75. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/benchmark.rb.diff +144 -0
  76. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/cmath.rb.diff +52 -0
  77. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/forwardable.rb.diff +150 -0
  78. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/mathn.rb.diff +58 -0
  79. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/matrix.rb.diff +657 -0
  80. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/observer.rb.diff +31 -0
  81. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/optparse.rb.diff +147 -0
  82. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/ostruct.rb.diff +78 -0
  83. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/prime.rb.diff +52 -0
  84. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/pstore.rb.diff +110 -0
  85. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/scanf.rb.diff +100 -0
  86. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/securerandom.rb.diff +144 -0
  87. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/set.rb.diff +637 -0
  88. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/shellwords.rb.diff +66 -0
  89. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/singleton.rb.diff +37 -0
  90. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/tempfile.rb.diff +104 -0
  91. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/thread.rb.diff +38 -0
  92. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/time.rb.diff +140 -0
  93. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/tmpdir.rb.diff +52 -0
  94. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/uri.rb.diff +39 -0
  95. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/uri/common.rb.diff +237 -0
  96. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/weakref.rb.diff +36 -0
  97. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/yaml/store.rb.diff +27 -0
  98. data/examples/ruby-2.0.0-p0/rakefile +165 -0
  99. data/lib/rdx.rb +331 -0
  100. data/lib/rdx/assertions.rb +484 -0
  101. data/lib/rdx/binding.rb +151 -0
  102. data/lib/rdx/code_object.rb +598 -0
  103. data/lib/rdx/comment.rb +338 -0
  104. data/lib/rdx/convention.rb +1174 -0
  105. data/lib/rdx/directive.rb +1432 -0
  106. data/lib/rdx/example.rb +679 -0
  107. data/lib/rdx/generator.rb +112 -0
  108. data/lib/rdx/generator/rdoc.rb +1006 -0
  109. data/lib/rdx/options.rb +359 -0
  110. data/lib/rdx/plain_text.rb +65 -0
  111. data/lib/rdx/reporter.rb +421 -0
  112. data/lib/rdx/ruby_lex.rb +324 -0
  113. data/lib/rdx/runner.rb +309 -0
  114. data/lib/rdx/source_file.rb +94 -0
  115. data/lib/rdx/specification.rb +194 -0
  116. data/lib/rdx/statement.rb +248 -0
  117. data/lib/rdx/store.rb +119 -0
  118. data/lib/rdx/task.rb +361 -0
  119. data/lib/rdx/text.rb +688 -0
  120. data/lib/rdx/version.rb +15 -0
  121. data/rakefile +64 -0
  122. metadata +203 -0
@@ -0,0 +1,359 @@
1
+
2
+ require 'optparse'
3
+ require 'pathname'
4
+
5
+ module RDX
6
+
7
+ #
8
+ # Handles running options for RDX.
9
+ #
10
+ class Options
11
+
12
+ # Current Options instance active.
13
+ def self.current
14
+ RDX.runner && RDX.runner.options
15
+ end
16
+
17
+ # :stopdoc:
18
+
19
+ DirArray = Object.new
20
+
21
+ attr_reader :parser
22
+
23
+ @contents = []
24
+
25
+ class << self
26
+
27
+ private
28
+
29
+ def define_option name=nil, &definition
30
+ attr_reader name if name
31
+ @contents << [name, definition]
32
+ end
33
+ alias define_options define_option
34
+
35
+ def section name
36
+ @contents << name.to_str
37
+ end
38
+
39
+ public
40
+
41
+ def apply_defaults_to options
42
+ @contents.each do |name,definition|
43
+ if definition
44
+ options.instance_eval(&definition)
45
+ else
46
+ options.parser.separator nil
47
+ options.parser.separator name
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ def initialize argv=[]
55
+ @parser = OptionParser.new
56
+ @parser.banner = "Usage: rdx [options] [--] [files...] "
57
+ setup_parser
58
+ @files = []
59
+ parse(argv)
60
+ @parser = nil
61
+ end
62
+
63
+ def setup_parser
64
+ @parser.accept DirArray do |names|
65
+ names.split(File::PATH_SEPARATOR).map do |name|
66
+ dir = File.expand_path(name)
67
+ raise OptionParser::InvalidArgument unless File.directory? dir
68
+ dir
69
+ end
70
+ end
71
+ Options.apply_defaults_to self
72
+ end
73
+
74
+ # :startdoc:
75
+
76
+ # The list of files to be processed.
77
+ attr_reader :files
78
+
79
+ section "Running modes:"
80
+
81
+ ##
82
+ # :method:
83
+ #
84
+ # Verbose running mode. When active locations of tests are showed while they run.
85
+ # In this way you can know where the problem is if the application blocks in the testing.
86
+ #
87
+ # Default to +false+.
88
+ #
89
+ define_option :verbose do
90
+ @verbose = false
91
+ @parser.on '-v', '--verbose', "Run in verbose mode" do
92
+ @verbose = true
93
+ end
94
+ end
95
+
96
+ ##
97
+ # :method:
98
+ #
99
+ # Debug running mode. When active the backtrace of raised exceptions is not filtered:
100
+ # they include also the frames generated in the RDX::ROOT.
101
+ #
102
+ # Default to +false+.
103
+ #
104
+ define_option :debug do
105
+ @debug = false
106
+ @parser.on '-d', '--debug', "Run in debug mode" do
107
+ @debug = true
108
+ end
109
+ end
110
+
111
+ ##
112
+ # :method:
113
+ #
114
+ # Dry run mode. When active conventions are detected, but nothing actually runs.
115
+ # Use this when you don't want to scan the whole sources to find the examples:
116
+ # RDX will recognize them for you.
117
+ #
118
+ # Default to +false+.
119
+ #
120
+ define_option :dry_run do
121
+ @dry_run = false
122
+ @parser.on '-y', '--dry-run', "Run in dry run mode" do
123
+ @dry_run = true
124
+ end
125
+ end
126
+
127
+ ##
128
+ # :method:
129
+ #
130
+ # Fast run mode. When active the documentation output is not produced, increasing
131
+ # the testing speed.
132
+ #
133
+ # Default to +false+.
134
+ #
135
+ define_option :fast do
136
+ @fast = false
137
+ @parser.on '-f', '--fast', '--no-doc-output',
138
+ "Run in fast mode (don't produce documentation output)" do
139
+ @fast = true
140
+ end
141
+ end
142
+
143
+ # Will the documentation output be produced?
144
+ def doc_output
145
+ not fast
146
+ end
147
+
148
+ section "Running options:"
149
+
150
+ ##
151
+ # :method:
152
+ #
153
+ # Directories to search in for libraries, that will be prepended to <tt>$LOAD_PATH</tt>.
154
+ #
155
+ # If this option is not given nothing will be required.
156
+ #
157
+ define_option :lib_dirs do
158
+ @lib_dirs = nil
159
+ @parser.on '-I', '--libdir DIRECTORIES', DirArray,
160
+ "Prepend DIRECTORIES to $LOAD_PATH" do |dirs|
161
+ @lib_dirs ||= []
162
+ @lib_dirs.concat dirs
163
+ end
164
+ end
165
+
166
+ ##
167
+ # :method:
168
+ #
169
+ # The list of libraries that will be required for the tests.
170
+ #
171
+ # If this option is not given but #lib_dirs was all their content will be loaded.
172
+ #
173
+ define_option :libs do
174
+ @libs = nil
175
+ @parser.on '-r', '--require FILE', String,
176
+ "Require FILE as a scipt during the testing phase" do |file|
177
+ @libs ||= []
178
+ @libs << file
179
+ end
180
+ end
181
+
182
+ ##
183
+ # :method:
184
+ #
185
+ # The random seed, that determines the test order.
186
+ #
187
+ define_option :seed do
188
+ @seed = nil
189
+ @parser.on '-s', '--seed SEED', Integer,
190
+ "Sets random seed to SEED. Also via env. Eg: SEED=n rake" do |seed|
191
+ @seed = seed
192
+ end
193
+ end
194
+
195
+ ##
196
+ # :method:
197
+ #
198
+ # The documentation generator tool on which RDX relies.
199
+ #
200
+ # Currently only RDoc is supported, so there isn't such option.
201
+ #
202
+ define_option :generator do
203
+ @generator = 'rdoc'
204
+ # @parser.on '-g', '--generator GENERATOR', String,
205
+ # "Use GENERATOR as the documentation generator" do |generator|
206
+ # @generator = generator
207
+ # end
208
+ end
209
+
210
+ ##
211
+ # :method:
212
+ #
213
+ # The list of options that will be sent to the #generator.
214
+ #
215
+ define_option :generator_options do
216
+ @generator_options = []
217
+ @parser.on '-G', '--generator-option OPTION',
218
+ "Pass OPTION to the documentation generator" do |option|
219
+ @generator_options << option
220
+ end
221
+ end
222
+
223
+ define_option do
224
+ @parser.on '--bash BASH', String,
225
+ "Sets the BASH system command to use in bash examples" do |bash|
226
+ Example::Bash.bash = bash
227
+ end
228
+ end
229
+
230
+ section "Reporting options:"
231
+
232
+ ##
233
+ # :method:
234
+ #
235
+ # The kind of reporter to use. +REPORTER+ may be one of the following:
236
+ # * +common+: no output redirection: the generator and RDX use the same streams;
237
+ # * +docquiet+: nothing is produced by the documentation generator;
238
+ # * +rdxfocused+ (default): writes to <tt>$stderr</tt> the output of the generator tool;
239
+ # * +essential+: writes to <tt>$stderr</tt> even the RDX messages: only the report will be sent to <tt>$stdout</tt>;
240
+ # * +summary+: <tt>$stdout</tt> contains only the headers of the report without messages, one per line.
241
+ #
242
+ define_option :reporter do
243
+ @reporter = 'rdxfocused'
244
+ @parser.on '-R', '--reporter REPORTER', String,
245
+ "Use REPORTER as the reporter" do |reporter|
246
+ @reporter = reporter
247
+ end
248
+ end
249
+
250
+ attr_reader :report_filter # :nodoc:
251
+
252
+ define_options do
253
+ @report_filter = { :show=>[], :hide=>[:Success, :Skip] }
254
+ @parser.on '--hide TYPE', String,
255
+ "Hide TYPE reportables in the report" do |name|
256
+ hide_reportable name
257
+ end
258
+ @parser.on '--show TYPE', String,
259
+ "Show only TYPE reportables in the report" do |name|
260
+ show_reportable name
261
+ end
262
+ @parser.on '-t', '--full-trace',
263
+ "Trace all the reportables (including Success)" do
264
+ @report_filter[:hide].clear
265
+ @report_filter[:show].clear
266
+ end
267
+ @parser.on '--no-warnings',
268
+ "Hide all warings in the report" do
269
+ hide_reportable :Warning
270
+ end
271
+ end
272
+
273
+ define_options do
274
+ Assertions.use_default_diff
275
+ @parser.on '--diff DIFF', String,
276
+ "Sets the DIFF system command to use in assert_equal" do |diff|
277
+ Assertions.diff = diff
278
+ end
279
+ @parser.on '--no-diff',
280
+ "Doesn't use the DIFF system command in assert_equal" do
281
+ Assertions.diff = nil
282
+ end
283
+ end
284
+
285
+ section "Other options:"
286
+
287
+ define_option do
288
+ @parser.on '--version', "Show version header and exit" do
289
+ puts RDX::VERSION_HEADER
290
+ exit
291
+ end
292
+ end
293
+
294
+ define_option do
295
+ @parser.on '-h', '--help', "Show this help message" do
296
+ puts @parser
297
+ exit
298
+ end
299
+ end
300
+
301
+ private
302
+
303
+ # :stopdoc:
304
+
305
+ def show_reportable name
306
+ name = name.capitalize.to_sym
307
+ @report_filter[:hide].delete(name) or
308
+ @report_filter[:show] << name
309
+ end
310
+
311
+ def hide_reportable name
312
+ name = name.capitalize.to_sym
313
+ @report_filter[:show].delete(name) or
314
+ @report_filter[:hide] << name
315
+ end
316
+
317
+ def parse(argv)
318
+ @parser.parse!(argv)
319
+ adjust_report_filter
320
+ adjust_require_list
321
+ adjust_seed
322
+ finalize_argv argv
323
+ end
324
+
325
+ def adjust_report_filter
326
+ @report_filter[:hide].uniq!
327
+ @report_filter[:show].uniq!
328
+ end
329
+
330
+ def adjust_require_list
331
+ if @libs
332
+ @lib_dirs ||= []
333
+ elsif @lib_dirs
334
+ @libs = []
335
+ @lib_dirs.each do |lib_dir|
336
+ Dir.glob "#{lib_dir}/*.rb" do |file|
337
+ @libs << File.basename(file,'.rb')
338
+ end
339
+ end
340
+ else
341
+ @lib_dirs = []
342
+ @libs = []
343
+ end
344
+ end
345
+
346
+ def adjust_seed
347
+ return if @seed
348
+ srand
349
+ @seed = (ENV["SEED"] || srand).to_i % 0xFFFF
350
+ end
351
+
352
+ def finalize_argv argv
353
+ @files.concat argv
354
+ argv.clear
355
+ end
356
+
357
+ end
358
+
359
+ end
@@ -0,0 +1,65 @@
1
+
2
+ module RDX
3
+
4
+ #
5
+ # Represents a text section (like this one) in a comment.
6
+ # :rdx: off
7
+ # Whereas this section is an example
8
+ # Its content is not intended to be executed.
9
+ #
10
+ class PlainText < CodeObject
11
+
12
+ # The SourceFile this text section belongs to.
13
+ def source_file
14
+ comment.source_file
15
+ end
16
+
17
+ # The Comment this text section belongs to.
18
+ attr_reader :comment
19
+ alias parent comment
20
+
21
+ def initialize(comment,text,relative_line_no=1) # :nodoc:
22
+ @comment = comment
23
+ super(text,relative_line_no)
24
+ end
25
+
26
+ #
27
+ # :section: API
28
+ #
29
+
30
+ # Returns +true+. This method should be used instead of _section_<tt>.is_a?(PlainText)</tt>.
31
+ def text?
32
+ true
33
+ end
34
+
35
+ # Returns +false+. This method should be used instead of _section_<tt>.is_a?(Example)</tt>.
36
+ def example?
37
+ false
38
+ end
39
+
40
+ #
41
+ # :section: Internal
42
+ #
43
+
44
+ #
45
+ # Generates a warning if a convention is detected in the text,
46
+ # because we probably forget to turn this plain text into an example
47
+ # (with +RDoc+ this happens if we don't add indentation).
48
+ #
49
+ # If it's not the case - you intentionally want to include a convention pattern
50
+ # in a text section - use Directive.disable_warnings with +conventions+ as parameter.
51
+ #
52
+ def check_missing_conventions
53
+ RubyLex.extract_potential_comments(text) do |comment,l_no|
54
+ comment = Text.normalize_comment comment
55
+ store.find_convention_in comment do |conv|
56
+ warn "Found pattern for convention `#{conv.name}' in plain text section",
57
+ :conventions, location(l_no)
58
+ end
59
+ end
60
+ return self
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,421 @@
1
+
2
+ module RDX
3
+
4
+ # :stopdoc:
5
+
6
+ class Reportable
7
+ attr_accessor :in_building
8
+ attr_accessor :before_require
9
+ attr_accessor :rdx_caller
10
+ attr_reader :file_name
11
+ attr_reader :line_no
12
+ attr_reader :type
13
+ def initialize location, type=nil
14
+ @file_name,@line_no = split_location(location)
15
+ @type = type && type.to_sym
16
+ end
17
+ def split_location location
18
+ m = location.to_str.match /:(\d++)(?!\w)/
19
+ return ['',0] unless m
20
+ return [m.pre_match, m[1].to_i]
21
+ end
22
+ private :split_location
23
+ def content
24
+ end
25
+ def location_ary
26
+ [file_name,line_no]
27
+ end
28
+ def location
29
+ location_ary.join ':'
30
+ end
31
+ def <=> other
32
+ return nil unless other.is_a?(:location_ary)
33
+ return self.location_ary <=> other.location_ary
34
+ end
35
+ def label
36
+ end
37
+ def result_code
38
+ label.to_str[0,1]
39
+ end
40
+ def code_priority
41
+ 0
42
+ end
43
+ def when
44
+ return "[in building]" if in_building
45
+ "[before require]" if before_require
46
+ end
47
+ def report_header
48
+ whr = location.to_str
49
+ whn = self.when && ' '+self.when
50
+ lbl = label.to_str
51
+ result = "#{whr}#{whn}: #{lbl}\n"
52
+ result << "\tCalled by: #{rdx_caller}\n" if rdx_caller
53
+ return result
54
+ end
55
+ def report_body
56
+ result = ''
57
+ if content && !content.empty?
58
+ result << content.gsub(/^/,"\t")
59
+ end
60
+ return result
61
+ end
62
+ def report
63
+ report_header.to_str + report_body.to_str
64
+ end
65
+ def failure?
66
+ false
67
+ end
68
+ end
69
+
70
+ class Success < Reportable
71
+ def label
72
+ "Success [#{type}]"
73
+ end
74
+ def result_code
75
+ '.'
76
+ end
77
+ def self.result_code
78
+ '.'
79
+ end
80
+ def code_priority
81
+ 1
82
+ end
83
+ def initialize type, location
84
+ super(location,type)
85
+ end
86
+ def type_of? arg
87
+ arg == :Success
88
+ end
89
+ end
90
+
91
+ class Detection < Success
92
+ def label
93
+ "Detected #{type}"
94
+ end
95
+ def result_code
96
+ ''
97
+ end
98
+ end
99
+
100
+ class Warning < Reportable
101
+ def label
102
+ "Warning [#{type}]"
103
+ end
104
+ def code_priority
105
+ 2
106
+ end
107
+ attr_reader :content
108
+ def initialize content, type, location
109
+ @content = content
110
+ super(location,type)
111
+ end
112
+ def type_of? arg
113
+ arg == :Warning
114
+ end
115
+ end
116
+
117
+ class Skip < Reportable
118
+ def label
119
+ "Skip [#{type}]"
120
+ end
121
+ def code_priority
122
+ 2
123
+ end
124
+ attr_reader :content
125
+ def initialize content, type, location
126
+ @content = content
127
+ super(location,type)
128
+ end
129
+ def type_of? arg
130
+ arg == :Skip
131
+ end
132
+ end
133
+
134
+ class Failure < Reportable
135
+ def label
136
+ "Failure [#{type}]"
137
+ end
138
+ def code_priority
139
+ 3
140
+ end
141
+ attr_reader :content
142
+ def initialize fail, type, location
143
+ @content = fail.message
144
+ unless location
145
+ location = fail.backtrace.find{ |line| !line.start_with?(RDX::ROOT) }
146
+ # TODO: search for first in the target folder
147
+ location ||= fail.backtrace.first
148
+ end
149
+ super(location,type)
150
+ end
151
+ def failure?
152
+ true
153
+ end
154
+ def type_of? arg
155
+ arg == :Failure
156
+ end
157
+ end
158
+
159
+ class UnexpectedError < Reportable
160
+ def label
161
+ 'Error'
162
+ end
163
+ def code_priority
164
+ 4
165
+ end
166
+ attr_reader :content
167
+ def initialize raised_exception
168
+ @content = [
169
+ "Class: #{raised_exception.class.name}",
170
+ "Message: #{raised_exception.message}",
171
+ "---Backtrace---",
172
+ *RDX.filter_backtrace(raised_exception.backtrace),
173
+ "---------------",
174
+ ""
175
+ ].join "\n"
176
+ idx = raised_exception.backtrace.find_index{ |line| line.start_with?(RDX::ROOT) }
177
+ idx -= 1 if idx > 0
178
+ super(raised_exception.backtrace[idx])
179
+ end
180
+ def failure?
181
+ true
182
+ end
183
+ def type_of? arg
184
+ arg == :Error
185
+ end
186
+ end
187
+
188
+ # :startdoc:
189
+
190
+ #
191
+ # Shows the report of the tests.
192
+ #
193
+ class Reporter
194
+
195
+ # :stopdoc:
196
+
197
+ @reporters = {}
198
+ class << self
199
+ attr_reader :reporters
200
+ end
201
+ def self.reporter_name
202
+ name.split('::').last.downcase
203
+ end
204
+ def self.inherited child_class
205
+ Reporter.reporters[child_class.reporter_name] = child_class
206
+ end
207
+ def self.[] name
208
+ Reporter.reporters[name.downcase] or
209
+ raise "Undefined reporter: #{name}"
210
+ end
211
+
212
+ attr_reader :runner
213
+ def options
214
+ runner.options
215
+ end
216
+ def verbose
217
+ options.verbose
218
+ end
219
+ def store
220
+ runner.store
221
+ end
222
+
223
+ attr_reader :stdout
224
+
225
+ attr_reader :stderr
226
+
227
+ def initialize runner, stdout=$stdout, stderr=$stderr
228
+ @runner = runner
229
+ @stdout = stdout || StringIO.new
230
+ @stderr = stderr || StringIO.new
231
+ end
232
+
233
+ def print *args
234
+ stdout.print *args
235
+ end
236
+ def puts *args
237
+ stdout.puts *args
238
+ end
239
+ alias report puts
240
+
241
+ def on_documenting &blk
242
+ RDX::Util.change_ostreams stdout, stderr, &blk
243
+ end
244
+
245
+ def on_testing &blk
246
+ RDX::Util.change_ostreams nil, nil, &blk
247
+ end
248
+
249
+ def start_run_test test
250
+ print "\n\tRunning #{test.location} : " if verbose
251
+ end
252
+ def finish_run_test test
253
+ print test.result_code
254
+ end
255
+
256
+ def run_tests tests
257
+ puts unless verbose # newline for dots
258
+ count = 0
259
+ total_time = RDX::Util.measure_time do
260
+ tests.each do |test|
261
+ start_run_test test
262
+ test.full_run
263
+ finish_run_test test
264
+ count += 1
265
+ if count == 40
266
+ count = 0
267
+ puts
268
+ end
269
+ end
270
+ end
271
+ if tests.empty?
272
+ puts 'No tests!'
273
+ else
274
+ puts # finishes the dots
275
+ tests_count = tests.size
276
+ # For statistics is fine to assume skip and warnings negligible...
277
+ assertions_count = tests.reduce(0){ |sum,test| sum+test.reportables.size }
278
+ show_statistics(total_time,tests_count,assertions_count)
279
+ end
280
+ puts
281
+ end
282
+
283
+ def run_pre_tests tests
284
+ print '# Running pre-require tests:'
285
+ run_tests tests
286
+ end
287
+
288
+ def require_libs
289
+ puts '# Requiring libs:'
290
+ before_req_size = $LOADED_FEATURES.size
291
+ result = yield
292
+ no_libs = before_req_size == $LOADED_FEATURES.size
293
+ puts 'No libraries to require!' if no_libs
294
+ puts
295
+ result
296
+ end
297
+
298
+ def require_lib lib
299
+ print lib, '... '
300
+ before_req_size = $LOADED_FEATURES.size
301
+ result = yield
302
+ required_now = $LOADED_FEATURES.drop(before_req_size)
303
+ if required_now.empty?
304
+ puts 'ALREDY LOADED'
305
+ else
306
+ unless verbose
307
+ puts 'OK!'
308
+ else
309
+ puts 'OK:'
310
+ required_now.each do |new_req|
311
+ puts "\t#{new_req} required"
312
+ end
313
+ end
314
+ end
315
+ result
316
+ end
317
+
318
+ def run_post_tests tests
319
+ print '# Running post-require tests:'
320
+ run_tests tests
321
+ end
322
+
323
+ def show_report
324
+ show_report_header
325
+ show_aggregated_results
326
+ show_summary
327
+ end
328
+
329
+ private
330
+
331
+ def show_report_header
332
+ puts
333
+ puts "========== Test report =========="
334
+ puts
335
+ end
336
+
337
+ def show_statistics total_time, tests_count, assertions_count
338
+ puts "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." %
339
+ [total_time, tests_count/total_time, assertions_count/total_time]
340
+ end
341
+
342
+ def show_aggregated_results
343
+ result = ''
344
+ digits = reportables.size.to_s.size
345
+ format = "%#{digits}d) %s\n"
346
+ reportables.each_with_index do |reportable,i|
347
+ result << format % [i+1, reportable_content(reportable)]
348
+ end
349
+ report result
350
+ end
351
+
352
+ def show_summary
353
+ tests_no = store.tests_no
354
+ counts = Hash.new(0)
355
+ all_reportables.each{ |r| counts[r.class] += 1 }
356
+ result = "Total: %d runs, %d successes, %d failures, %d errors, %d skips, %d warnings" %
357
+ [tests_no, counts[Success], counts[Failure], counts[UnexpectedError], counts[Skip], counts[Warning]]
358
+ puts result
359
+ end
360
+
361
+ def all_reportables
362
+ store.collect_reportables
363
+ end
364
+
365
+ def reportables
366
+ return @reportables if @reportables
367
+ @reportables = all_reportables.dup
368
+ options.report_filter[:hide].each do |type|
369
+ @reportables.delete_if{ |r| r.type_of?(type) }
370
+ end
371
+ show = options.report_filter[:show]
372
+ unless show.empty?
373
+ @reportables.keep_if do |reportable|
374
+ show.any?{ |type| reportable.type_of? type }
375
+ end
376
+ end
377
+ @reportables
378
+ end
379
+
380
+ def reportable_content reportable
381
+ reportable.report
382
+ end
383
+
384
+ class Common < self
385
+ end
386
+
387
+ class DocQuiet < self
388
+ def on_documenting &blk
389
+ RDX::Util.change_ostreams(nil,nil,&blk)
390
+ end
391
+ end
392
+
393
+ class RDXFocused < self
394
+ def on_documenting &blk
395
+ RDX::Util.change_ostreams(stderr,stderr,&blk)
396
+ end
397
+ end
398
+
399
+ class Essential < RDXFocused
400
+ def print *args
401
+ stderr.print *args
402
+ end
403
+ def puts *args
404
+ stderr.puts *args
405
+ end
406
+ def show_report_header
407
+ end
408
+ def reportable_content reportable
409
+ super.chomp("\n")
410
+ end
411
+ end
412
+
413
+ class Summary < Essential
414
+ def reportable_content reportable
415
+ reportable.report_header[/.+/]
416
+ end
417
+ end
418
+
419
+ end
420
+
421
+ end