ronin 1.0.0.pre3 → 1.0.0.pre4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. data/COPYING.txt +623 -288
  2. data/ChangeLog.md +21 -2
  3. data/Gemfile +5 -12
  4. data/README.md +6 -7
  5. data/gemspec.yml +3 -3
  6. data/lib/ronin.rb +6 -7
  7. data/lib/ronin/address.rb +18 -7
  8. data/lib/ronin/arch.rb +6 -7
  9. data/lib/ronin/author.rb +6 -7
  10. data/lib/ronin/bootstrap.rb +6 -8
  11. data/lib/ronin/cached_file.rb +6 -7
  12. data/lib/ronin/campaign.rb +10 -11
  13. data/lib/ronin/class_methods.rb +6 -7
  14. data/lib/ronin/config.rb +6 -7
  15. data/lib/ronin/credential.rb +19 -8
  16. data/lib/ronin/database.rb +6 -7
  17. data/lib/ronin/database/database.rb +8 -9
  18. data/lib/ronin/database/exceptions.rb +6 -7
  19. data/lib/ronin/database/exceptions/invalid_config.rb +6 -7
  20. data/lib/ronin/database/exceptions/unknown_repository.rb +6 -7
  21. data/lib/ronin/database/migrations.rb +6 -7
  22. data/lib/ronin/database/migrations/create_addresses_table.rb +6 -7
  23. data/lib/ronin/database/migrations/create_arches_table.rb +6 -7
  24. data/lib/ronin/database/migrations/create_authors_table.rb +6 -7
  25. data/lib/ronin/database/migrations/create_cached_files_table.rb +6 -7
  26. data/lib/ronin/database/migrations/create_campaigns_table.rb +8 -7
  27. data/lib/ronin/database/migrations/create_countries_table.rb +6 -7
  28. data/lib/ronin/database/migrations/create_credentials_table.rb +16 -10
  29. data/lib/ronin/database/migrations/create_email_addresses_table.rb +10 -11
  30. data/lib/ronin/database/migrations/create_host_name_ip_addresses_table.rb +14 -9
  31. data/lib/ronin/database/migrations/create_ip_address_mac_addresses_table.rb +14 -9
  32. data/lib/ronin/database/migrations/create_licenses_table.rb +6 -7
  33. data/lib/ronin/database/migrations/create_open_ports_table.rb +11 -7
  34. data/lib/ronin/database/migrations/create_organizations_table.rb +8 -7
  35. data/lib/ronin/database/migrations/create_os_guesses_table.rb +13 -9
  36. data/lib/ronin/database/migrations/create_os_table.rb +6 -7
  37. data/lib/ronin/database/migrations/create_passwords_table.rb +6 -7
  38. data/lib/ronin/database/migrations/create_ports_table.rb +6 -7
  39. data/lib/ronin/database/migrations/create_proxies_table.rb +6 -7
  40. data/lib/ronin/database/migrations/create_remote_files_table.rb +6 -7
  41. data/lib/ronin/database/migrations/create_repositories_table.rb +6 -7
  42. data/lib/ronin/database/migrations/create_services_table.rb +6 -8
  43. data/lib/ronin/database/migrations/create_softwares_table.rb +6 -7
  44. data/lib/ronin/database/migrations/create_taggings_table.rb +6 -7
  45. data/lib/ronin/database/migrations/create_tags_table.rb +6 -7
  46. data/lib/ronin/database/migrations/create_targets_table.rb +7 -8
  47. data/lib/ronin/database/migrations/create_url_query_params_table.rb +6 -7
  48. data/lib/ronin/database/migrations/create_url_schemes_table.rb +6 -7
  49. data/lib/ronin/database/migrations/create_urls_table.rb +16 -9
  50. data/lib/ronin/database/migrations/create_user_names_table.rb +6 -7
  51. data/lib/ronin/database/migrations/create_vendors_table.rb +6 -7
  52. data/lib/ronin/database/migrations/exceptions.rb +6 -7
  53. data/lib/ronin/database/migrations/exceptions/duplicate_migration.rb +6 -7
  54. data/lib/ronin/database/migrations/exceptions/unknown_migration.rb +6 -7
  55. data/lib/ronin/database/migrations/graph.rb +19 -0
  56. data/lib/ronin/database/migrations/migration.rb +6 -7
  57. data/lib/ronin/database/migrations/migrations.rb +6 -7
  58. data/lib/ronin/email_address.rb +34 -13
  59. data/lib/ronin/engine.rb +6 -7
  60. data/lib/ronin/engine/buildable.rb +6 -7
  61. data/lib/ronin/engine/class_methods.rb +6 -7
  62. data/lib/ronin/engine/deployable.rb +6 -7
  63. data/lib/ronin/engine/engine.rb +6 -7
  64. data/lib/ronin/engine/exceptions.rb +6 -7
  65. data/lib/ronin/engine/exceptions/deploy_failed.rb +6 -7
  66. data/lib/ronin/engine/exceptions/not_built.rb +6 -7
  67. data/lib/ronin/engine/exceptions/verification_failed.rb +6 -7
  68. data/lib/ronin/engine/instance_methods.rb +6 -7
  69. data/lib/ronin/engine/verifiable.rb +6 -7
  70. data/lib/ronin/environment.rb +11 -7
  71. data/lib/ronin/exceptions.rb +6 -7
  72. data/lib/ronin/exceptions/duplicate_repository.rb +6 -7
  73. data/lib/ronin/exceptions/repository_not_found.rb +6 -7
  74. data/lib/ronin/host_name.rb +40 -22
  75. data/lib/ronin/host_name_ip_address.rb +11 -9
  76. data/lib/ronin/installation.rb +6 -7
  77. data/lib/ronin/ip_address.rb +41 -33
  78. data/lib/ronin/ip_address_mac_address.rb +11 -9
  79. data/lib/ronin/license.rb +6 -7
  80. data/lib/ronin/mac_address.rb +8 -13
  81. data/lib/ronin/model.rb +6 -7
  82. data/lib/ronin/model/cacheable.rb +6 -7
  83. data/lib/ronin/model/cacheable/cacheable.rb +6 -7
  84. data/lib/ronin/model/cacheable/class_methods.rb +6 -7
  85. data/lib/ronin/model/class_methods.rb +6 -7
  86. data/lib/ronin/model/has_authors.rb +6 -7
  87. data/lib/ronin/model/has_authors/class_methods.rb +8 -9
  88. data/lib/ronin/model/has_authors/has_authors.rb +6 -7
  89. data/lib/ronin/model/has_description.rb +6 -7
  90. data/lib/ronin/model/has_description/class_methods.rb +7 -8
  91. data/lib/ronin/model/has_description/has_description.rb +6 -7
  92. data/lib/ronin/model/has_license.rb +6 -7
  93. data/lib/ronin/model/has_license/class_methods.rb +7 -8
  94. data/lib/ronin/model/has_license/has_license.rb +6 -7
  95. data/lib/ronin/model/has_name.rb +6 -7
  96. data/lib/ronin/model/has_name/class_methods.rb +7 -12
  97. data/lib/ronin/model/has_name/has_name.rb +6 -7
  98. data/lib/ronin/model/has_title.rb +6 -7
  99. data/lib/ronin/model/has_title/class_methods.rb +7 -8
  100. data/lib/ronin/model/has_title/has_title.rb +6 -7
  101. data/lib/ronin/model/has_unique_name.rb +18 -7
  102. data/lib/ronin/model/has_version.rb +6 -7
  103. data/lib/ronin/model/has_version/class_methods.rb +7 -8
  104. data/lib/ronin/model/has_version/has_version.rb +6 -7
  105. data/lib/ronin/model/model.rb +6 -7
  106. data/lib/ronin/model/types.rb +6 -7
  107. data/lib/ronin/model/types/description.rb +6 -7
  108. data/lib/ronin/network/mixins.rb +11 -13
  109. data/lib/ronin/network/mixins/esmtp.rb +11 -13
  110. data/lib/ronin/network/mixins/http.rb +11 -13
  111. data/lib/ronin/network/mixins/imap.rb +11 -13
  112. data/lib/ronin/network/mixins/pop3.rb +11 -13
  113. data/lib/ronin/network/mixins/smtp.rb +11 -13
  114. data/lib/ronin/network/mixins/tcp.rb +11 -13
  115. data/lib/ronin/network/mixins/telnet.rb +11 -13
  116. data/lib/ronin/network/mixins/udp.rb +11 -13
  117. data/lib/ronin/open_port.rb +11 -11
  118. data/lib/ronin/organization.rb +8 -9
  119. data/lib/ronin/os.rb +6 -7
  120. data/lib/ronin/os_guess.rb +14 -12
  121. data/lib/ronin/password.rb +18 -7
  122. data/lib/ronin/port.rb +18 -7
  123. data/lib/ronin/proxy.rb +6 -7
  124. data/lib/ronin/proxy_credential.rb +6 -7
  125. data/lib/ronin/remote_file.rb +13 -11
  126. data/lib/ronin/repository.rb +8 -12
  127. data/lib/ronin/ronin.rb +6 -7
  128. data/lib/ronin/service.rb +8 -23
  129. data/lib/ronin/service_credential.rb +6 -7
  130. data/lib/ronin/software.rb +6 -7
  131. data/lib/ronin/spec/database.rb +6 -7
  132. data/lib/ronin/spec/ui/output.rb +6 -7
  133. data/lib/ronin/target.rb +11 -9
  134. data/lib/ronin/tcp_port.rb +6 -7
  135. data/lib/ronin/udp_port.rb +6 -7
  136. data/lib/ronin/ui.rb +6 -7
  137. data/lib/ronin/ui/cli.rb +6 -7
  138. data/lib/ronin/ui/cli/cli.rb +6 -7
  139. data/lib/ronin/ui/cli/command.rb +6 -7
  140. data/lib/ronin/ui/cli/commands.rb +6 -7
  141. data/lib/ronin/ui/cli/commands/campaigns.rb +6 -7
  142. data/lib/ronin/ui/cli/commands/console.rb +7 -8
  143. data/lib/ronin/ui/cli/commands/creds.rb +6 -7
  144. data/lib/ronin/ui/cli/commands/database.rb +6 -7
  145. data/lib/ronin/ui/cli/commands/emails.rb +6 -7
  146. data/lib/ronin/ui/cli/commands/exec.rb +6 -7
  147. data/lib/ronin/ui/cli/commands/help.rb +6 -7
  148. data/lib/ronin/ui/cli/commands/hosts.rb +10 -9
  149. data/lib/ronin/ui/cli/commands/ips.rb +10 -9
  150. data/lib/ronin/ui/cli/commands/repos.rb +6 -7
  151. data/lib/ronin/ui/cli/commands/urls.rb +6 -7
  152. data/lib/ronin/ui/cli/engine_command.rb +6 -7
  153. data/lib/ronin/ui/cli/exceptions.rb +6 -7
  154. data/lib/ronin/ui/cli/exceptions/unknown_command.rb +6 -7
  155. data/lib/ronin/ui/cli/model_command.rb +6 -7
  156. data/lib/ronin/ui/console.rb +8 -12
  157. data/lib/ronin/ui/hexdump.rb +6 -7
  158. data/lib/ronin/ui/hexdump/extensions.rb +6 -7
  159. data/lib/ronin/ui/hexdump/extensions/file.rb +6 -7
  160. data/lib/ronin/ui/hexdump/extensions/kernel.rb +6 -7
  161. data/lib/ronin/ui/hexdump/hexdump.rb +13 -7
  162. data/lib/ronin/ui/output.rb +6 -7
  163. data/lib/ronin/ui/output/helpers.rb +6 -7
  164. data/lib/ronin/ui/output/output.rb +6 -7
  165. data/lib/ronin/ui/output/terminal.rb +6 -7
  166. data/lib/ronin/ui/output/terminal/color.rb +6 -7
  167. data/lib/ronin/ui/output/terminal/raw.rb +6 -7
  168. data/lib/ronin/ui/shell.rb +6 -7
  169. data/lib/ronin/url.rb +123 -30
  170. data/lib/ronin/url_query_param.rb +32 -7
  171. data/lib/ronin/url_scheme.rb +6 -7
  172. data/lib/ronin/user_name.rb +6 -7
  173. data/lib/ronin/vendor.rb +6 -7
  174. data/lib/ronin/version.rb +7 -8
  175. data/lib/ronin/web_credential.rb +52 -8
  176. data/spec/arch_spec.rb +7 -0
  177. data/spec/author_spec.rb +1 -1
  178. data/spec/campaign_spec.rb +1 -1
  179. data/spec/credential_spec.rb +33 -0
  180. data/spec/database_spec.rb +23 -0
  181. data/spec/email_address_spec.rb +15 -0
  182. data/spec/engine/buildable_spec.rb +2 -2
  183. data/spec/engine/deployable_spec.rb +2 -2
  184. data/spec/host_name_spec.rb +20 -0
  185. data/spec/ip_address.rb +20 -3
  186. data/spec/model/cacheable_spec.rb +1 -1
  187. data/spec/model/has_description_spec.rb +1 -1
  188. data/spec/os_spec.rb +26 -0
  189. data/spec/password_spec.rb +4 -0
  190. data/spec/port_spec.rb +43 -0
  191. data/spec/repository_spec.rb +10 -10
  192. data/spec/service_spec.rb +18 -0
  193. data/spec/software_spec.rb +15 -5
  194. data/spec/url_query_param_spec.rb +30 -0
  195. data/spec/url_scheme_spec.rb +18 -0
  196. data/spec/url_spec.rb +54 -37
  197. metadata +18 -9
  198. data/lib/ronin/ui/async_console.rb +0 -130
data/spec/ip_address.rb CHANGED
@@ -5,6 +5,8 @@ describe IPAddress do
5
5
  let(:example_domain) { 'www.example.com' }
6
6
  let(:example_ip) { '192.0.32.10' }
7
7
 
8
+ subject { IPAddress.new(:address => example_ip) }
9
+
8
10
  it "should require an address" do
9
11
  ip = IPAddress.new
10
12
 
@@ -23,6 +25,14 @@ describe IPAddress do
23
25
  ips[0].address.should == example_ip
24
26
  end
25
27
 
28
+ it "should associate the IP addresses with the original host name" do
29
+ ips = subject.lookup(example_domain)
30
+
31
+ ips.each do |ip|
32
+ ip.host_names[0].address.should == example_domain
33
+ end
34
+ end
35
+
26
36
  it "should return an empty Array for unknown domain names" do
27
37
  ips = subject.lookup(bad_domain)
28
38
 
@@ -34,13 +44,20 @@ describe IPAddress do
34
44
  let(:bad_ip) { '0.0.0.0' }
35
45
 
36
46
  it "should reverse lookup the host-name for an IP Address" do
37
- ip = IPAddress.new(:address => example_ip)
38
- host_names = ip.lookup!
47
+ host_names = subject.lookup!
39
48
 
40
49
  host_names.should_not be_empty
41
50
  host_names[0].address.should == example_domain
42
51
  end
43
52
 
53
+ it "should associate the host names with the original IP address" do
54
+ host_names = subject.lookup!
55
+
56
+ host_names.each do |host_name|
57
+ host_name.ip_addresses[0].address.should == subject
58
+ end
59
+ end
60
+
44
61
  it "should return an empty Array for unknown domain names" do
45
62
  ip = IPAddress.new(:address => bad_ip)
46
63
  host_names = ip.lookup!
@@ -49,7 +66,7 @@ describe IPAddress do
49
66
  end
50
67
  end
51
68
 
52
- describe "version" do
69
+ describe "#version" do
53
70
  let(:ipv4) { IPAddress.new(:address => '192.168.1.1') }
54
71
  let(:ipv6) { IPAddress.new(:address => '::1') }
55
72
 
@@ -56,7 +56,7 @@ describe Model::Cacheable do
56
56
  end
57
57
  end
58
58
 
59
- describe "cached" do
59
+ context "previously cached" do
60
60
  subject { CacheableModel.first }
61
61
 
62
62
  it "should have a cached_file resource" do
@@ -14,7 +14,7 @@ describe Model::HasDescription do
14
14
  subject.properties.should be_named(:description)
15
15
  end
16
16
 
17
- describe "description" do
17
+ describe "#description" do
18
18
  let(:resource) { DescribedModel.new }
19
19
 
20
20
  it "should allow the setting of the description" do
data/spec/os_spec.rb CHANGED
@@ -2,6 +2,10 @@ require 'spec_helper'
2
2
  require 'ronin/os'
3
3
 
4
4
  describe OS do
5
+ subject do
6
+ OS.new(:name => 'Linux', :version => '2.6.11')
7
+ end
8
+
5
9
  it "should require a name" do
6
10
  os = OS.new
7
11
  os.should_not be_valid
@@ -17,4 +21,26 @@ describe OS do
17
21
  it "should provide methods for creating OSes with versions" do
18
22
  OS.linux('2.6.11').should be_valid
19
23
  end
24
+
25
+ describe "#to_s" do
26
+ it "should convert both the name and version" do
27
+ os = OS.new(:name => 'Linux', :version => '2.6.23')
28
+
29
+ os.to_s.should == 'Linux 2.6.23'
30
+ end
31
+
32
+ it "should convert just the name if there is no version" do
33
+ os = OS.new(:name => 'Linux')
34
+
35
+ os.to_s.should == os.name
36
+ end
37
+ end
38
+
39
+ it "should implicitly splat the name and version" do
40
+ os = OS.new(:name => 'Linux', :version => '2.6.23')
41
+ name, version = os
42
+
43
+ name.should == os.name
44
+ version.should == os.version
45
+ end
20
46
  end
@@ -32,4 +32,8 @@ describe Password do
32
32
  digest.should == Digest::SHA1.hexdigest(password + salt)
33
33
  end
34
34
  end
35
+
36
+ it "should be convertable to a String" do
37
+ subject.to_s.should == password
38
+ end
35
39
  end
data/spec/port_spec.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'ronin/port'
3
+
4
+ describe Port do
5
+ let(:protocol) { 'tcp' }
6
+ let(:number) { 80 }
7
+
8
+ before(:all) do
9
+ @port = Port.create(:protocol => protocol, :number => number)
10
+ end
11
+
12
+ it "should require a protocol" do
13
+ port = Port.new(:number => 1111)
14
+
15
+ port.should_not be_valid
16
+ end
17
+
18
+ it "should require a port number" do
19
+ port = Port.new(:protocol => 'tcp')
20
+
21
+ port.should_not be_valid
22
+ end
23
+
24
+ it "should only allow 'tcp' and 'udp' as protocols" do
25
+ port = Port.new(:protocol => 'foo', :number => 1111)
26
+
27
+ port.should_not be_valid
28
+ end
29
+
30
+ it "should require unique protocol/port-number combinations" do
31
+ port = Port.new(:protocol => protocol, :number => number)
32
+
33
+ port.should_not be_valid
34
+ end
35
+
36
+ it "should be convertable to an Integer" do
37
+ @port.to_i.should == number
38
+ end
39
+
40
+ it "should be convertable to a String" do
41
+ @port.to_s.should == "#{number}/#{protocol}"
42
+ end
43
+ end
@@ -82,7 +82,7 @@ describe Repository do
82
82
  end
83
83
  end
84
84
 
85
- describe "domain" do
85
+ describe "#domain" do
86
86
  it "should be considered local for 'localhost' domains" do
87
87
  hello = repository('hello')
88
88
 
@@ -98,7 +98,7 @@ describe Repository do
98
98
  end
99
99
  end
100
100
 
101
- describe "initialize" do
101
+ describe "#initialize" do
102
102
  it "should default the 'name' property to the name of the Repository directory" do
103
103
  repo = subject.new(
104
104
  :path => File.join(Helpers::Repositories::DIR,'hello')
@@ -117,7 +117,7 @@ describe Repository do
117
117
  end
118
118
  end
119
119
 
120
- describe "initialize_metadata" do
120
+ describe "#initialize_metadata" do
121
121
  subject { repository('hello') }
122
122
 
123
123
  it "should load the title" do
@@ -149,7 +149,7 @@ describe Repository do
149
149
  end
150
150
  end
151
151
 
152
- describe "activate!" do
152
+ describe "#activate!" do
153
153
  subject { repository('hello') }
154
154
 
155
155
  before(:all) do
@@ -165,7 +165,7 @@ describe Repository do
165
165
  end
166
166
  end
167
167
 
168
- describe "deactivate!" do
168
+ describe "#deactivate!" do
169
169
  subject { repository('hello') }
170
170
 
171
171
  before(:all) do
@@ -179,7 +179,7 @@ describe Repository do
179
179
  end
180
180
  end
181
181
 
182
- describe "cache_paths" do
182
+ describe "#cache_paths" do
183
183
  subject { repository('test1') }
184
184
 
185
185
  it "should list the contents of the 'cache/' directory" do
@@ -195,7 +195,7 @@ describe Repository do
195
195
  end
196
196
  end
197
197
 
198
- describe "cached_files" do
198
+ describe "#cached_files" do
199
199
  before(:all) do
200
200
  CacheableModel.auto_migrate!
201
201
  end
@@ -203,7 +203,7 @@ describe Repository do
203
203
  let(:test1) { repository('test1') }
204
204
  let(:test2) { repository('test2') }
205
205
 
206
- describe "cache_files!" do
206
+ describe "#cache_files!" do
207
207
  before(:all) do
208
208
  test1.cache_files!
209
209
  test2.cache_files!
@@ -251,7 +251,7 @@ describe Repository do
251
251
  end
252
252
  end
253
253
 
254
- describe "sync_cached_files!" do
254
+ describe "#sync_cached_files!" do
255
255
  before(:all) do
256
256
  test1.cache_files!
257
257
  test2.cache_files!
@@ -278,7 +278,7 @@ describe Repository do
278
278
  end
279
279
  end
280
280
 
281
- describe "clean_cached_files!" do
281
+ describe "#clean_cached_files!" do
282
282
  before(:all) do
283
283
  test1.clean_cached_files!
284
284
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'ronin/service'
3
+
4
+ describe Service do
5
+ before(:all) { @service = Service.create(:name => 'Apache') }
6
+
7
+ it "should require a name" do
8
+ service = Service.new
9
+
10
+ service.should_not be_valid
11
+ end
12
+
13
+ it "should require a unique name" do
14
+ service = Service.new(:name => 'Apache')
15
+
16
+ service.should_not be_valid
17
+ end
18
+ end
@@ -13,11 +13,21 @@ describe Software do
13
13
  software.should be_valid
14
14
  end
15
15
 
16
- it "should be convertable to a String" do
17
- software = Software.new(:name => 'Test', :version => '0.1.0')
18
- software.to_s.should == 'Test 0.1.0'
16
+ describe "#to_s" do
17
+ it "should be convertable to a String" do
18
+ software = Software.new(
19
+ :name => 'Test',
20
+ :version => '0.1.0',
21
+ :vendor => {:name => 'TestCo'}
22
+ )
19
23
 
20
- software.vendor = Vendor.new(:name => 'TestCo')
21
- software.to_s.should == 'TestCo Test 0.1.0'
24
+ software.to_s.should == 'TestCo Test 0.1.0'
25
+ end
26
+
27
+ it "should ignore the missing vendor information" do
28
+ software = Software.new(:name => 'Test', :version => '0.1.0')
29
+
30
+ software.to_s.should == 'Test 0.1.0'
31
+ end
22
32
  end
23
33
  end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'ronin/url_query_param'
3
+
4
+ describe URLQueryParam do
5
+ it "should require a name" do
6
+ param = URLQueryParam.new
7
+
8
+ param.should_not be_valid
9
+ end
10
+
11
+ describe "#to_s" do
12
+ it "should dump a name and a value into a String" do
13
+ param = URLQueryParam.new(:name => 'foo', :value => 'bar')
14
+
15
+ param.to_s.should == "foo=bar"
16
+ end
17
+
18
+ it "should ignore empty or nil values" do
19
+ param = URLQueryParam.new(:name => 'foo')
20
+
21
+ param.to_s.should == "foo="
22
+ end
23
+
24
+ it "should escape special characters" do
25
+ param = URLQueryParam.new(:name => 'foo', :value => 'bar baz')
26
+
27
+ param.to_s.should == "foo=bar%20baz"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'ronin/url_scheme'
3
+
4
+ describe URLScheme do
5
+ before(:all) { @scheme = URLScheme.create(:name => 'http') }
6
+
7
+ it "should require a name" do
8
+ scheme = URLScheme.new
9
+
10
+ scheme.should_not be_valid
11
+ end
12
+
13
+ it "should require a unique name" do
14
+ scheme = URLScheme.new(:name => 'http')
15
+
16
+ scheme.should_not be_valid
17
+ end
18
+ end
data/spec/url_spec.rb CHANGED
@@ -11,8 +11,8 @@ describe URL do
11
11
  let(:query_string) { 'q=1' }
12
12
  let(:fragment) { 'frag' }
13
13
 
14
- let(:uri) do
15
- URI::HTTPS.build(
14
+ before(:all) do
15
+ @uri = URI::HTTPS.build(
16
16
  :scheme => scheme,
17
17
  :host => host_name,
18
18
  :port => port,
@@ -20,12 +20,15 @@ describe URL do
20
20
  :query => query_string,
21
21
  :fragment => fragment
22
22
  )
23
- end
24
-
25
- it "should have a default path" do
26
- url = URL.new
27
23
 
28
- url.path.should == ''
24
+ @url = URL.create(
25
+ :scheme => {:name => scheme},
26
+ :host_name => {:address => host_name},
27
+ :port => {:number => port},
28
+ :path => path,
29
+ :query_string => query_string,
30
+ :fragment => fragment
31
+ )
29
32
  end
30
33
 
31
34
  it "should have a host String" do
@@ -35,77 +38,91 @@ describe URL do
35
38
  end
36
39
 
37
40
  it "should be convertable to a String" do
38
- url = URL.new(
39
- :scheme => {:name => scheme},
40
- :host_name => {:address => host_name},
41
- :port => {:number => port},
42
- :path => path,
43
- :query_string => query_string,
44
- :fragment => fragment
45
- )
41
+ @url.to_s.should == @uri.to_s
42
+ end
43
+
44
+ describe "[]" do
45
+ it "should query URLs using URIs" do
46
+ URL[@uri].should == @url
47
+ end
46
48
 
47
- url.to_s.should == uri.to_s
49
+ it "should query URLs using Strings" do
50
+ URL[@uri.to_s].should == @url
51
+ end
52
+
53
+ it "should still treat Integer arguments as indexes" do
54
+ URL[0].should == @url
55
+ end
48
56
  end
49
57
 
50
58
  describe "from" do
51
- before(:all) do
52
- @url = URL.from(uri)
53
- end
59
+ subject { URL.from(@uri) }
54
60
 
55
61
  it "should parse URL schemes" do
56
- @url.scheme.should_not be_nil
57
- @url.scheme.name.should == scheme
62
+ subject.scheme.should_not be_nil
63
+ subject.scheme.name.should == scheme
58
64
  end
59
65
 
60
66
  it "should parse host names" do
61
- @url.host_name.address.should == host_name
67
+ subject.host_name.address.should == host_name
62
68
  end
63
69
 
64
70
  it "should parse port numbers" do
65
- @url.port.number.should == port
71
+ subject.port.number.should == port
66
72
  end
67
73
 
68
74
  it "should parse paths" do
69
- @url.path.should == path
75
+ subject.path.should == path
70
76
  end
71
77
 
72
78
  it "should parse query strings" do
73
- @url.query_string.should == query_string
79
+ subject.query_string.should == query_string
74
80
  end
75
81
 
76
82
  it "should parse URL fragments" do
77
- @url.fragment.should == fragment
83
+ subject.fragment.should == fragment
78
84
  end
79
- end
80
85
 
81
- describe "to_uri" do
82
- before(:all) do
83
- @url = URL.parse('https://www.example.com:8080/path?q=1#frag')
84
- @uri = @url.to_uri
86
+ it "should normalize the paths of HTTP URIs" do
87
+ uri = URI('http://www.example.com')
88
+ url = URL.from(uri)
89
+
90
+ url.path.should == '/'
85
91
  end
92
+ end
93
+
94
+ describe "#to_uri" do
95
+ subject { @url.to_uri }
86
96
 
87
97
  it "should convert the scheme" do
88
- @uri.scheme.should == scheme
98
+ subject.scheme.should == scheme
89
99
  end
90
100
 
91
101
  it "should convert the host name" do
92
- @uri.host.should == host_name
102
+ subject.host.should == host_name
93
103
  end
94
104
 
95
105
  it "should convert the port number" do
96
- @uri.port.should == port
106
+ subject.port.should == port
97
107
  end
98
108
 
99
109
  it "should convert the path" do
100
- @uri.path.should == path
110
+ subject.path.should == path
101
111
  end
102
112
 
103
113
  it "should convert the query string" do
104
- @uri.query.should == query_string
114
+ subject.query.should == query_string
115
+ end
116
+
117
+ it "should omit the query string if there are no query params" do
118
+ new_url = URL.parse('https://www.example.com:8080/path')
119
+ new_uri = new_url.to_uri
120
+
121
+ new_uri.query.should be_nil
105
122
  end
106
123
 
107
124
  it "should convert the fragment" do
108
- @uri.fragment.should == fragment
125
+ subject.fragment.should == fragment
109
126
  end
110
127
  end
111
128
  end