ruckus 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/README +0 -0
  4. data/README.markdown +51 -0
  5. data/Rakefile +54 -0
  6. data/VERSION +1 -0
  7. data/lib/ruckus.rb +70 -0
  8. data/lib/ruckus/blob.rb +113 -0
  9. data/lib/ruckus/choice.rb +55 -0
  10. data/lib/ruckus/dfuzz.rb +231 -0
  11. data/lib/ruckus/dictionary.rb +119 -0
  12. data/lib/ruckus/enum.rb +39 -0
  13. data/lib/ruckus/extensions/array.rb +33 -0
  14. data/lib/ruckus/extensions/class.rb +168 -0
  15. data/lib/ruckus/extensions/duplicable.rb +37 -0
  16. data/lib/ruckus/extensions/file.rb +24 -0
  17. data/lib/ruckus/extensions/fixnum.rb +26 -0
  18. data/lib/ruckus/extensions/hash.rb +10 -0
  19. data/lib/ruckus/extensions/integer.rb +26 -0
  20. data/lib/ruckus/extensions/ipaddr.rb +155 -0
  21. data/lib/ruckus/extensions/irb.rb +30 -0
  22. data/lib/ruckus/extensions/math.rb +6 -0
  23. data/lib/ruckus/extensions/module.rb +37 -0
  24. data/lib/ruckus/extensions/numeric.rb +117 -0
  25. data/lib/ruckus/extensions/object.rb +22 -0
  26. data/lib/ruckus/extensions/range.rb +16 -0
  27. data/lib/ruckus/extensions/socket.rb +20 -0
  28. data/lib/ruckus/extensions/string.rb +327 -0
  29. data/lib/ruckus/filter.rb +16 -0
  30. data/lib/ruckus/human_display.rb +79 -0
  31. data/lib/ruckus/ip.rb +38 -0
  32. data/lib/ruckus/mac_addr.rb +31 -0
  33. data/lib/ruckus/mutator.rb +318 -0
  34. data/lib/ruckus/null.rb +24 -0
  35. data/lib/ruckus/number.rb +360 -0
  36. data/lib/ruckus/parsel.rb +363 -0
  37. data/lib/ruckus/selector.rb +92 -0
  38. data/lib/ruckus/str.rb +164 -0
  39. data/lib/ruckus/structure.rb +263 -0
  40. data/lib/ruckus/structure/atcreate.rb +23 -0
  41. data/lib/ruckus/structure/beforebacks.rb +28 -0
  42. data/lib/ruckus/structure/defaults.rb +57 -0
  43. data/lib/ruckus/structure/factory.rb +42 -0
  44. data/lib/ruckus/structure/fixupfields.rb +16 -0
  45. data/lib/ruckus/structure/initializers.rb +14 -0
  46. data/lib/ruckus/structure/relate.rb +34 -0
  47. data/lib/ruckus/structure/replacement.rb +30 -0
  48. data/lib/ruckus/structure/searchmods.rb +33 -0
  49. data/lib/ruckus/structure/structureproxies.rb +28 -0
  50. data/lib/ruckus/structure/validate.rb +12 -0
  51. data/lib/ruckus/structure_shortcuts.rb +109 -0
  52. data/lib/ruckus/time_t.rb +26 -0
  53. data/lib/ruckus/vector.rb +97 -0
  54. data/ruckus.gemspec +104 -0
  55. data/test/test_decides.rb +61 -0
  56. data/test/test_mutator.rb +29 -0
  57. data/test/test_override.rb +23 -0
  58. data/test/test_replace.rb +39 -0
  59. metadata +138 -0
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,22 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ *.gem
21
+
22
+ ## PROJECT::SPECIFIC
data/README ADDED
File without changes
@@ -0,0 +1,51 @@
1
+ *Under construction: we're in the process of extracting this from our toolshed
2
+ repository; please pardon the flaws.*
3
+
4
+ # Ruckus: A DOM-Inspired Ruby Smart Fuzzer
5
+
6
+ Ruckus is a:
7
+
8
+ ### Fuzzer
9
+
10
+ A tool used in security testing to generate pathological inputs for
11
+ target code. Two common use cases:
12
+
13
+ * Generating malicious protocol messages to attack network
14
+ software
15
+
16
+ * Creating malicious files in specific file formats to feed
17
+ to target programs
18
+
19
+ ### Smart Fuzzer
20
+
21
+ I'm stealing [Mike Eddington's](http://peachfuzzer.com/) term;
22
+ Smart Fuzzers distinguish themselves from "just plain fuzzers"
23
+ by being aware of the data format they're being used to test. In
24
+ both Eddington's Peach Fuzzer and Ruckus, you accomplish that by
25
+ defining data models (structures) to describe protocols and file
26
+ formats.
27
+
28
+ ### Ruby
29
+
30
+ Peach Fuzzer is written in Python. So is Sully, Pedram Amini's
31
+ fuzzer. SPIKE is written in C. Ruckus is Ruby's answer, and it
32
+ tries to play to Ruby's strengths:
33
+
34
+ * It's much more DSL-y than Peach Fuzzer or Sully
35
+
36
+ * Unlike XML-bound Peach Fuzzer, it's "configuration files"
37
+ are code
38
+
39
+ * You don't really need to know Ruby to write those files
40
+
41
+ Long term I'm hoping Ruckus bears the same relationship to Ruby as
42
+ Expect did to Tcl.
43
+
44
+ ### DOM-Inspired
45
+
46
+ Ruckus separates metadata and actual content, and structures packets
47
+ and file formats as trees of nodes, each with classes and (when desired)
48
+ DOM-style id's (we call them "tags"). Ruckus data can be manipulated
49
+ with tree traversal and "mutated" with cascading style sheet selector-type
50
+ logic.
51
+
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ruckus"
8
+ gem.summary = %Q{A DOM-Inspired Ruby Smart Fuzzer}
9
+ gem.description = %Q{Ruckus: A DOM-Inspired Ruby Smart Fuzzer}
10
+ gem.email = "td@matasano.com"
11
+ gem.homepage = "http://github.com/tduehr/ruckus"
12
+ gem.authors = ["tduehr", "tqbf"]
13
+ gem.add_development_dependency "jeweler", ">= 0"
14
+ gem.rdoc_options = ["--inline-source", "--line-numbers", "--main", "README.markdown"]
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "ruckus #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.4
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # == Introduction
4
+ # This is yet another binary formatter for Ruby; compare to bindata,
5
+ # bitstruct, or pack/unpack.
6
+ #
7
+ # Read in this order:
8
+ # * Parsel
9
+ # * Number
10
+ # * Str
11
+ # * Blob
12
+ # * Structure
13
+
14
+ module Ruckus
15
+
16
+ # :stopdoc:
17
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
18
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
19
+ # :startdoc:
20
+ # Returns the version string for the library.
21
+ #
22
+ def self.version
23
+ VERSION
24
+ end
25
+
26
+ # Returns the library path for the module. If any arguments are given,
27
+ # they will be joined to the end of the libray path using
28
+ # <tt>File.join</tt>.
29
+ #
30
+ def self.libpath( *args )
31
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
32
+ end
33
+
34
+ # Returns the lpath for the module. If any arguments are given,
35
+ # they will be joined to the end of the path using
36
+ # <tt>File.join</tt>.
37
+ #
38
+ def self.path( *args )
39
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
40
+ end
41
+
42
+ # Utility method used to require all files ending in .rb that lie in the
43
+ # directory below this file that has the same name as the filename passed
44
+ # in. Optionally, a specific _directory_ name can be passed in such that
45
+ # the _filename_ does not have to be equivalent to the directory.
46
+ #
47
+ def self.require_all_libs_relative_to( fname, dir = nil )
48
+ dir ||= ::File.basename(fname, '.*')
49
+ search_me = ::File.expand_path(
50
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
51
+ extensions = ::File.expand_path(::File.join(::File.dirname(fname),dir,'extensions','**','*.rb'))
52
+ spath = ::File.expand_path(::File.join(::File.dirname(fname), dir))
53
+ Dir.glob(extensions).each{|rb| require rb}
54
+ require ::File.join(spath, 'parsel.rb')
55
+ require ::File.join(spath, 'number.rb')
56
+ require ::File.join(spath, 'str.rb')
57
+ require ::File.join(spath, 'structure.rb')
58
+ Dir.glob(search_me).reject{|rb| rb =~ /human_display\.rb/}.each {|rb| require rb}
59
+ require ::File.join(spath, 'human_display.rb')
60
+ end
61
+ end
62
+
63
+ Ruckus.require_all_libs_relative_to(__FILE__)
64
+
65
+ # require 'extensions/extensions'
66
+ #
67
+ # %w[ parsel number ip str choice null blob filter structure dictionary
68
+ # mutator vector mac_addr enum time_t selector dfuzz ].each do |f|
69
+ # require 'ruckus/' + f
70
+ # end
@@ -0,0 +1,113 @@
1
+ # === Blobs are collections of Parsels.
2
+
3
+ module Ruckus
4
+ # A Blob wraps an array. Everything within the array is rendered
5
+ # sequentially, returning a single string. Blob rendering is effectively
6
+ # preorder tree traversal (Blobs can contain any Parsel, including other
7
+ # Blobs)
8
+ class Blob < Parsel
9
+ # No special options needed.
10
+ #
11
+ def initialize(opts={})
12
+ @value = Array.new
13
+ (opts[:populate]||[]).each do |k|
14
+ self << k.new
15
+ end
16
+ super(opts)
17
+ end
18
+
19
+ # This is the only
20
+ # way you should add elements to a Blob for now.
21
+ #
22
+ def <<(v)
23
+ @value << v
24
+ v.parent = self
25
+ end
26
+
27
+ # How many elements are in the blob? (<tt>size</tt> returns
28
+ # the rendered size)
29
+ #
30
+ def count; @value.size; end
31
+
32
+ # Assign a value to an element of a blob, so if you assign
33
+ # blob[1] = 1, it works as expected.
34
+ #
35
+ def []=(k, v)
36
+ return @value[k].value = v if not v.kind_of? Parsel
37
+ @value[k] = v
38
+ end
39
+
40
+ # Where is <tt>o</tt> in this blob? (Pretty sure you could
41
+ # just use <tt>index</tt> for this, but whatever)
42
+ #
43
+ def place(o)
44
+ @value.each_with_index do |it, i|
45
+ if o == it
46
+ return i
47
+ end
48
+ end
49
+ nil
50
+ end
51
+
52
+ # As with Parsel; this will recurse through any embedded
53
+ # blobs.
54
+ #
55
+ def capture(str)
56
+ @value.each_with_index do |it, i|
57
+ begin
58
+ str ||= "" # XXX bug
59
+
60
+ # you don't always know the type of object
61
+ # you want to instantiate at compile time;
62
+ # it can depend on the contents of a packet.
63
+ # when it does, there's a flag set that enables
64
+ # a "factory" method which does the parse.
65
+ #
66
+ # the downside of this is once a blob has
67
+ # been parsed with a factory, its definition
68
+ # changes; that same blob can't be reused
69
+ # to parse another packet. So, just don't
70
+ # do that.
71
+
72
+ if it.class.factory?
73
+ @value[i], str = it.class.factory(str)
74
+ else
75
+ str = it.capture(str)
76
+ end
77
+ rescue IncompleteCapture
78
+ err = "at item #{ i }"
79
+ err << " named \"#{ it.name }\"" if it.name
80
+ err << " in struct \"#{ it.parent_struct.name }\"" if it.parent_struct
81
+
82
+ raise IncompleteCapture.new(err) if not str or str.empty?
83
+ end
84
+ end
85
+ str
86
+ end
87
+
88
+ # How big in bytes is this blob and everything it contains?
89
+ # An empty blob has size 0
90
+ #
91
+ def size
92
+ @value.inject(0) {|acc, it| acc + it.size}
93
+ end
94
+
95
+ # Render the blob, or return "" if it's empty.
96
+ #
97
+ def to_s(off=nil)
98
+ @rendered_offset = off || 0
99
+ voff = @rendered_offset
100
+ r = ""
101
+ @value.each do |it|
102
+ s, voff = it.to_s(voff)
103
+ r << s
104
+ end
105
+
106
+ if off
107
+ return r, voff
108
+ else
109
+ return r
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,55 @@
1
+ # === Choices pick binary structures at runtime
2
+
3
+ module Ruckus
4
+
5
+ # A choice wraps a blob, and, on input, picks what to put in the blob
6
+ # based on a code block. Use choices to dispatch protocol responses
7
+ # based on type codes, etc.
8
+ #
9
+ class Choice < Parsel
10
+
11
+ # You must call Choice.new with a block that takes two
12
+ # arguments --- an input string and a reference to the
13
+ # choice instance. For instance:
14
+ #
15
+ # data << Choice.new do |buf, this|
16
+ # if this.parent_struct.message_code == Codes::ERROR
17
+ # this << ErrorFrame.new
18
+ # else
19
+ # this << ResponseFrame.new
20
+ # end
21
+ # this[-1].capture(buf)
22
+ # end
23
+ #
24
+ def initialize(opts={}, &block)
25
+ @parent = opts[:parent]
26
+ raise "provide a block" if not block_given? and not opts[:block] and not respond_to? :choose
27
+ if not opts[:block] and not block_given?
28
+ opts[:block] = lambda {|x, y| self.choose(x)}
29
+ end
30
+ super(opts)
31
+ @block ||= block
32
+ @value = Blob.new
33
+ @value.parent = self
34
+ end
35
+
36
+ # Just render the blob
37
+ #
38
+ def to_s(off=nil)
39
+ @rendered_offset = off || 0
40
+ (@value)? @value.to_s(off) : ""
41
+ end
42
+
43
+ # Call the block, which must return the remainder string.
44
+ #
45
+ def capture(str)
46
+ block.call(str, self)
47
+ end
48
+
49
+ def <<(o)
50
+ @value << o
51
+ o.parent = self
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # = fuzz.rb
4
+ #
5
+ # Fuzz Generators
6
+ #
7
+ # Ruby 1.8 Generators use continuations (which are slow) and leak
8
+ # memory like crazy, so use generators.rb from Ruby 1.9.
9
+ #
10
+ # Author:: Dai Zovi, Dino <ddz@theta44.org>
11
+ # License:: Private
12
+ # Revision:: $Id$
13
+ #
14
+
15
+ require 'generator'
16
+
17
+ module DFuzz
18
+ # Generate Xi-F...Xi+F for each Xi in boundaries and fudge_factor F
19
+ class Fudge < Generator
20
+ def initialize(boundaries, fudge_factor, mask = nil)
21
+ super() { |g|
22
+ boundaries.each {|b|
23
+ 0.upto(fudge_factor) { |f|
24
+ if (mask)
25
+ g.yield((b+f) & mask)
26
+ g.yield((b-f) & mask)
27
+ else
28
+ g.yield b+f
29
+ g.yield b-f
30
+ end
31
+ }
32
+ }
33
+ }
34
+ end
35
+ end
36
+
37
+ # Serially generate each variable in turn (equivalent to
38
+ # recursively nesting generators)
39
+ class Block
40
+ def initialize(defaults, generators)
41
+ @defaults = defaults
42
+ @generators = generators
43
+ end
44
+
45
+ def run(&block)
46
+ generators_index = 0
47
+
48
+ # Baseline
49
+ block.call(@defaults)
50
+
51
+ # Iterate through generators, fully exhausting each and
52
+ # calling the code block with each set of values
53
+ @generators.each { |g|
54
+ values = Array.new(@defaults)
55
+ while (g.next?)
56
+ values[generators_index] = g.next
57
+ block.call(values)
58
+ end
59
+ generators_index += 1;
60
+ }
61
+ end
62
+ end
63
+
64
+ class Integer < Fudge
65
+ def initialize(delta = 128)
66
+ super([0, 0x7FFF, 0xFFFF, 0x7FFFFFFF,
67
+ 0x7FFFFFFFFFFFFFFF], delta)
68
+ end
69
+ end
70
+
71
+ class Byte < Fudge
72
+ def initialize(delta = 16)
73
+ super([0x00, 0x01, 0x7F, 0xFF], delta, 0xFF)
74
+ end
75
+ end
76
+
77
+ class Short < Fudge
78
+ def initialize(delta = 128)
79
+ super([0x0000, 0x0001, 0x7FFF, 0xFFFF], delta, 0xFFFF)
80
+ end
81
+ end
82
+
83
+ class Long < Fudge
84
+ def initialize(delta = 256)
85
+ super([0x00000000, 0x0000001, 0x7FFFFFFF, 0xFFFFFFFF, 0x40000000, 0xC0000000], delta, 0xffffffff)
86
+ end
87
+ end
88
+
89
+ class Char < Generator
90
+ def initialize()
91
+ c = ["A", "0", "~", "`", "!", "@", "#", "$", "%", "^", "&",
92
+ "*", "(", ")", "-", "=", "+", "[", "]", "\\", "|", ";",
93
+ ":", "'", "\"", ",", "<", ".", ">", "/", "?",
94
+ " ", "~", "_", "{", "}", "\x7f","\x00","\x01",
95
+ "\x02","\x03","\x04","\x05", "\x06","\x07","\x08","\x09",
96
+ "\x0a","\x0b","\x0c","\x0d", "\x0e","\x0f","\x10","\x11",
97
+ "\x12","\x13","\x14","\x15", "\x16","\x17","\x18","\x19",
98
+ "\x1a","\x1b","\x1c","\x1d", "\x1e","\x1f",
99
+ "\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87",
100
+ "\x88","\x89","\x8a","\x8b","\x8c","\x8d","\x8e","\x8f",
101
+ "\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97",
102
+ "\x98","\x99","\x9a","\x9b","\x9c","\x9d","\x9e","\x9f",
103
+ "\xa0","\xa1","\xa2","\xa3","\xa4","\xa5","\xa6","\xa7",
104
+ "\xa8","\xa9","\xaa","\xab","\xac","\xad","\xae","\xaf",
105
+ "\xb0","\xb1","\xb2","\xb3","\xb4","\xb5","\xb6","\xb7",
106
+ "\xb8","\xb9","\xba","\xbb","\xbc","\xbd","\xbe","\xbf",
107
+ "\xc0","\xc1","\xc2","\xc3","\xc4","\xc5","\xc6","\xc7",
108
+ "\xc8","\xc9","\xca","\xcb","\xcc","\xcd","\xce","\xcf",
109
+ "\xd0","\xd1","\xd2","\xd3","\xd4","\xd5","\xd6","\xd7",
110
+ "\xd8","\xd9","\xda","\xdb","\xdc","\xdd","\xde","\xdf",
111
+ "\xe0","\xe1","\xe2","\xe3","\xe4","\xe5","\xe6","\xe7",
112
+ "\xe8","\xe9","\xea","\xeb","\xec","\xed","\xee","\xef",
113
+ "\xf0","\xf1","\xf2","\xf3","\xf4","\xf5","\xf6","\xf7",
114
+ "\xf8","\xf9","\xfa","\xfb","\xfc","\xfd","\xfe","\xff", ]
115
+ super(c)
116
+ end
117
+ end
118
+
119
+ class String < Generator
120
+ def initialize(lengths=nil)
121
+ super() { |g|
122
+ # Fuzz strings are each of CHARS repeated each of
123
+ # LENGTHS times and each of strings
124
+ lengths ||= [16, 32, 64, 100, 128, 192, 256, 384, 512, 768, 1024, 2048, 3072, 4096, 6000, 8192, 10000, 16000, 20000, 32000, 50000, 64000, 72000, 100000]
125
+ strings = [
126
+ "%n%n%n%n%n%n%n%n%n%n", "%252n%252n%252n%252n%252n",
127
+ "%x%x%x%x", "%252x%252x%252x%252x",
128
+ "../../../../../../../../../../../../../etc/passwd",
129
+ "../../../../../../../../../../../../../etc/passwd%00",
130
+ "../../../../../../../../../../../../../boot.ini",
131
+ "../../../../../../../../../../../../../boot.ini%00",
132
+ "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\boot.ini",
133
+ "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\boot.ini%00",
134
+ "<script>alert('XSS');</script>",
135
+ "A0`~!@#\$\%^&*()-_=+[]{}\\|;:',.<>/?\""
136
+ ]
137
+ chars = Char.new()
138
+ while chars.next?
139
+ c = chars.next
140
+
141
+ lengths.each { |l|
142
+ g.yield(c * l)
143
+ }
144
+ end
145
+
146
+ strings.each { |s|
147
+ g.yield(s)
148
+ }
149
+ }
150
+ end
151
+ end
152
+
153
+ #
154
+ # Modules for higher-level tokens (e-mail addresses, asn1, etc)
155
+ #
156
+ class EmailAddress < Generator
157
+ def initialize()
158
+ end
159
+ end
160
+
161
+ end
162
+
163
+ ####
164
+ # Unit test
165
+ ####
166
+
167
+ if $0 == __FILE__
168
+ puts "Testing integers..."
169
+ i = 0
170
+ integers = Fuzz::Integer.new()
171
+ while integers.next?
172
+ integers.next
173
+ i += 1
174
+ end
175
+ puts "=> #{i} items"
176
+
177
+ puts "Testing bytes..."
178
+ i = 0
179
+ bytes = Fuzz::Byte.new()
180
+ while bytes.next?
181
+ bytes.next
182
+ i += 1
183
+ end
184
+ puts "=> #{i} items"
185
+
186
+ puts "Testing shorts"
187
+ i = 0
188
+ shorts = Fuzz::Short.new()
189
+ while shorts.next?
190
+ shorts.next
191
+ i += 1
192
+ end
193
+ puts "=> #{i} items"
194
+
195
+ puts "Testing longs"
196
+ i = 0
197
+ longs = Fuzz::Long.new()
198
+ while longs.next?
199
+ longs.next
200
+ i += 1
201
+ end
202
+ puts "=> #{i} items"
203
+
204
+ puts "Testing characters"
205
+ i = 0
206
+ characters = Fuzz::Char.new()
207
+ while characters.next?
208
+ characters.next
209
+ i += 1
210
+ end
211
+ puts "=> #{i} items"
212
+
213
+ puts "Testing strings"
214
+ i = 0
215
+ strings = Fuzz::String.new()
216
+ while strings.next?
217
+ strings.next
218
+ i += 1
219
+ end
220
+ puts "=> #{i} items"
221
+
222
+ puts "Testing Block"
223
+ b = Fuzz::Block.new(["FOO", "BAR"],
224
+ [Fuzz::String.new(), Fuzz::String.new()])
225
+ i = 0
226
+ b.run() { |a, b|
227
+ i += 1
228
+ }
229
+ puts "=> #{i} items"
230
+
231
+ end