ruckus 0.5.4

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 (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