ronin 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/History.txt +39 -0
  2. data/Manifest.txt +46 -34
  3. data/README.txt +81 -20
  4. data/Rakefile +6 -4
  5. data/TODO.txt +1 -5
  6. data/bin/ronin +2 -2
  7. data/lib/ronin.rb +3 -3
  8. data/lib/ronin/arch.rb +5 -3
  9. data/lib/ronin/author.rb +2 -1
  10. data/lib/ronin/cache/cache.rb +78 -0
  11. data/lib/ronin/cache/extension.rb +6 -6
  12. data/lib/ronin/cache/extension_cache.rb +3 -21
  13. data/lib/ronin/{parameters/instance_param.rb → cache/maintainer.rb} +22 -17
  14. data/lib/ronin/cache/overlay.rb +74 -23
  15. data/lib/ronin/cache/overlay_cache.rb +3 -21
  16. data/lib/ronin/chars/char_set.rb +114 -31
  17. data/lib/ronin/chars/chars.rb +20 -10
  18. data/lib/ronin/{parameters/param.rb → code/emittable.rb} +29 -11
  19. data/lib/ronin/code/symbol_table.rb +13 -0
  20. data/lib/ronin/{parameters/class_param.rb → code/token.rb} +37 -10
  21. data/lib/ronin/config.rb +33 -0
  22. data/lib/ronin/context.rb +32 -29
  23. data/lib/ronin/database.rb +1 -2
  24. data/lib/ronin/extensions.rb +0 -1
  25. data/lib/ronin/extensions/string.rb +41 -0
  26. data/lib/ronin/extensions/uri/query_params.rb +8 -0
  27. data/lib/ronin/formatting/extensions/binary/string.rb +10 -0
  28. data/lib/ronin/{program.rb → hexdump.rb} +2 -2
  29. data/lib/ronin/{parameters/exceptions/missing_param.rb → hexdump/extensions.rb} +2 -6
  30. data/lib/ronin/{extensions/kernel.rb → hexdump/extensions/file.rb} +8 -6
  31. data/lib/ronin/{persistence.rb → hexdump/extensions/kernel.rb} +7 -6
  32. data/lib/ronin/hexdump/hexdump.rb +76 -0
  33. data/lib/ronin/license.rb +5 -3
  34. data/lib/ronin/model.rb +4 -2
  35. data/lib/ronin/models.rb +8 -2
  36. data/lib/ronin/object_context.rb +89 -62
  37. data/lib/ronin/rpc/console.rb +6 -4
  38. data/lib/ronin/rpc/shell.rb +4 -4
  39. data/lib/ronin/sessions/http.rb +144 -0
  40. data/lib/ronin/sessions/session.rb +2 -1
  41. data/lib/ronin/sessions/telnet.rb +3 -1
  42. data/lib/ronin/sessions/udp.rb +1 -1
  43. data/lib/ronin/sessions/web.rb +7 -2
  44. data/lib/ronin/translators/translator.rb +75 -0
  45. data/lib/ronin/ui/command_line.rb +25 -0
  46. data/lib/ronin/ui/command_line/command.rb +165 -0
  47. data/lib/ronin/ui/command_line/command_line.rb +117 -0
  48. data/lib/ronin/{program → ui/command_line}/commands.rb +12 -9
  49. data/lib/ronin/ui/command_line/commands/add.rb +75 -0
  50. data/lib/ronin/{program/commands/help.rb → ui/command_line/commands/default.rb} +26 -17
  51. data/lib/ronin/ui/command_line/commands/extension.rb +85 -0
  52. data/lib/ronin/ui/command_line/commands/help.rb +70 -0
  53. data/lib/ronin/{program → ui/command_line}/commands/install.rb +26 -23
  54. data/lib/ronin/ui/command_line/commands/list.rb +93 -0
  55. data/lib/ronin/ui/command_line/commands/overlay.rb +187 -0
  56. data/lib/ronin/{program/commands/uninstall.rb → ui/command_line/commands/remove.rb} +25 -17
  57. data/lib/ronin/{program/commands/update.rb → ui/command_line/commands/uninstall.rb} +27 -17
  58. data/lib/ronin/{program/commands/remove.rb → ui/command_line/commands/update.rb} +24 -18
  59. data/lib/ronin/{program → ui/command_line}/exceptions.rb +1 -1
  60. data/lib/ronin/{program → ui/command_line}/exceptions/unknown_command.rb +4 -2
  61. data/lib/ronin/ui/command_line/options.rb +148 -0
  62. data/lib/ronin/{console.rb → ui/console.rb} +0 -0
  63. data/lib/ronin/ui/shell.rb +117 -0
  64. data/lib/ronin/version.rb +1 -1
  65. data/lib/ronin/web.rb +1 -0
  66. data/lib/ronin/web/extensions.rb +1 -0
  67. data/lib/ronin/web/extensions/hpricot.rb +5 -0
  68. data/lib/ronin/web/extensions/hpricot/comment.rb +19 -0
  69. data/lib/ronin/web/extensions/hpricot/container.rb +46 -0
  70. data/lib/ronin/web/extensions/hpricot/doc.rb +21 -0
  71. data/lib/ronin/web/extensions/hpricot/elem.rb +25 -0
  72. data/lib/ronin/web/extensions/hpricot/tag.rb +19 -0
  73. data/lib/ronin/web/extensions/hpricot/text.rb +19 -0
  74. data/lib/ronin/web/web.rb +70 -4
  75. data/spec/arch_spec.rb +1 -1
  76. data/spec/author_spec.rb +1 -1
  77. data/spec/chars/char_set_spec.rb +177 -0
  78. data/spec/code/symbol_table_spec.rb +6 -0
  79. data/spec/extensions/string_spec.rb +12 -0
  80. data/spec/formatting/binary_spec.rb +9 -0
  81. data/spec/license_spec.rb +1 -1
  82. data/spec/object_context/object_context_spec.rb +29 -0
  83. data/spec/platform_spec.rb +1 -1
  84. data/spec/product_spec.rb +1 -1
  85. data/spec/ronin_spec.rb +1 -1
  86. data/spec/spec_helper.rb +3 -2
  87. data/spec/target_spec.rb +1 -1
  88. data/spec/translators/translator_spec.rb +63 -0
  89. data/spec/web/extensions/hpricot_spec.rb +62 -0
  90. data/static/extension.rb.erb +16 -0
  91. data/static/overlay.xsl +103 -0
  92. data/tasks/spec.rb +2 -0
  93. metadata +72 -42
  94. data/FAQ.txt +0 -103
  95. data/lib/ronin/environment.rb +0 -39
  96. data/lib/ronin/objects.rb +0 -27
  97. data/lib/ronin/parameters.rb +0 -27
  98. data/lib/ronin/parameters/exceptions.rb +0 -25
  99. data/lib/ronin/parameters/exceptions/param_not_found.rb +0 -29
  100. data/lib/ronin/parameters/parameters.rb +0 -286
  101. data/lib/ronin/program/command.rb +0 -203
  102. data/lib/ronin/program/commands/add.rb +0 -71
  103. data/lib/ronin/program/commands/list.rb +0 -79
  104. data/lib/ronin/program/options.rb +0 -201
  105. data/lib/ronin/program/program.rb +0 -168
  106. data/lib/ronin/rpc/interactive.rb +0 -55
  107. data/lib/ronin/rpc/interactive_console.rb +0 -58
  108. data/lib/ronin/rpc/interactive_shell.rb +0 -59
  109. data/lib/ronin/shell.rb +0 -81
  110. data/spec/parameters/parameters_spec.rb +0 -109
File without changes
@@ -0,0 +1,117 @@
1
+ #
2
+ #--
3
+ # Ronin - A Ruby platform designed for information security and data
4
+ # exploration tasks.
5
+ #
6
+ # Copyright (c) 2006-2008 Hal Brodigan (postmodern.mod3 at gmail.com)
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #++
22
+ #
23
+
24
+ module Ronin
25
+ class Shell
26
+
27
+ # Default shell prompt
28
+ DEFAULT_PROMPT = '>'
29
+
30
+ # Shell name to use
31
+ attr_accessor :name
32
+
33
+ # Shell prompt
34
+ attr_accessor :prompt
35
+
36
+ #
37
+ # Creates a new Shell object with the given _options_.
38
+ #
39
+ # _options_ may contain the following keys:
40
+ # <tt>:name</tt>:: The name of the shell.
41
+ # <tt>:prompt</tt>::The prompt to use for the shell.
42
+ #
43
+ def initialize(options={})
44
+ @name = options[:name]
45
+ @prompt = (options[:prompt] || DEFAULT_PROMPT)
46
+ end
47
+
48
+ #
49
+ # Creates and starts a new Shell object with the specified _options_.
50
+ # If a _block_ is given, it will be passed every command.
51
+ #
52
+ def self.start(options={},&block)
53
+ self.new(options).start(&block)
54
+ end
55
+
56
+ #
57
+ # Starts the shell using the given _block_ to process commands.
58
+ #
59
+ def start(&block)
60
+ history_rollback = 0
61
+
62
+ loop do
63
+ line = Readline.readline("#{@name}#{@prompt} ")
64
+
65
+ if line =~ /^\s*exit\s*$/
66
+ break
67
+ else
68
+ Readline::HISTORY << line
69
+ history_rollback += 1
70
+
71
+ begin
72
+ block.call(self,line)
73
+ rescue => e
74
+ puts "#{e.class.name}: #{e.message}"
75
+ end
76
+ end
77
+ end
78
+
79
+ history_rollback.times do
80
+ Readline::HISTORY.pop
81
+ end
82
+
83
+ return nil
84
+ end
85
+
86
+ #
87
+ # Equivalent to <tt>STDOUT.putc(char)</tt>.
88
+ #
89
+ def putc(char)
90
+ STDOUT.putc(char)
91
+ end
92
+
93
+ #
94
+ # Equivalent to <tt>STDOUT.print(string)</tt>.
95
+ #
96
+ def print(string)
97
+ STDOUT.print(string)
98
+ end
99
+
100
+ #
101
+ # Equivalent to <tt>STDOUT.puts(string)</tt>.
102
+ #
103
+ def puts(string)
104
+ STDOUT.puts(string)
105
+ end
106
+
107
+ alias << puts
108
+
109
+ #
110
+ # Equivalent to <tt>STDOUT.printf(string,*objects)</tt>.
111
+ #
112
+ def printf(string,*objects)
113
+ STDOUT.printf(string,*objects)
114
+ end
115
+
116
+ end
117
+ end
@@ -23,5 +23,5 @@
23
23
 
24
24
  module Ronin
25
25
  # Ronin version
26
- VERSION = '0.1.1'
26
+ VERSION = '0.1.2'
27
27
  end
@@ -21,4 +21,5 @@
21
21
  #++
22
22
  #
23
23
 
24
+ require 'ronin/web/extensions'
24
25
  require 'ronin/web/web'
@@ -0,0 +1 @@
1
+ require 'ronin/web/extensions/hpricot'
@@ -0,0 +1,5 @@
1
+ require 'ronin/web/extensions/hpricot/comment'
2
+ require 'ronin/web/extensions/hpricot/tag'
3
+ require 'ronin/web/extensions/hpricot/container'
4
+ require 'ronin/web/extensions/hpricot/elem'
5
+ require 'ronin/web/extensions/hpricot/doc'
@@ -0,0 +1,19 @@
1
+ require 'hpricot'
2
+
3
+ module Hpricot
4
+ class Comment
5
+
6
+ #
7
+ # Returns +true+ if the comment has the same content the _other_ comment,
8
+ # returns +false+ otherwise.
9
+ #
10
+ def eql?(other)
11
+ return false unless self.class == other.class
12
+
13
+ return content == other.content
14
+ end
15
+
16
+ alias == eql?
17
+
18
+ end
19
+ end
@@ -0,0 +1,46 @@
1
+ require 'hpricot'
2
+
3
+ module Hpricot
4
+ module Container
5
+ #
6
+ # Iterates over every sub-child, passing each to the specified _block_.
7
+ #
8
+ def every_child(&block)
9
+ each_child do |child|
10
+ block.call(child)
11
+
12
+ if child.kind_of?(Hpricot::Container)
13
+ child.every_child(&block)
14
+ end
15
+ end
16
+
17
+ return self
18
+ end
19
+
20
+ #
21
+ # Iterates over every text node, passing each to the specified _block_.
22
+ #
23
+ def all_text(&block)
24
+ every_child do |child|
25
+ block.call(child) if child.kind_of?(Text)
26
+ end
27
+ end
28
+
29
+ #
30
+ # Returns the number of all sub-children.
31
+ #
32
+ def count_children
33
+ sum = 0
34
+
35
+ every_child { |child| sum += 1 }
36
+ return sum
37
+ end
38
+
39
+ #
40
+ # Compares the number of sub-children with that of the _other_ element.
41
+ #
42
+ def <=>(other)
43
+ count_children <=> other.count_children
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ require 'ronin/web/extensions/hpricot/container'
2
+ require 'ronin/web/extensions/hpricot/tag'
3
+ require 'ronin/web/extensions/hpricot/text'
4
+ require 'ronin/web/extensions/hpricot/comment'
5
+ require 'ronin/web/extensions/hpricot/elem'
6
+
7
+ module Hpricot
8
+ class Doc
9
+
10
+ include Comparable
11
+
12
+ #
13
+ # Returns +true+ if the documents children match the children of the
14
+ # _other_ document.
15
+ #
16
+ def ==(other)
17
+ children == other.children
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require 'ronin/web/extensions/hpricot/container'
2
+
3
+ require 'hpricot'
4
+
5
+ module Hpricot
6
+ class Elem
7
+
8
+ include Comparable
9
+
10
+ #
11
+ # Returns +true+ if the element has the same starting-tag and
12
+ # ending-tag as the _other_ element, returns +false+ otherwise.
13
+ #
14
+ def eql?(other)
15
+ return false unless self.class == other.class
16
+
17
+ return (stag == other.stag && etag == other.etag)
18
+ end
19
+
20
+ def ==(other)
21
+ self.eql?(other) && super(other)
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ require 'hpricot'
2
+
3
+ module Hpricot
4
+ module Tag
5
+
6
+ #
7
+ # Returns +true+ if the tag has the same name as the _other_ tag,
8
+ # returns +false+ otherwise.
9
+ #
10
+ def eql?(other)
11
+ return false unless self.class == other.class
12
+
13
+ return self.name == other.name
14
+ end
15
+
16
+ alias == eql?
17
+
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'hpricot'
2
+
3
+ module Hpricot
4
+ class Text
5
+
6
+ #
7
+ # Returns +true+ if the text node has the same content the _other_ text
8
+ # node, returns +false+ otherwise.
9
+ #
10
+ def eql?(other)
11
+ return false unless self.class == other.class
12
+
13
+ return content == other.content
14
+ end
15
+
16
+ alias == eql?
17
+
18
+ end
19
+ end
@@ -26,6 +26,7 @@ require 'ronin/network/http'
26
26
  require 'uri/http'
27
27
  require 'mechanize'
28
28
  require 'open-uri'
29
+ require 'spidr'
29
30
 
30
31
  module Ronin
31
32
  module Web
@@ -69,10 +70,12 @@ module Ronin
69
70
  userinfo = "#{Web.proxy[:user]}:#{Web.proxy[:password]}"
70
71
  end
71
72
 
72
- return URI::HTTP.build(:host => Web.proxy[:host],
73
- :port => Web.proxy[:port],
74
- :userinfo => userinfo,
75
- :path => '/')
73
+ return URI::HTTP.build(
74
+ :host => Web.proxy[:host],
75
+ :port => Web.proxy[:port],
76
+ :userinfo => userinfo,
77
+ :path => '/'
78
+ )
76
79
  end
77
80
  end
78
81
 
@@ -261,5 +264,68 @@ module Ronin
261
264
  block.call(body) if block
262
265
  return body
263
266
  end
267
+
268
+ #
269
+ # Creates a new Spidr::Agent object with the given _options_ and
270
+ # _block_. If a _block_ is given, it will be passed the newly created
271
+ # Spidr::Agent object.
272
+ #
273
+ # _options_ may contain the following keys:
274
+ # <tt>:proxy</tt>:: The proxy to use while spidering. Defaults to
275
+ # Web.proxy.
276
+ # <tt>:user_agent</tt>:: The User-Agent string to send. Defaults to
277
+ # Web.user_agent.
278
+ # <tt>:referer</tt>:: The referer URL to send.
279
+ # <tt>:delay</tt>:: Duration in seconds to pause between spidering each
280
+ # link. Defaults to 0.
281
+ # <tt>:host</tt>:: The host-name to visit.
282
+ # <tt>:hosts</tt>:: An +Array+ of host patterns to visit.
283
+ # <tt>:ignore_hosts</tt>:: An +Array+ of host patterns to not visit.
284
+ # <tt>:ports</tt>:: An +Array+ of port patterns to visit.
285
+ # <tt>:ignore_ports</tt>:: An +Array+ of port patterns to not visit.
286
+ # <tt>:links</tt>:: An +Array+ of link patterns to visit.
287
+ # <tt>:ignore_links</tt>:: An +Array+ of link patterns to not visit.
288
+ # <tt>:exts</tt>:: An +Array+ of File extension patterns to visit.
289
+ # <tt>:ignore_exts</tt>:: An +Array+ of File extension patterns to not
290
+ # visit.
291
+ #
292
+ def Web.spider_agent(options={},&block)
293
+ options = Web.spider_default_options.merge(options)
294
+
295
+ return Spidr::Agent.new(options,&block)
296
+ end
297
+
298
+ #
299
+ # Creates a new Spidr::Agent object with the given _options_ and will
300
+ # begin spidering the specified host _name_. If a _block_ is given it
301
+ # will be passed the newly created Spidr::Agent object, before the
302
+ # agent begins spidering.
303
+ #
304
+ def Web.spider_host(name,options={},&block)
305
+ options = Web.spider_default_options.merge(options)
306
+
307
+ return Spidr::Agent.host(name,options,&block)
308
+ end
309
+
310
+ #
311
+ # Creates a new Spidr::Agent object with the given _options_ and will
312
+ # begin spidering the host of the specified _url_. If a _block_ is
313
+ # given it will be passed the newly created Spidr::Agent object, before
314
+ # the agent begins spidering.
315
+ #
316
+ def Web.spider_site(url,options={},&block)
317
+ options = Web.spider_default_options.merge(options)
318
+
319
+ return Spidr::Agent.site(url,options,&block)
320
+ end
321
+
322
+ protected
323
+
324
+ #
325
+ # Returns the default options for Spidr::Agent.
326
+ #
327
+ def Web.spider_default_options
328
+ {:proxy => Web.proxy, :user_agent => Web.user_agent}
329
+ end
264
330
  end
265
331
  end
@@ -1,6 +1,6 @@
1
1
  require 'ronin/arch'
2
2
 
3
- require 'spec_helper'
3
+ require 'helpers/database'
4
4
 
5
5
  describe Arch do
6
6
  it "should require a name, endian and address_length attributes" do
@@ -1,6 +1,6 @@
1
1
  require 'ronin/author'
2
2
 
3
- require 'spec_helper'
3
+ require 'helpers/database'
4
4
 
5
5
  describe Author do
6
6
  it "should have a default name" do
@@ -0,0 +1,177 @@
1
+ require 'ronin/chars/chars'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Ronin do
6
+ describe Chars::CharSet do
7
+ before(:all) do
8
+ @integer_range = (0x41..0x43)
9
+ @string_range = ('A'..'C')
10
+ @integers = @integer_range.to_a
11
+ @strings = @string_range.to_a
12
+
13
+ @char_set = Chars::CharSet.new(*@strings)
14
+ end
15
+
16
+ it "may be created with String arguments" do
17
+ @chars = Chars::CharSet.new(*@strings)
18
+
19
+ @strings.each do |s|
20
+ @chars.include_char?(s).should == true
21
+ end
22
+ end
23
+
24
+ it "may be created with an Array of Strings" do
25
+ @chars = Chars::CharSet.new(@strings)
26
+
27
+ @strings.each do |s|
28
+ @chars.include_char?(s).should == true
29
+ end
30
+ end
31
+
32
+ it "may be created with a Range of Strings" do
33
+ @chars = Chars::CharSet.new(@string_range)
34
+
35
+ @strings.each do |s|
36
+ @chars.include_char?(s).should == true
37
+ end
38
+ end
39
+
40
+ it "may be created with Integer arguments" do
41
+ @chars = Chars::CharSet.new(*@integers)
42
+
43
+ @integers.each do |i|
44
+ @chars.include?(i).should == true
45
+ end
46
+ end
47
+
48
+ it "may be created with an Array of Integers" do
49
+ @chars = Chars::CharSet.new(@integers)
50
+
51
+ @integers.each do |i|
52
+ @chars.include?(i).should == true
53
+ end
54
+ end
55
+
56
+ it "may be created with a Range of Integers" do
57
+ @chars = Chars::CharSet.new(@integer_range)
58
+
59
+ @integers.each do |i|
60
+ @chars.include?(i).should == true
61
+ end
62
+ end
63
+
64
+ it "should include Strings" do
65
+ @char_set.include_char?('A').should == true
66
+ end
67
+
68
+ it "should include Integers" do
69
+ @char_set.include?(0x41).should == true
70
+ end
71
+
72
+ it "should be able to select bytes" do
73
+ @sub_chars = @char_set.select_bytes { |c| c <= 0x42 }
74
+
75
+ @sub_chars.should == [0x41, 0x42]
76
+ end
77
+
78
+ it "should be able to select chars" do
79
+ @sub_chars = @char_set.select_chars { |c| c <= 'B' }
80
+
81
+ @sub_chars.should == ['A', 'B']
82
+ end
83
+
84
+ it "should return a random byte" do
85
+ @char_set.include?(@char_set.random_byte).should == true
86
+ end
87
+
88
+ it "should return a random char" do
89
+ @char_set.include_char?(@char_set.random_char).should == true
90
+ end
91
+
92
+ it "should iterate over n random bytes" do
93
+ @char_set.each_random_byte(10) do |b|
94
+ @char_set.include?(b).should == true
95
+ end
96
+ end
97
+
98
+ it "should iterate over n random chars" do
99
+ @char_set.each_random_char(10) do |c|
100
+ @char_set.include_char?(c).should == true
101
+ end
102
+ end
103
+
104
+ it "should return a random Array of bytes" do
105
+ bytes = @char_set.random_bytes(10)
106
+
107
+ bytes.each do |b|
108
+ @char_set.include?(b).should == true
109
+ end
110
+ end
111
+
112
+ it "should return a random Array of chars" do
113
+ chars = @char_set.random_chars(10)
114
+
115
+ chars.each do |c|
116
+ @char_set.include_char?(c).should == true
117
+ end
118
+ end
119
+
120
+ it "should return a random Array of bytes with a varying length" do
121
+ bytes = @char_set.random_bytes(5..10)
122
+
123
+ bytes.length.between?(5, 10).should == true
124
+ bytes.each do |b|
125
+ @char_set.include?(b).should == true
126
+ end
127
+ end
128
+
129
+ it "should return a random Array of chars with a varying length" do
130
+ chars = @char_set.random_chars(5..10)
131
+
132
+ chars.length.between?(5, 10).should == true
133
+ chars.each do |c|
134
+ @char_set.include_char?(c).should == true
135
+ end
136
+ end
137
+
138
+ it "should return a random String of chars" do
139
+ @char_set.random_string(10).each_byte do |b|
140
+ @char_set.include?(b).should == true
141
+ end
142
+ end
143
+
144
+ it "should return a random String of chars with a varying length" do
145
+ string = @char_set.random_string(5..10)
146
+
147
+ string.length.between?(5, 10)
148
+ string.each_byte do |b|
149
+ @char_set.include?(b).should == true
150
+ end
151
+ end
152
+
153
+ it "should be able to be compared with another set of chars" do
154
+ (@char_set == Chars::CharSet['A', 'B', 'C']).should == true
155
+ (@char_set == Chars::CharSet['A', 'C', 'B']).should == true
156
+ end
157
+
158
+ it "should be able to be unioned with another set of chars" do
159
+ super_set = (@char_set | Chars::CharSet['D'])
160
+
161
+ super_set.class.should == Chars::CharSet
162
+ super_set.should == Chars::CharSet['A', 'B', 'C', 'D']
163
+ end
164
+
165
+ it "should be able to be removed from another set of chars" do
166
+ sub_set = (@char_set - Chars::CharSet['B'])
167
+
168
+ sub_set.class.should == Chars::CharSet
169
+ sub_set.subset?(@char_set).should == true
170
+ end
171
+
172
+ it "should determine if a String is made up of the characters from the char set" do
173
+ (@char_set =~ "AABCBAA").should == true
174
+ (@char_set =~ "AADDEE").should_not == true
175
+ end
176
+ end
177
+ end