rufus-treechecker 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -125,7 +125,7 @@ module Rufus
125
125
  #
126
126
  class TreeChecker
127
127
 
128
- VERSION = '1.0.1'
128
+ VERSION = '1.0.2'
129
129
 
130
130
  #
131
131
  # pretty-prints the sexp tree of the given rubycode
@@ -142,20 +142,19 @@ module Rufus
142
142
  #
143
143
  def initialize (&block)
144
144
 
145
- @root_checks = []
146
- @checks = []
147
-
148
- @current_checks = @checks
145
+ @root_set = RuleSet.new
146
+ @set = RuleSet.new
147
+ @current_set = @set
149
148
 
150
149
  add_rules(&block)
151
150
  end
152
151
 
153
152
  def to_s
154
- p self.class
155
- puts ' root_checks :'
156
- puts @root_checks.collect { |r| r.inspect }.join("\n")
157
- puts ' checks :'
158
- puts @checks.collect { |r| r.inspect }.join("\n")
153
+ s = "#{self.class} (#{self.object_id})\n"
154
+ s << "root_set :\n"
155
+ s << @root_set.to_s
156
+ s << "set :\n"
157
+ s << @set.to_s
159
158
  end
160
159
 
161
160
  #
@@ -167,9 +166,10 @@ module Rufus
167
166
 
168
167
  sexp = parse(rubycode)
169
168
 
170
- @root_checks.each do |meth, *args|
171
- send meth, sexp, args
172
- end
169
+ #@root_checks.each do |meth, *args|
170
+ # send meth, sexp, args
171
+ #end
172
+ @root_set.check(sexp)
173
173
 
174
174
  do_check(sexp)
175
175
  end
@@ -179,9 +179,10 @@ module Rufus
179
179
  #
180
180
  def clone
181
181
 
182
- copy = TreeChecker.new
183
- copy.instance_variable_set(:@checks, @checks.dup)
184
- copy
182
+ tc = TreeChecker.new
183
+ tc.instance_variable_set(:@root_set, @root_set.clone)
184
+ tc.instance_variable_set(:@set, @set.clone)
185
+ tc
185
186
  end
186
187
 
187
188
  #
@@ -199,46 +200,117 @@ module Rufus
199
200
  #
200
201
  def freeze
201
202
  super
202
- @root_checks.freeze
203
- @root_checks.each { |c| c.freeze }
204
- @checks.freeze
205
- @checks.each { |c| c.freeze }
206
- end
207
-
208
- #
209
- # generates a 'classic' tree checker
210
- #
211
- # Here is how it's built :
212
- #
213
- # return TreeChecker.new do
214
- # exclude_fvccall :abort
215
- # exclude_fvccall :exit, :exit!
216
- # exclude_fvccall :system
217
- # exclude_eval
218
- # exclude_alias
219
- # exclude_global_vars
220
- # exclude_call_on File, FileUtils
221
- # exclude_class_tinkering
222
- # exclude_module_tinkering
223
- # end
224
- #
225
- def self.new_classic_tree_checker
226
-
227
- return TreeChecker.new do
228
- exclude_fvccall :abort
229
- exclude_fvccall :exit, :exit!
230
- exclude_fvccall :system
231
- exclude_eval
232
- exclude_alias
233
- exclude_global_vars
234
- exclude_call_on File, FileUtils
235
- exclude_class_tinkering
236
- exclude_module_tinkering
237
- end
203
+ @root_set.freeze
204
+ @set.freeze
238
205
  end
239
206
 
240
207
  protected
241
208
 
209
+ class RuleSet
210
+
211
+ def initialize
212
+
213
+ @excluded_symbols = {} # symbol => exclusion_message
214
+ @accepted_patterns = {} # 1st elt of pattern => pattern
215
+ @excluded_patterns = {} # 1st elt of pattern => pattern, excl_message
216
+ end
217
+
218
+ def clone
219
+ rs = RuleSet.new
220
+ rs.instance_variable_set(:@excluded_symbols, @excluded_symbols.dup)
221
+ rs.instance_variable_set(:@accepted_patterns, @accepted_patterns.dup)
222
+ rs.instance_variable_set(:@excluded_patterns, @excluded_patterns.dup)
223
+ rs
224
+ end
225
+
226
+ def exclude_symbol (s, message)
227
+
228
+ @excluded_symbols[s] = (message || ":#{s} is excluded")
229
+ end
230
+
231
+ def accept_pattern (pat)
232
+
233
+ (@accepted_patterns[pat.first] ||= []) << pat
234
+ end
235
+
236
+ def exclude_pattern (pat, message)
237
+
238
+ (@excluded_patterns[pat.first] ||= []) << [
239
+ pat, message || "#{pat.inspect} is excluded" ]
240
+ end
241
+
242
+ def check (sexp)
243
+
244
+ if sexp.is_a?(Symbol)
245
+
246
+ m = @excluded_symbols[sexp]
247
+ raise SecurityError.new(m) if m
248
+
249
+ elsif sexp.is_a?(Array)
250
+
251
+ # accepted patterns are evaluated before excluded patterns
252
+ # if one is found the excluded patterns are skipped
253
+
254
+ pats = @accepted_patterns[sexp.first]
255
+ pats.each { |pat| return if check_pattern(sexp, pat) } if pats
256
+
257
+ pats = @excluded_patterns[sexp.first]
258
+ return unless pats
259
+
260
+ pats.each do |pat, msg|
261
+ raise SecurityError.new(msg) if check_pattern(sexp, pat)
262
+ end
263
+ end
264
+ end
265
+
266
+ def freeze
267
+
268
+ super
269
+
270
+ @excluded_symbols.freeze
271
+ @excluded_symbols.each { |k, v| k.freeze; v.freeze }
272
+ @accepted_patterns.freeze
273
+ @accepted_patterns.each { |k, v| k.freeze; v.freeze }
274
+ @excluded_patterns.freeze
275
+ @excluded_patterns.each { |k, v| k.freeze; v.freeze }
276
+ end
277
+
278
+ def to_s
279
+
280
+ s = "#{self.class} (#{self.object_id})\n"
281
+ s << " excluded symbols :\n"
282
+ @excluded_symbols.each do |k, v|
283
+ s << " - #{k.inspect}, #{v}\n"
284
+ end
285
+ s << " accepted patterns :\n"
286
+ @accepted_patterns.each do |k, v|
287
+ v.each do |p|
288
+ s << " - #{k.inspect}, #{p.inspect}\n"
289
+ end
290
+ end
291
+ s << " excluded patterns :\n"
292
+ @excluded_patterns.each do |k, v|
293
+ v.each do |p|
294
+ s << " - #{k.inspect}, #{p.inspect}\n"
295
+ end
296
+ end
297
+ s
298
+ end
299
+
300
+ protected
301
+
302
+ def check_pattern (sexp, pat)
303
+
304
+ return false if sexp.length < pat.length
305
+
306
+ (1..pat.length-1).each do |i|
307
+ return false if (pat[i] != :any and pat[i] != sexp[i])
308
+ end
309
+
310
+ return true # we have a match
311
+ end
312
+ end
313
+
242
314
  #--
243
315
  # the methods used to define the checks
244
316
  #++
@@ -249,9 +321,26 @@ module Rufus
249
321
  #
250
322
  def at_root (&block)
251
323
 
252
- @current_checks = @root_checks
324
+ @current_set = @root_set
253
325
  add_rules(&block)
254
- @current_checks = @checks
326
+ @current_set = @set
327
+ end
328
+
329
+ def extract_message (args)
330
+
331
+ message = nil
332
+ args = args.dup
333
+ message = args.pop if args.last.is_a?(String)
334
+ [ args, message ]
335
+ end
336
+
337
+ def expand_class (arg)
338
+
339
+ if arg.is_a?(Class) or arg.is_a?(Module)
340
+ [ parse(arg.to_s), parse("::#{arg.to_s}") ]
341
+ else
342
+ [ arg ]
343
+ end
255
344
  end
256
345
 
257
346
  #
@@ -266,33 +355,39 @@ module Rufus
266
355
  #
267
356
  def exclude_head (head, message=nil)
268
357
 
269
- @current_checks << [ :do_exclude_head, head, message ]
358
+ @current_set.exclude_pattern(head, message)
270
359
  end
271
360
 
272
- [
273
- :exclude_symbol,
274
- :exclude_fcall,
275
- :exclude_vcall,
276
- :exclude_fvcall,
277
- :exclude_fvccall,
278
- :exclude_call_on,
279
- :exclude_call_to
361
+ def exclude_symbol (*args)
362
+ args, message = extract_message(args)
363
+ args.each { |a| @current_set.exclude_symbol(a, message) }
364
+ end
280
365
 
281
- ].each do |m|
282
- class_eval <<-EOS
283
- def #{m} (*args)
366
+ def exclude_fcall (*args)
367
+ do_exclude_pair(:fcall, args)
368
+ end
284
369
 
285
- message = args.last.is_a?(String) ? args.pop : nil
370
+ def exclude_vcall (*args)
371
+ do_exclude_pair(:vcall, args)
372
+ end
286
373
 
287
- args.each do |a|
374
+ def exclude_fvcall (*args)
375
+ do_exclude_pair(:fcall, args)
376
+ do_exclude_pair(:vcall, args)
377
+ end
288
378
 
289
- a = [ Class, Module ].include?(a.class) ? \
290
- parse(a.to_s) : a.to_sym
379
+ def exclude_call_on (*args)
380
+ do_exclude_pair(:call, args)
381
+ end
291
382
 
292
- @current_checks << [ :do_#{m}, a, message ]
293
- end
294
- end
295
- EOS
383
+ def exclude_call_to (*args)
384
+ args, message = extract_message(args)
385
+ args.each { |a| @current_set.exclude_pattern([ :call, :any, a], message) }
386
+ end
387
+
388
+ def exclude_fvccall (*args)
389
+ exclude_fvcall(*args)
390
+ exclude_call_to(*args)
296
391
  end
297
392
 
298
393
  #
@@ -306,14 +401,11 @@ module Rufus
306
401
  # k = ::Kernel
307
402
  #
308
403
  def exclude_rebinding (*args)
309
-
310
- message = args.last.is_a?(String) ? args.pop : nil
311
-
404
+ args, message = extract_message(args)
312
405
  args.each do |a|
313
- c0 = parse(a.to_s)
314
- c1 = parse("::#{a.to_s}")
315
- @current_checks << [ :do_exclude_rebinding, c0, message ]
316
- @current_checks << [ :do_exclude_rebinding, c1, message ]
406
+ expand_class(a).each do |c|
407
+ @current_set.exclude_pattern([ :lasgn, :any, c], message)
408
+ end
317
409
  end
318
410
  end
319
411
 
@@ -322,7 +414,6 @@ module Rufus
322
414
  # of classes
323
415
  #
324
416
  def exclude_access_to (*args)
325
-
326
417
  exclude_call_on *args
327
418
  exclude_rebinding *args
328
419
  end
@@ -332,8 +423,7 @@ module Rufus
332
423
  #
333
424
  def exclude_def
334
425
 
335
- @current_checks << [
336
- :do_exclude_symbol, :defn, 'method definitions are forbidden' ]
426
+ @current_set.exclude_symbol(:defn, 'method definitions are forbidden')
337
427
  end
338
428
 
339
429
  #
@@ -342,23 +432,21 @@ module Rufus
342
432
  # a list of exceptions (classes) can be passed. Subclassing those
343
433
  # exceptions is permitted.
344
434
  #
345
- def exclude_class_tinkering (*exceptions)
346
-
347
- #
348
- # :class
435
+ # exclude_class_tinkering :except => [ String, Array ]
436
+ #
437
+ def exclude_class_tinkering (*args)
349
438
 
350
- @current_checks << [
351
- :do_exclude_class_tinkering
352
- ] + exceptions.collect { |e| parse(e.to_s) }
439
+ @current_set.exclude_pattern(
440
+ [ :sclass ], 'opening the metaclass of an instance is forbidden')
353
441
 
354
- #
355
- # :sclass
442
+ Array(args.last[:except]).each { |e|
443
+ expand_class(e).each do |c|
444
+ @current_set.accept_pattern([ :class, :any, c ])
445
+ end
446
+ } if args.last.is_a?(Hash)
356
447
 
357
- @current_checks << [
358
- :do_exclude_symbol,
359
- :sclass,
360
- 'opening the metaclass of an instance is forbidde'
361
- ]
448
+ @current_set.exclude_pattern(
449
+ [ :class ], 'defining a class is forbidden')
362
450
  end
363
451
 
364
452
  #
@@ -366,9 +454,8 @@ module Rufus
366
454
  #
367
455
  def exclude_module_tinkering
368
456
 
369
- @current_checks << [
370
- :do_exclude_symbol, :module, 'defining or opening a module is forbidden'
371
- ]
457
+ @current_set.exclude_symbol(
458
+ :module, 'defining or opening a module is forbidden')
372
459
  end
373
460
 
374
461
  #
@@ -376,10 +463,8 @@ module Rufus
376
463
  #
377
464
  def exclude_global_vars
378
465
 
379
- @current_checks << [
380
- :do_exclude_symbol, :gvar, "global vars are forbidden" ]
381
- @current_checks << [
382
- :do_exclude_symbol, :gasgn, "global vars are forbidden" ]
466
+ @current_set.exclude_symbol(:gvar, 'global vars are forbidden')
467
+ @current_set.exclude_symbol(:gasgn, 'global vars are forbidden')
383
468
  end
384
469
 
385
470
  #
@@ -387,10 +472,8 @@ module Rufus
387
472
  #
388
473
  def exclude_alias
389
474
 
390
- @current_checks << [
391
- :do_exclude_symbol, :alias, "'alias' is forbidden" ]
392
- @current_checks << [
393
- :do_exclude_symbol, :alias_method, "'alias_method' is forbidden" ]
475
+ @current_set.exclude_symbol(:alias, "'alias' is forbidden")
476
+ @current_set.exclude_symbol(:alias_method, "'alias_method' is forbidden")
394
477
  end
395
478
 
396
479
  #
@@ -398,26 +481,17 @@ module Rufus
398
481
  #
399
482
  def exclude_eval
400
483
 
401
- @current_checks << [
402
- :do_exclude_fcall,
403
- :eval,
404
- "eval() is forbidden" ]
405
- @current_checks << [
406
- :do_exclude_call_to,
407
- :instance_eval,
408
- "instance_eval() is forbidden" ]
409
- @current_checks << [
410
- :do_exclude_call_to,
411
- :module_eval,
412
- "module_eval() is forbidden" ]
484
+ exclude_fcall(:eval, 'eval() is forbidden')
485
+ exclude_call_to(:module_eval, 'module_eval() is forbidden')
486
+ exclude_call_to(:instance_eval, 'instance_eval() is forbidden')
413
487
  end
414
488
 
415
489
  #
416
490
  # bans the use of backquotes
417
491
  #
418
492
  def exclude_backquotes
419
- @current_checks << [
420
- :do_exclude_symbol, :xstr, "backquotes are forbidden" ]
493
+
494
+ @current_set.exclude_symbol(:xstr, 'backquotes are forbidden')
421
495
  end
422
496
 
423
497
  #
@@ -425,8 +499,18 @@ module Rufus
425
499
  #
426
500
  def exclude_raise
427
501
 
428
- @current_checks << [ :do_exclude_fvccall, :raise, "raise is forbidden" ]
429
- @current_checks << [ :do_exclude_fvccall, :throw, "throw is forbidden" ]
502
+ exclude_fvccall(:raise, 'raise is forbidden')
503
+ exclude_fvccall(:throw, 'throw is forbidden')
504
+ end
505
+
506
+ def do_exclude_pair (first, args)
507
+
508
+ args, message = extract_message(args)
509
+ args.each do |a|
510
+ expand_class(a).each do |c|
511
+ @current_set.exclude_pattern([ first, c ], message)
512
+ end
513
+ end
430
514
  end
431
515
 
432
516
  #
@@ -434,9 +518,7 @@ module Rufus
434
518
  #
435
519
  def do_check (sexp)
436
520
 
437
- @checks.each do |exclusion_method, *args|
438
- send exclusion_method, sexp, args
439
- end
521
+ @set.check(sexp)
440
522
 
441
523
  return unless sexp.is_a?(Array) # check over, seems fine...
442
524
 
@@ -445,125 +527,6 @@ module Rufus
445
527
  sexp.each { |c| do_check c }
446
528
  end
447
529
 
448
- #
449
- # the methods that actually perform the checks
450
- # (and potentially raise security exceptions)
451
-
452
- #
453
- # constructs a new set of arguments by inserting the newhead at the
454
- # beginning of the arguments
455
- #
456
- def cons (newhead, args)
457
-
458
- newhead = Array(newhead)
459
- newhead << args[0]
460
-
461
- [ newhead ] + (args[1, -1] || [])
462
- end
463
-
464
- def do_exclude_fcall (sexp, args)
465
-
466
- do_exclude_head(sexp, cons(:fcall, args))
467
- end
468
-
469
- def do_exclude_vcall (sexp, args)
470
-
471
- do_exclude_head(sexp, cons(:vcall, args))
472
- end
473
-
474
- #
475
- # excludes :fcall and :vcall
476
- #
477
- def do_exclude_fvcall (sexp, args)
478
-
479
- do_exclude_fcall(sexp, args)
480
- do_exclude_vcall(sexp, args)
481
- end
482
-
483
- #
484
- # excludes :fcall and :vcall and :call (to)
485
- #
486
- def do_exclude_fvccall (sexp, args)
487
-
488
- do_exclude_fvcall(sexp, args)
489
- #do_exclude_head(sexp, cons([ :call, [ :const, :Kernel ] ], args))
490
- do_exclude_call_to(sexp, args)
491
- end
492
-
493
- #
494
- # raises a Rufus::SecurityError if the sexp is a reference to
495
- # a certain symbol (like :gvar or :alias).
496
- #
497
- def do_exclude_symbol (sexp, args)
498
-
499
- raise SecurityError.new(
500
- args[1] || "symbol :#{excluded_symbol} is forbidden"
501
- ) if sexp == args[0]
502
- end
503
-
504
- #
505
- # raises a security error if the sexp is a call on a given constant or
506
- # module (class)
507
- #
508
- def do_exclude_call_on (sexp, args)
509
-
510
- do_exclude_head(sexp, [ [:call, args[0]] ] + (args[1, -1] || []))
511
- end
512
-
513
- #
514
- # this method is called by all the methods checking composite sexps.
515
- #
516
- def do__exclude (sexp, args, default_error_message, &block)
517
-
518
- return unless sexp.is_a?(Array)
519
-
520
- raise SecurityError.new(
521
- args[1] || default_error_message
522
- ) if block.call(args)
523
- end
524
-
525
- #
526
- # raises a security error if a call to a given method of any instance
527
- # is found
528
- #
529
- def do_exclude_call_to (sexp, args)
530
-
531
- do__exclude(sexp, args, "calls to '#{args[0]}' are forbidden") do
532
-
533
- (sexp[0] == :call and sexp[2] == args[0])
534
- end
535
- end
536
-
537
- def do_exclude_rebinding (sexp, args)
538
-
539
- do__exclude(sexp, args, "rebinding '#{args[0]}' is forbidden") do
540
-
541
- (sexp[0] == :lasgn and sexp[2] == args[0])
542
- end
543
- end
544
-
545
- def do_exclude_head (sexp, args)
546
-
547
- do__exclude(sexp, args, "#{args[0].inspect} is forbidden") do
548
-
549
- (sexp[0, args[0].length] == args[0])
550
- end
551
- end
552
-
553
- def do_exclude_class_tinkering (sexp, args)
554
-
555
- return unless sexp.is_a?(Array) # lonely symbols are not class definitions
556
-
557
- return unless sexp[0] == :class
558
-
559
- raise SecurityError.new(
560
- 'defining or opening a class is forbidden'
561
- ) if args.length == 0 or ( ! args.include?(sexp[2]))
562
- #
563
- # raise error if there are no exceptions or
564
- # if the parent class is not a member of the exception list
565
- end
566
-
567
530
  #
568
531
  # a simple parse (relies on ruby_parser currently)
569
532
  #
data/test/bm.rb ADDED
@@ -0,0 +1,95 @@
1
+
2
+ require 'rubygems'
3
+
4
+ require 'benchmark'
5
+ include Benchmark
6
+
7
+ require 'rufus/treechecker'
8
+
9
+ Benchmark.benchmark do |b|
10
+
11
+ tc = nil
12
+
13
+ b.report do
14
+ tc = Rufus::TreeChecker.new do
15
+
16
+ exclude_fvccall :abort, :exit, :exit!
17
+ exclude_fvccall :system, :fork, :syscall, :trap, :require, :load
18
+
19
+ #exclude_call_to :class
20
+ exclude_fvcall :private, :public, :protected
21
+
22
+ #exclude_def # no method definition
23
+ exclude_eval # no eval, module_eval or instance_eval
24
+ exclude_backquotes # no `rm -fR the/kitchen/sink`
25
+ exclude_alias # no alias or aliast_method
26
+ exclude_global_vars # $vars are off limits
27
+ exclude_module_tinkering # no module opening
28
+ exclude_raise # no raise or throw
29
+
30
+ exclude_rebinding Kernel # no 'k = Kernel'
31
+
32
+ exclude_access_to(
33
+ IO, File, FileUtils, Process, Signal, Thread, ThreadGroup)
34
+
35
+ #exclude_class_tinkering :except => OpenWFE::ProcessDefinition
36
+ exclude_class_tinkering :except => Rufus::TreeChecker
37
+ #
38
+ # excludes defining/opening any class except
39
+ # OpenWFE::ProcessDefinition
40
+
41
+ exclude_call_to :instance_variable_get, :instance_variable_set
42
+ end
43
+ end
44
+
45
+ DEF0 = <<-EOS
46
+ #class MyDef0 < OpenWFE::ProcessDefinition
47
+ class MyDef0 < Rufus::TreeChecker
48
+ sequence do
49
+ participant "alpha"
50
+ participant 'alpha'
51
+ alpha
52
+ end
53
+ end
54
+ EOS
55
+
56
+ N = 100
57
+ #N = 1
58
+
59
+ b.report do
60
+ N.times { tc.check(DEF0) }
61
+ end
62
+ end
63
+
64
+ #
65
+ # before RuleSet (N=100)
66
+ #
67
+ # mettraux:rufus-treechecker[master]/$ date
68
+ # Tue Sep 2 09:33:06 JST 2008
69
+ # mettraux:rufus-treechecker[master]/$ ruby -Ilib test/bm.rb
70
+ # 0.000000 0.000000 0.000000 ( 0.004252)
71
+ # 5.680000 0.040000 5.720000 ( 5.745755)
72
+ # mettraux:rufus-treechecker[master]/$ ruby -Ilib test/bm.rb
73
+ # 0.010000 0.000000 0.010000 ( 0.004367)
74
+ # 5.670000 0.040000 5.710000 ( 5.731221)
75
+ # mettraux:rufus-treechecker[master]/$ ruby -Ilib test/bm.rb
76
+ # 0.010000 0.000000 0.010000 ( 0.004247)
77
+ # 5.670000 0.040000 5.710000 ( 5.727363)
78
+ #
79
+
80
+ #
81
+ # with RuleSet (N=100)
82
+ #
83
+ # mettraux:rufus-treechecker[master]/$ date
84
+ # Tue Sep 2 13:25:24 JST 2008
85
+ # mettraux:rufus-treechecker[master]/$ ruby -Ilib test/bm.rb
86
+ # 0.000000 0.000000 0.000000 ( 0.006439)
87
+ # 0.340000 0.000000 0.340000 ( 0.342302)
88
+ # mettraux:rufus-treechecker[master]/$ ruby -Ilib test/bm.rb
89
+ # 0.000000 0.000000 0.000000 ( 0.006269)
90
+ # 0.340000 0.000000 0.340000 ( 0.342301)
91
+ # mettraux:rufus-treechecker[master]/$ ruby -Ilib test/bm.rb
92
+ # 0.000000 0.000000 0.000000 ( 0.006350)
93
+ # 0.340000 0.000000 0.340000 ( 0.342841)
94
+ #
95
+
data/test/ft_0_basic.rb CHANGED
@@ -68,6 +68,7 @@ class BasicTest < Test::Unit::TestCase
68
68
  exclude_call_on File, FileUtils
69
69
  exclude_call_on IO
70
70
  end
71
+ #puts tc.to_s
71
72
 
72
73
  assert_nok(tc, 'data = File.read("surf.txt")')
73
74
  assert_nok(tc, 'f = File.new("surf.txt")')
@@ -99,23 +100,9 @@ class BasicTest < Test::Unit::TestCase
99
100
  def test_5b_exclude_class_tinkering_with_exceptions
100
101
 
101
102
  tc = Rufus::TreeChecker.new do
102
- exclude_class_tinkering String, Rufus::TreeChecker
103
- end
104
-
105
- assert_nok(tc, 'class String; def length; 3; end; end')
106
-
107
- assert_ok(tc, 'class S2 < String; def length; 3; end; end')
108
- assert_ok(tc, 'class Toto < Rufus::TreeChecker; def length; 3; end; end')
109
-
110
- assert_nok(tc, 'class Toto; end')
111
- assert_nok(tc, 'class Alpha::Toto; end')
112
- end
113
-
114
- def test_5c_exclude_class_tinkering_with_exceptions
115
-
116
- tc = Rufus::TreeChecker.new do
117
- exclude_class_tinkering 'String', 'Rufus::TreeChecker'
103
+ exclude_class_tinkering :except => [ String, Rufus::TreeChecker ]
118
104
  end
105
+ #puts tc.to_s
119
106
 
120
107
  assert_nok(tc, 'class String; def length; 3; end; end')
121
108
 
@@ -238,9 +225,12 @@ class BasicTest < Test::Unit::TestCase
238
225
  exclude_access_to File
239
226
  end
240
227
 
228
+ #puts tc.to_s
229
+
241
230
  assert_nok(tc, 'f = File')
242
231
  assert_nok(tc, 'f = ::File')
243
232
  assert_nok(tc, 'File.read "hello.txt"')
233
+ assert_nok(tc, '::File.read "hello.txt"')
244
234
  end
245
235
 
246
236
  #def test_X
@@ -28,7 +28,7 @@ class OldTreeCheckerTest < Test::Unit::TestCase
28
28
  exclude_alias
29
29
  exclude_global_vars
30
30
  exclude_call_on File, FileUtils
31
- exclude_class_tinkering Testy::Tasty
31
+ exclude_class_tinkering :except => Testy::Tasty
32
32
  exclude_module_tinkering
33
33
 
34
34
  exclude_fvcall :public
@@ -0,0 +1,32 @@
1
+
2
+ #
3
+ # Testing rufus-treechecker
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Tue Sep 2 14:28:01 JST 2008
8
+ #
9
+
10
+ require 'testmixin'
11
+
12
+ class CloneTest < Test::Unit::TestCase
13
+ include TestMixin
14
+
15
+
16
+ def test_0
17
+
18
+ tc0 = Rufus::TreeChecker.new do
19
+ exclude_fvccall :abort
20
+ end
21
+
22
+ tc1 = tc0.clone
23
+ tc1.add_rules do
24
+ at_root do
25
+ exclude_head [ :block ]
26
+ end
27
+ end
28
+
29
+ assert_not_equal tc0.object_id, tc1.object_id
30
+ end
31
+ end
32
+
data/test/test.rb CHANGED
@@ -1,4 +1,5 @@
1
1
 
2
2
  require 'ft_0_basic'
3
3
  require 'ft_1_old_treechecker'
4
+ require 'ft_2_clone'
4
5
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufus-treechecker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-09-01 00:00:00 +09:00
12
+ date: 2008-09-02 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -33,8 +33,10 @@ extra_rdoc_files:
33
33
  files:
34
34
  - lib/rufus
35
35
  - lib/rufus/treechecker.rb
36
+ - test/bm.rb
36
37
  - test/ft_0_basic.rb
37
38
  - test/ft_1_old_treechecker.rb
39
+ - test/ft_2_clone.rb
38
40
  - test/test.rb
39
41
  - test/testmixin.rb
40
42
  - README.txt