cloudfiles 1.4.10 → 1.4.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,83 +1,97 @@
1
1
  module CloudFiles
2
2
  class StorageObject
3
3
  # See COPYING for license information.
4
- # Copyright (c) 2009, Rackspace US, Inc.
5
-
4
+ # Copyright (c) 2011, Rackspace US, Inc.
5
+
6
6
  # Name of the object corresponding to the instantiated object
7
7
  attr_reader :name
8
-
9
- # Size of the object (in bytes)
10
- attr_reader :bytes
11
8
 
12
9
  # The parent CloudFiles::Container object
13
10
  attr_reader :container
14
11
 
15
- # Date of the object's last modification
16
- attr_reader :last_modified
17
-
18
- # ETag of the object data
19
- attr_reader :etag
20
-
21
- # Content type of the object data
22
- attr_reader :content_type
23
-
24
12
  # Builds a new CloudFiles::StorageObject in the current container. If force_exist is set, the object must exist or a
25
- # NoSuchObjectException will be raised. If not, an "empty" CloudFiles::StorageObject will be returned, ready for data
13
+ # CloudFiles::Exception::NoSuchObject Exception will be raised. If not, an "empty" CloudFiles::StorageObject will be returned, ready for data
26
14
  # via CloudFiles::StorageObject.write
27
- def initialize(container,objectname,force_exists=false,make_path=false)
15
+ def initialize(container, objectname, force_exists = false, make_path = false)
28
16
  if objectname.match(/\?/)
29
- raise SyntaxException, "Object #{objectname} contains an invalid character in the name (? not allowed)"
17
+ raise CloudFiles::Exception::Syntax, "Object #{objectname} contains an invalid character in the name (? not allowed)"
30
18
  end
31
19
  @container = container
32
20
  @containername = container.name
33
21
  @name = objectname
34
22
  @make_path = make_path
35
23
  @storagehost = self.container.connection.storagehost
36
- @storagepath = self.container.connection.storagepath+"/#{URI.encode(@containername).gsub(/&/,'%26')}/#{URI.encode(@name).gsub(/&/,'%26')}"
24
+ @storagepath = self.container.connection.storagepath + "/#{CloudFiles.escape @containername}/#{CloudFiles.escape @name}"
37
25
  @storageport = self.container.connection.storageport
38
26
  @storagescheme = self.container.connection.storagescheme
39
- if container.object_exists?(objectname)
40
- populate
41
- else
42
- raise NoSuchObjectException, "Object #{@name} does not exist" if force_exists
27
+ if force_exists
28
+ raise CloudFiles::Exception::NoSuchObject, "Object #{@name} does not exist" unless container.object_exists?(objectname)
43
29
  end
44
30
  end
45
-
46
- # Caches data about the CloudFiles::StorageObject for fast retrieval. This method is automatically called when the
47
- # class is initialized, but it can be called again if the data needs to be updated.
48
- def populate
49
- response = self.container.connection.cfreq("HEAD",@storagehost,@storagepath,@storageport,@storagescheme)
50
- raise NoSuchObjectException, "Object #{@name} does not exist" unless (response.code =~ /^20/)
51
- @bytes = response["content-length"]
52
- @last_modified = Time.parse(response["last-modified"])
53
- @etag = response["etag"]
54
- @content_type = response["content-type"]
55
- resphash = {}
56
- response.to_hash.select { |k,v| k.match(/^x-object-meta/) }.each { |x| resphash[x[0]] = x[1].to_s }
57
- @metadata = resphash
31
+
32
+ # Refreshes the object metadata
33
+ def refresh
34
+ @object_metadata = nil
58
35
  true
59
36
  end
60
- alias :refresh :populate
37
+ alias :populate :refresh
38
+
39
+ # Retrieves Metadata for the object
40
+ def object_metadata
41
+ @object_metadata ||= (
42
+ response = self.container.connection.cfreq("HEAD", @storagehost, @storagepath, @storageport, @storagescheme)
43
+ raise CloudFiles::Exception::NoSuchObject, "Object #{@name} does not exist" unless (response.code =~ /^20/)
44
+ resphash = {}
45
+ response.to_hash.select { |k,v| k.match(/^x-object-meta/) }.each { |x| resphash[x[0]] = x[1].to_s }
46
+ {
47
+ :bytes => response["content-length"],
48
+ :last_modified => Time.parse(response["last-modified"]),
49
+ :etag => response["etag"],
50
+ :content_type => response["content-type"],
51
+ :metadata => resphash
52
+ }
53
+ )
54
+ end
55
+
56
+ # Size of the object (in bytes)
57
+ def bytes
58
+ self.object_metadata[:bytes]
59
+ end
60
+
61
+ # Date of the object's last modification
62
+ def last_modified
63
+ self.object_metadata[:last_modified]
64
+ end
65
+
66
+ # ETag of the object data
67
+ def etag
68
+ self.object_metadata[:etag]
69
+ end
70
+
71
+ # Content type of the object data
72
+ def content_type
73
+ self.object_metadata[:content_type]
74
+ end
61
75
 
62
76
  # Retrieves the data from an object and stores the data in memory. The data is returned as a string.
63
77
  # Throws a NoSuchObjectException if the object doesn't exist.
64
78
  #
65
79
  # If the optional size and range arguments are provided, the call will return the number of bytes provided by
66
80
  # size, starting from the offset provided in offset.
67
- #
81
+ #
68
82
  # object.data
69
83
  # => "This is the text stored in the file"
70
- def data(size=-1,offset=0,headers = {})
84
+ def data(size = -1, offset = 0, headers = {})
71
85
  if size.to_i > 0
72
86
  range = sprintf("bytes=%d-%d", offset.to_i, (offset.to_i + size.to_i) - 1)
73
87
  headers['Range'] = range
74
88
  end
75
- response = self.container.connection.cfreq("GET",@storagehost,@storagepath,@storageport,@storagescheme,headers)
76
- raise NoSuchObjectException, "Object #{@name} does not exist" unless (response.code =~ /^20/)
89
+ response = self.container.connection.cfreq("GET", @storagehost, @storagepath, @storageport, @storagescheme, headers)
90
+ raise CloudFiles::Exception::NoSuchObject, "Object #{@name} does not exist" unless (response.code =~ /^20/)
77
91
  response.body
78
92
  end
79
93
 
80
- # Retrieves the data from an object and returns a stream that must be passed to a block. Throws a
94
+ # Retrieves the data from an object and returns a stream that must be passed to a block. Throws a
81
95
  # NoSuchObjectException if the object doesn't exist.
82
96
  #
83
97
  # If the optional size and range arguments are provided, the call will return the number of bytes provided by
@@ -87,16 +101,16 @@ module CloudFiles
87
101
  # object.data_stream do |chunk|
88
102
  # data += chunk
89
103
  # end
90
- #
104
+ #
91
105
  # data
92
106
  # => "This is the text stored in the file"
93
- def data_stream(size=-1,offset=0,headers = {},&block)
107
+ def data_stream(size = -1, offset = 0, headers = {}, &block)
94
108
  if size.to_i > 0
95
109
  range = sprintf("bytes=%d-%d", offset.to_i, (offset.to_i + size.to_i) - 1)
96
110
  headers['Range'] = range
97
111
  end
98
- self.container.connection.cfreq("GET",@storagehost,@storagepath,@storageport,@storagescheme,headers,nil) do |response|
99
- raise NoSuchObjectException, "Object #{@name} does not exist" unless (response.code == "200")
112
+ self.container.connection.cfreq("GET", @storagehost, @storagepath, @storageport, @storagescheme, headers, nil) do |response|
113
+ raise CloudFiles::Exception::NoSuchObject, "Object #{@name} does not exist" unless (response.code == "200")
100
114
  response.read_body(&block)
101
115
  end
102
116
  end
@@ -108,32 +122,32 @@ module CloudFiles
108
122
  # => {"ruby"=>"cool", "foo"=>"bar"}
109
123
  def metadata
110
124
  metahash = {}
111
- @metadata.each{|key, value| metahash[key.gsub(/x-object-meta-/,'').gsub(/\+\-/, ' ')] = URI.decode(value).gsub(/\+\-/, ' ')}
125
+ self.object_metadata[:metadata].each{ |key, value| metahash[key.gsub(/x-object-meta-/, '').gsub(/\+\-/, ' ')] = URI.decode(value).gsub(/\+\-/, ' ') }
112
126
  metahash
113
127
  end
114
-
128
+
115
129
  # Sets the metadata for an object. By passing a hash as an argument, you can set the metadata for an object.
116
130
  # However, setting metadata will overwrite any existing metadata for the object.
117
- #
131
+ #
118
132
  # Throws NoSuchObjectException if the object doesn't exist. Throws InvalidResponseException if the request
119
133
  # fails.
120
134
  def set_metadata(metadatahash)
121
135
  headers = {}
122
- metadatahash.each{|key, value| headers['X-Object-Meta-' + key.to_s.capitalize] = value.to_s}
123
- response = self.container.connection.cfreq("POST",@storagehost,@storagepath,@storageport,@storagescheme,headers)
124
- raise NoSuchObjectException, "Object #{@name} does not exist" if (response.code == "404")
125
- raise InvalidResponseException, "Invalid response code #{response.code}" unless (response.code == "202")
136
+ metadatahash.each{ |key, value| headers['X-Object-Meta-' + key.to_s.capitalize] = value.to_s }
137
+ response = self.container.connection.cfreq("POST", @storagehost, @storagepath, @storageport, @storagescheme, headers)
138
+ raise CloudFiles::Exception::NoSuchObject, "Object #{@name} does not exist" if (response.code == "404")
139
+ raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{response.code}" unless (response.code == "202")
126
140
  true
127
141
  end
128
-
142
+
129
143
  # Takes supplied data and writes it to the object, saving it. You can supply an optional hash of headers, including
130
144
  # Content-Type and ETag, that will be applied to the object.
131
145
  #
132
- # If you would rather stream the data in chunks, instead of reading it all into memory at once, you can pass an
146
+ # If you would rather stream the data in chunks, instead of reading it all into memory at once, you can pass an
133
147
  # IO object for the data, such as: object.write(open('/path/to/file.mp3'))
134
148
  #
135
149
  # You can compute your own MD5 sum and send it in the "ETag" header. If you provide yours, it will be compared to
136
- # the MD5 sum on the server side. If they do not match, the server will return a 422 status code and a MisMatchedChecksumException
150
+ # the MD5 sum on the server side. If they do not match, the server will return a 422 status code and a CloudFiles::Exception::MisMatchedChecksum Exception
137
151
  # will be raised. If you do not provide an MD5 sum as the ETag, one will be computed on the server side.
138
152
  #
139
153
  # Updates the container cache and returns true on success, raises exceptions if stuff breaks.
@@ -153,9 +167,9 @@ module CloudFiles
153
167
  # with no data (or, if you need to pass headers)
154
168
  #
155
169
  # object.write(nil,{'header' => 'value})
156
-
157
- def write(data=nil,headers={})
158
- raise SyntaxException, "No data or header updates supplied" if ((data.nil? && $stdin.tty?) and headers.empty?)
170
+
171
+ def write(data = nil, headers = {})
172
+ raise CloudFiles::Exception::Syntax, "No data or header updates supplied" if ((data.nil? && $stdin.tty?) and headers.empty?)
159
173
  if headers['Content-Type'].nil?
160
174
  type = MIME::Types.type_for(self.name).first.to_s
161
175
  if type.empty?
@@ -166,18 +180,20 @@ module CloudFiles
166
180
  end
167
181
  # If we're taking data from standard input, send that IO object to cfreq
168
182
  data = $stdin if (data.nil? && $stdin.tty? == false)
169
- response = self.container.connection.cfreq("PUT",@storagehost,"#{@storagepath}",@storageport,@storagescheme,headers,data)
183
+ response = self.container.connection.cfreq("PUT", @storagehost, "#{@storagepath}", @storageport, @storagescheme, headers, data)
170
184
  code = response.code
171
- raise InvalidResponseException, "Invalid content-length header sent" if (code == "412")
172
- raise MisMatchedChecksumException, "Mismatched etag" if (code == "422")
173
- raise InvalidResponseException, "Invalid response code #{code}" unless (code == "201")
185
+ raise CloudFiles::Exception::InvalidResponse, "Invalid content-length header sent" if (code == "412")
186
+ raise CloudFiles::Exception::MisMatchedChecksum, "Mismatched etag" if (code == "422")
187
+ raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{code}" unless (code =~ /^20./)
174
188
  make_path(File.dirname(self.name)) if @make_path == true
175
- self.populate
189
+ self.refresh
176
190
  true
177
191
  end
178
-
192
+
179
193
  # A convenience method to stream data into an object from a local file (or anything that can be loaded by Ruby's open method)
180
194
  #
195
+ # You can provide an optional hash of headers, in case you want to do something like set the Content-Type manually.
196
+ #
181
197
  # Throws an Errno::ENOENT if the file cannot be read.
182
198
  #
183
199
  # object.data
@@ -186,21 +202,23 @@ module CloudFiles
186
202
  # object.load_from_filename("/tmp/file.txt")
187
203
  # => true
188
204
  #
205
+ # object.load_from_filename("/home/rackspace/myfile.tmp", 'Content-Type' => 'text/plain')
206
+ #
189
207
  # object.data
190
208
  # => "This data was in the file /tmp/file.txt"
191
209
  #
192
210
  # object.load_from_filename("/tmp/nonexistent.txt")
193
211
  # => Errno::ENOENT: No such file or directory - /tmp/nonexistent.txt
194
- def load_from_filename(filename)
212
+ def load_from_filename(filename, headers = {})
195
213
  f = open(filename)
196
- self.write(f)
214
+ self.write(f, headers)
197
215
  f.close
198
216
  true
199
217
  end
200
218
 
201
219
  # A convenience method to stream data from an object into a local file
202
220
  #
203
- # Throws an Errno::ENOENT if the file cannot be opened for writing due to a path error,
221
+ # Throws an Errno::ENOENT if the file cannot be opened for writing due to a path error,
204
222
  # and Errno::EACCES if the file cannot be opened for writing due to permissions.
205
223
  #
206
224
  # object.data
@@ -222,7 +240,7 @@ module CloudFiles
222
240
  end
223
241
  true
224
242
  end
225
-
243
+
226
244
  # If the parent container is public (CDN-enabled), returns the CDN URL to this object. Otherwise, return nil
227
245
  #
228
246
  # public_object.public_url
@@ -231,26 +249,68 @@ module CloudFiles
231
249
  # private_object.public_url
232
250
  # => nil
233
251
  def public_url
234
- self.container.public? ? self.container.cdn_url + "/#{URI.encode(@name).gsub(/&/,'%26')}" : nil
252
+ self.container.public? ? self.container.cdn_url + "/#{CloudFiles.escape @name}" : nil
235
253
  end
236
254
 
255
+ # Copy this object to a new location (optionally in a new container)
256
+ #
257
+ # You must supply either a name for the new object or a container name, or both. If a :name is supplied without a :container,
258
+ # the object is copied within the current container. If the :container is specified with no :name, then the object is copied
259
+ # to the new container with its current name.
260
+ #
261
+ # object.copy(:name => "images/funny/lolcat.jpg", :container => "pictures")
262
+ #
263
+ # You may also supply a hash of headers in the :headers option. From there, you can set things like Content-Type, or other
264
+ # headers as available in the API document.
265
+ #
266
+ # object.copy(:name => 'newfile.tmp', :headers => {'Content-Type' => 'text/plain'})
267
+ #
268
+ # Returns the new CloudFiles::StorageObject for the copied item.
269
+ def copy(options = {})
270
+ raise CloudFiles::Exception::Syntax, "You must either provide the :container or the :name for this operation" unless (options[:container] || options[:name])
271
+ new_container = options[:container] || self.container.name
272
+ new_name = options[:name] || self.name
273
+ new_headers = options[:headers] || {}
274
+ raise CloudFiles::Exception::Syntax, "The :headers option must be a hash" unless new_headers.is_a?(Hash)
275
+ new_name.sub!(/^\//,'')
276
+ headers = {'X-Copy-From' => "#{self.container.name}/#{self.name}", 'Content-Type' => self.content_type.sub(/;.+/, '')}.merge(new_headers)
277
+ # , 'Content-Type' => self.content_type
278
+ new_path = self.container.connection.storagepath + "/#{CloudFiles.escape new_container}/#{CloudFiles.escape new_name}"
279
+ response = self.container.connection.cfreq("PUT", @storagehost, new_path, @storageport, @storagescheme, headers)
280
+ code = response.code
281
+ raise CloudFiles::Exception::InvalidResponse, "Invalid response code #{response.code}" unless (response.code =~ /^20/)
282
+ return CloudFiles::Container.new(self.container.connection, new_container).object(new_name)
283
+ end
284
+
285
+ # Takes the same options as the copy method, only it does a copy followed by a delete on the original object.
286
+ #
287
+ # Returns the new CloudFiles::StorageObject for the moved item. You should not attempt to use the old object after doing
288
+ # a move.
289
+ def move(options = {})
290
+ new_object = self.copy(options)
291
+ self.container.delete_object(self.name)
292
+ self.freeze
293
+ return new_object
294
+ end
295
+
296
+
237
297
  def to_s # :nodoc:
238
298
  @name
239
299
  end
240
-
300
+
241
301
  private
242
-
243
- def make_path(path) # :nodoc:
244
- if path == "." || path == "/"
245
- return
246
- else
247
- unless self.container.object_exists?(path)
248
- o = self.container.create_object(path)
249
- o.write(nil,{'Content-Type' => 'application/directory'})
302
+
303
+ def make_path(path) # :nodoc:
304
+ if path == "." || path == "/"
305
+ return
306
+ else
307
+ unless self.container.object_exists?(path)
308
+ o = self.container.create_object(path)
309
+ o.write(nil, {'Content-Type' => 'application/directory'})
310
+ end
311
+ make_path(File.dirname(path))
250
312
  end
251
- make_path(File.dirname(path))
252
313
  end
253
- end
254
314
 
255
315
  end
256
316
 
@@ -10,7 +10,7 @@ class CloudfilesAuthenticationTest < Test::Unit::TestCase
10
10
  server = mock(:use_ssl= => true, :verify_mode= => true, :start => true, :finish => true)
11
11
  server.stubs(:get).returns(response)
12
12
  CloudFiles::Authentication.any_instance.stubs(:get_server).returns(server)
13
- @connection = stub(:authuser => 'dummy_user', :authkey => 'dummy_key', :cdnmgmthost= => true, :cdnmgmtpath= => true, :cdnmgmtport= => true, :cdnmgmtscheme= => true, :storagehost= => true, :storagepath= => true, :storageport= => true, :storagescheme= => true, :authtoken= => true, :authok= => true, :snet? => false, :authurl => 'https://auth.api.rackspacecloud.com/v1.0')
13
+ @connection = stub(:authuser => 'dummy_user', :authkey => 'dummy_key', :cdnmgmthost= => true, :cdnmgmtpath= => true, :cdnmgmtport= => true, :cdnmgmtscheme= => true, :storagehost= => true, :storagepath= => true, :storageport= => true, :storagescheme= => true, :authtoken= => true, :authok= => true, :snet? => false, :auth_url => 'https://auth.api.rackspacecloud.com/v1.0')
14
14
  result = CloudFiles::Authentication.new(@connection)
15
15
  assert_equal result.class, CloudFiles::Authentication
16
16
  end
@@ -21,7 +21,7 @@ class CloudfilesAuthenticationTest < Test::Unit::TestCase
21
21
  server = mock(:use_ssl= => true, :verify_mode= => true, :start => true, :finish => true)
22
22
  server.stubs(:get).returns(response)
23
23
  CloudFiles::Authentication.any_instance.stubs(:get_server).returns(server)
24
- @connection = stub(:authuser => 'dummy_user', :authkey => 'dummy_key', :cdnmgmthost= => true, :cdnmgmtpath= => true, :cdnmgmtport= => true, :cdnmgmtscheme= => true, :storagehost= => true, :storagepath= => true, :storageport= => true, :storagescheme= => true, :authtoken= => true, :authok= => true, :snet? => true, :authurl => 'https://auth.api.rackspacecloud.com/v1.0')
24
+ @connection = stub(:authuser => 'dummy_user', :authkey => 'dummy_key', :cdnmgmthost= => true, :cdnmgmtpath= => true, :cdnmgmtport= => true, :cdnmgmtscheme= => true, :storagehost= => true, :storagepath= => true, :storageport= => true, :storagescheme= => true, :authtoken= => true, :authok= => true, :snet? => true, :auth_url => 'https://auth.api.rackspacecloud.com/v1.0')
25
25
  result = CloudFiles::Authentication.new(@connection)
26
26
  assert_equal result.class, CloudFiles::Authentication
27
27
  end
@@ -32,16 +32,16 @@ class CloudfilesAuthenticationTest < Test::Unit::TestCase
32
32
  server = mock(:use_ssl= => true, :verify_mode= => true, :start => true)
33
33
  server.stubs(:get).returns(response)
34
34
  CloudFiles::Authentication.any_instance.stubs(:get_server).returns(server)
35
- @connection = stub(:authuser => 'bad_user', :authkey => 'bad_key', :authok= => true, :authtoken= => true, :authurl => 'https://auth.api.rackspacecloud.com/v1.0')
36
- assert_raises(AuthenticationException) do
35
+ @connection = stub(:authuser => 'bad_user', :authkey => 'bad_key', :authok= => true, :authtoken= => true, :auth_url => 'https://auth.api.rackspacecloud.com/v1.0')
36
+ assert_raises(CloudFiles::Exception::Authentication) do
37
37
  result = CloudFiles::Authentication.new(@connection)
38
38
  end
39
39
  end
40
40
 
41
41
  def test_bad_hostname
42
- Net::HTTP.stubs(:new).raises(ConnectionException)
43
- @connection = stub(:authuser => 'bad_user', :authkey => 'bad_key', :authok= => true, :authtoken= => true, :authurl => 'https://auth.api.rackspacecloud.com/v1.0')
44
- assert_raises(ConnectionException) do
42
+ Net::HTTP.stubs(:new).raises(CloudFiles::Exception::Connection)
43
+ @connection = stub(:proxy_host => nil, :proxy_port => nil, :authuser => 'bad_user', :authkey => 'bad_key', :authok= => true, :authtoken= => true, :auth_url => 'https://auth.api.rackspacecloud.com/v1.0')
44
+ assert_raises(CloudFiles::Exception::Connection) do
45
45
  result = CloudFiles::Authentication.new(@connection)
46
46
  end
47
47
  end
@@ -83,8 +83,8 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
83
83
  end
84
84
 
85
85
  def test_net_http_raises_connection_exception
86
- Net::HTTP.expects(:new).raises(ConnectionException)
87
- assert_raises(ConnectionException) do
86
+ Net::HTTP.expects(:new).raises(CloudFiles::Exception::Connection)
87
+ assert_raises(CloudFiles::Exception::Connection) do
88
88
  response = @connection.cfreq("GET", "test.server.example", "/dummypath", "80", "http")
89
89
  end
90
90
  end
@@ -118,8 +118,9 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
118
118
  server = stub(:use_ssl= => true, :verify_mode= => true, :start => true)
119
119
  server.stubs(:finish).returns(true)
120
120
  server.stubs(:request).raises(EOFError)
121
+ CloudFiles::Connection.any_instance.stubs(:get_info).returns({:bytes => @bytes, :count => @count})
121
122
  Net::HTTP.stubs(:new).returns(server)
122
- assert_raises(ConnectionException) do
123
+ assert_raises(CloudFiles::Exception::Connection) do
123
124
  response = @connection.cfreq("GET", "test.server.example", "/dummypath", "80", "http")
124
125
  end
125
126
  end
@@ -133,7 +134,7 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
133
134
 
134
135
  def test_get_info_fails
135
136
  build_net_http_object(:response => {'x-account-bytes-used' => '9999', 'x-account-container-count' => '5'}, :code => '999')
136
- assert_raises(InvalidResponseException) do
137
+ assert_raises(CloudFiles::Exception::InvalidResponse) do
137
138
  @connection.get_info
138
139
  end
139
140
  end
@@ -154,7 +155,7 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
154
155
 
155
156
  def test_public_containers_exception
156
157
  build_net_http_object(:code => '999')
157
- assert_raises(InvalidResponseException) do
158
+ assert_raises(CloudFiles::Exception::InvalidResponse) do
158
159
  public_containers = @connection.public_containers
159
160
  end
160
161
  end
@@ -167,14 +168,14 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
167
168
 
168
169
  def test_delete_nonempty_container
169
170
  build_net_http_object(:code => '409')
170
- assert_raises(NonEmptyContainerException) do
171
+ assert_raises(CloudFiles::Exception::NonEmptyContainer) do
171
172
  response = @connection.delete_container("not_empty")
172
173
  end
173
174
  end
174
175
 
175
176
  def test_delete_unknown_container
176
177
  build_net_http_object(:code => '999')
177
- assert_raises(NoSuchContainerException) do
178
+ assert_raises(CloudFiles::Exception::NoSuchContainer) do
178
179
  response = @connection.delete_container("not_empty")
179
180
  end
180
181
  end
@@ -188,7 +189,7 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
188
189
 
189
190
  def test_create_container_with_invalid_name
190
191
  CloudFiles::Container.stubs(:new)
191
- assert_raise(SyntaxException) do
192
+ assert_raise(CloudFiles::Exception::Syntax) do
192
193
  container = @connection.create_container('a'*300)
193
194
  end
194
195
  end
@@ -196,7 +197,7 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
196
197
  def test_create_container_name_filter
197
198
  CloudFiles::Container.any_instance.stubs(:populate)
198
199
  build_net_http_object(:code => '201')
199
- assert_raises(SyntaxException) do
200
+ assert_raises(CloudFiles::Exception::Syntax) do
200
201
  container = @connection.create_container('this/has/bad?characters')
201
202
  end
202
203
  end
@@ -219,9 +220,9 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
219
220
  end
220
221
 
221
222
  def test_fetch_nonexistent_container
222
- CloudFiles::Container.any_instance.stubs(:populate).raises(NoSuchContainerException)
223
+ CloudFiles::Container.any_instance.stubs(:metadata).raises(CloudFiles::Exception::NoSuchContainer)
223
224
  build_net_http_object
224
- assert_raise(NoSuchContainerException) do
225
+ assert_raise(CloudFiles::Exception::NoSuchContainer) do
225
226
  container = @connection.container('bad_container')
226
227
  end
227
228
  end
@@ -258,7 +259,7 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
258
259
 
259
260
  def test_containers_bad_result
260
261
  build_net_http_object(:code => '999')
261
- assert_raises(InvalidResponseException) do
262
+ assert_raises(CloudFiles::Exception::InvalidResponse) do
262
263
  containers = @connection.containers
263
264
  end
264
265
  end
@@ -280,7 +281,7 @@ class CloudfilesConnectionTest < Test::Unit::TestCase
280
281
 
281
282
  def test_containers_detail_bad_response
282
283
  build_net_http_object(:code => '999')
283
- assert_raises(InvalidResponseException) do
284
+ assert_raises(CloudFiles::Exception::InvalidResponse) do
284
285
  details = @connection.containers_detail
285
286
  end
286
287
  end