ruby-atmos-pure 1.0.3
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.
- data/COPYING +8 -0
- data/README +129 -0
- data/Rakefile +103 -0
- data/lib/atmos.rb +35 -0
- data/lib/atmos/attributes.rb +545 -0
- data/lib/atmos/exceptions.rb +28 -0
- data/lib/atmos/object.rb +321 -0
- data/lib/atmos/parser.rb +110 -0
- data/lib/atmos/parser/rexml.rb +1 -0
- data/lib/atmos/request.rb +221 -0
- data/lib/atmos/response.rb +116 -0
- data/lib/atmos/rest.rb +145 -0
- data/lib/atmos/store.rb +220 -0
- data/lib/atmos/util.rb +40 -0
- data/lib/atmos/version.rb +12 -0
- data/test/credentials.rb +141 -0
- data/test/esutest.rb +499 -0
- data/test/files/SmallImageForTest.iso +0 -0
- data/test/files/dragaf-tiny-from-vsphere.ova +0 -0
- data/test/files/something.txt +1 -0
- data/test/require_test.rb +2 -0
- data/test/suite.rb +11 -0
- data/test/suite_noproxy.rb +12 -0
- data/test/suite_proxy.rb +14 -0
- data/test/test_acl.rb +283 -0
- data/test/test_metadata.rb +162 -0
- data/test/test_object_create.rb +167 -0
- data/test/test_object_get.rb +55 -0
- data/test/test_object_misc.rb +80 -0
- data/test/test_object_read.rb +98 -0
- data/test/test_object_update.rb +59 -0
- data/test/test_request.rb +49 -0
- data/test/test_store.rb +125 -0
- data/test/test_util.rb +58 -0
- metadata +155 -0
data/lib/atmos/store.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
module Atmos
|
2
|
+
|
3
|
+
class Store
|
4
|
+
attr_reader :http, :uid, :secret, :uri, :tenant, :user, :proxy # :nodoc:
|
5
|
+
|
6
|
+
#
|
7
|
+
# Create and validate a connection to an Atmos server.
|
8
|
+
# This API supports both the object interface and the namespace interface.
|
9
|
+
# Proxy support has been tested against squid 2.7.STABLE9 on ubuntu 10.10.
|
10
|
+
#
|
11
|
+
# If you have used Atmos Online this example will look familiar:
|
12
|
+
#
|
13
|
+
# store = Atmos::Store.new(:url => 'https://accesspoint.atmosonline.com'
|
14
|
+
# :uid => 'ab9090e754b549eeb460a468abdf7fc2/A797558526171ea693ce'
|
15
|
+
# :secret => 'pEauABL07ujkF2hJN7r6wA9/HPs='
|
16
|
+
# )
|
17
|
+
#
|
18
|
+
# Required:
|
19
|
+
# * <tt>:url</tt> - the url to the Atmos server the Store object will
|
20
|
+
# represent (e.g. \https://accesspoint.atmosonline.com)
|
21
|
+
# * <tt>:uid</tt> - a string, "<tenant id>/<username>"
|
22
|
+
# ("Full Token ID" in Atmos Online)
|
23
|
+
# * <tt>:secret</tt> - a string, the secret key associated with the user
|
24
|
+
# (shared secret for a token in Atmos Online)
|
25
|
+
# --
|
26
|
+
# Optional:
|
27
|
+
# * <tt>:proxy</tt> - url to proxy of the form
|
28
|
+
# scheme://[user[:password]@]host:port
|
29
|
+
#
|
30
|
+
#
|
31
|
+
def initialize(options = {})
|
32
|
+
valid = [:url,:secret,:uid,:tag,:version,:proxy,:unsupported].freeze
|
33
|
+
invalid = options.keys - valid
|
34
|
+
raise Atmos::Exceptions::ArgumentException,
|
35
|
+
"Unrecognized options: #{invalid.inspect}" if (!invalid.empty?)
|
36
|
+
Atmos::LOG.info("Store.initialize: options: #{options.inspect}")
|
37
|
+
|
38
|
+
raise Atmos::Exceptions::ArgumentException,
|
39
|
+
"The kind of XML parser you would like to use has not been set yet." if (Atmos::Parser::parser.nil?)
|
40
|
+
|
41
|
+
@uri = URI.parse(options[:url])
|
42
|
+
@secret = options[:secret]
|
43
|
+
@uid = options[:uid]
|
44
|
+
@tag = options[:tag]
|
45
|
+
|
46
|
+
if (@uid =~ /^([^\/]+)\/([^\/]+)$/)
|
47
|
+
@tenant = $1
|
48
|
+
@user = $2
|
49
|
+
else
|
50
|
+
@tenant = nil
|
51
|
+
@user = @uid
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
proxyopts = [nil]
|
56
|
+
if !options[:proxy].nil?
|
57
|
+
|
58
|
+
proxyurl = URI.parse(options[:proxy])
|
59
|
+
|
60
|
+
if (!proxyurl.kind_of?(URI::HTTP) &&
|
61
|
+
!proxyurl.kind_of?(URI::HTTPS))
|
62
|
+
|
63
|
+
msg = "Please check the proxy URL scheme. "
|
64
|
+
msg += "It's not being recognized as an http or https url. "
|
65
|
+
msg += "You do have to include the http(s):// part."
|
66
|
+
raise Atmos::Exceptions::ArgumentException, msg
|
67
|
+
end
|
68
|
+
|
69
|
+
Atmos::LOG.warn("using proxy: #{options[:proxy]}")
|
70
|
+
proxyopts = [proxyurl.host, proxyurl.port]
|
71
|
+
|
72
|
+
if (proxyurl.userinfo =~ /([^:]+):([^:])/)
|
73
|
+
proxyopts.push([$1, $2])
|
74
|
+
elsif (!proxyurl.userinfo.nil?)
|
75
|
+
proxyopts.push(proxyurl.userinfo)
|
76
|
+
end
|
77
|
+
Atmos::LOG.info("proxy options: #{proxyopts.inspect}")
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
@http = Net::HTTP.Proxy(*proxyopts).new(@uri.host, @uri.port)
|
82
|
+
if @uri.scheme == 'https'
|
83
|
+
@http.use_ssl = true
|
84
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
85
|
+
end
|
86
|
+
Atmos::LOG.debug("http class: #{@http.inspect}")
|
87
|
+
|
88
|
+
@request = Atmos::Request.new(:store => self, :default_tag => @tag)
|
89
|
+
res = @request.do(:get_service_info)
|
90
|
+
|
91
|
+
if (res.http_response.kind_of?(Net::HTTPMovedPermanently))
|
92
|
+
rurl = (res['location'].nil?) ? res.body.match(/<a href=\"([^>]+)\">/i)[1] : res['location']
|
93
|
+
raise ArgumentException, "The Atmos URL is redirecting. Please supply the correct URL. (#{@uri.to_s} => #{rurl})"
|
94
|
+
end
|
95
|
+
|
96
|
+
@server_version = Atmos::Parser::response_get_string(res.http_response, '//xmlns:Atmos')
|
97
|
+
|
98
|
+
if ((!SUPPORTED_VERSIONS.include?(@server_version)) &&
|
99
|
+
(options[:unsupported] != true))
|
100
|
+
msg ="This library does not support Atmos version #{@server_version}. "
|
101
|
+
msg += "Supported versions: #{SUPPORTED_VERSIONS.inspect}. "
|
102
|
+
msg += "To silence this, pass :unsupported => true when instantiating."
|
103
|
+
|
104
|
+
raise Atmos::Exceptions::NotImplementedException, msg
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
if (!options[:version].nil? && !options[:version].eql?(@server_version))
|
109
|
+
raise Atmos::Exceptions::ArgumentException,
|
110
|
+
"Atmos server version and version you were expecting do not match."
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
#
|
116
|
+
# Create an Atmos object. This can be done with no arguments,
|
117
|
+
# or with any of the listed optional arguments. Checksums are
|
118
|
+
# not yet supported.
|
119
|
+
#
|
120
|
+
# If no data is passed, a 0 length object is created.
|
121
|
+
# If no ACLs are passed, the default access control is applied.
|
122
|
+
# If no mime type is passed, the default is 'binary/octet-stream'.
|
123
|
+
#
|
124
|
+
# Optional:
|
125
|
+
# * <tt>:user_acl</tt> - hash of username/permissions (<tt>:none</tt>, <tt>:read</tt>, <tt>:write</tt>, <tt>:full</tt>) pairs
|
126
|
+
# * <tt>:group_acl</tt> - hash of groupname/permissions (<tt>:none</tt>, <tt>:read</tt>, <tt>:write</tt>, <tt>:full</tt>) pairs
|
127
|
+
# * <tt>:metadata</tt> - hash of string pairs
|
128
|
+
# * <tt>:listable_metadata</tt> - hash of string pairs
|
129
|
+
# * <tt>:mimetype</tt> - defaults to application/octet-stream
|
130
|
+
# * <tt>:data</tt> - a String or an IO stream
|
131
|
+
# * <tt>:length</tt> - a number (requires <tt>:data</tt>)
|
132
|
+
# * <tt>:namespace</tt> - name for namespace interface instead of object interface
|
133
|
+
#
|
134
|
+
def create(options = {})
|
135
|
+
Atmos::Object.new(self, :create, options)
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
#
|
140
|
+
# Retrieve an Atmos object given an id.
|
141
|
+
# When the object is retrieved, the ACL and
|
142
|
+
# Metadata information is loaded from the server.
|
143
|
+
# The blob data is not loaded until
|
144
|
+
# accessed, so it can be progressively downloaded.
|
145
|
+
#
|
146
|
+
# Mutually exclusive, one required:
|
147
|
+
# * <tt>:id</tt> - the id of the object to retrieve
|
148
|
+
# * <tt>:namespace</tt> - the namespace key of the object to retrieve
|
149
|
+
def get(options)
|
150
|
+
|
151
|
+
# can't both be set, can't both be empty
|
152
|
+
if (!options[:id].nil? && !options[:namespace].nil?)
|
153
|
+
raise Atmos::Exceptions::ArgumentException, "One of :id, :namespace is required, but not both."
|
154
|
+
elsif (options[:id].nil? && options[:namespace].nil?)
|
155
|
+
raise Atmos::Exceptions::ArgumentException, "One of :id, :namespace is required."
|
156
|
+
end
|
157
|
+
|
158
|
+
Atmos::Object.new(self, :get, options)
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
#
|
163
|
+
# Tags are the key part of key/value metadata pairs.
|
164
|
+
# Metadata that has been created as listable can be
|
165
|
+
# retrieved based on the tag. This method iterates
|
166
|
+
# through all listable tags in Atmos.
|
167
|
+
#
|
168
|
+
# Tags can be hierarchical: foo/bar/baz. And each
|
169
|
+
# level anc have multiple tags under it. So to
|
170
|
+
# list all tags under the "foo" tag pass "foo" as the
|
171
|
+
# argument. To list all tags under "foo/bar", pass
|
172
|
+
# "foo/bar" as the argument.
|
173
|
+
#
|
174
|
+
def each_listable_tag(tag = nil) #:nodoc:
|
175
|
+
token = ""
|
176
|
+
headers = {}
|
177
|
+
headers['x-emc-tags'] = tag if (!tag.nil?)
|
178
|
+
|
179
|
+
while (!token.nil?)
|
180
|
+
response = @request.do(:listable_tags, headers)
|
181
|
+
response.each('x-emc-listable-tags') do |tag|
|
182
|
+
yield tag
|
183
|
+
end
|
184
|
+
|
185
|
+
token = response['x-emc-token']
|
186
|
+
headers['x-emc-token'] = token if (!token.nil?)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
#
|
192
|
+
# Iterate through objects that are indexed by a particular tag. Tag can't be nil,
|
193
|
+
# and must be a ruby String. Note that as the objects are instantiated, ACLs and
|
194
|
+
# Metadata will be retrieved, and object data will not.
|
195
|
+
#
|
196
|
+
# Note that there may not be any objects associated with a listable tag even though
|
197
|
+
# that tag shows up when listing all listable tags.
|
198
|
+
#
|
199
|
+
def each_object_with_listable_tag(tag)
|
200
|
+
raise Atmos::Exceptions::ArgumentException, "The 'tag' parameter cannot be nil." if (tag.nil?)
|
201
|
+
raise Atmos::Exceptions::ArgumentException, "Only one tag is allowed at a time." if (!tag.kind_of?(String))
|
202
|
+
|
203
|
+
response = @request.do(:list_objects, 'x-emc-include-meta' => 0, 'x-emc-tags' => tag)
|
204
|
+
|
205
|
+
Atmos::Parser::response_get_array(response, '//xmlns:ObjectID').each do |idxml|
|
206
|
+
yield Atmos::Object.new(self, idxml)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
#
|
212
|
+
# Returns the version of the Atmos server authenticated to as a string.
|
213
|
+
#
|
214
|
+
def server_version
|
215
|
+
@server_version
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
data/lib/atmos/util.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Atmos
|
2
|
+
class Util # :nodoc:
|
3
|
+
|
4
|
+
#
|
5
|
+
# Utility method to convert from a standard Atmos key/value pair return header.
|
6
|
+
#
|
7
|
+
def self.header2hash(value)
|
8
|
+
return nil if (value.nil?)
|
9
|
+
raise Atmos::Exceptions::ArgumentException, "The 'value' parameter must be a String" if (!value.kind_of?(String))
|
10
|
+
|
11
|
+
rv = {}
|
12
|
+
if (!value.nil?)
|
13
|
+
value.split(',').each do |elt|
|
14
|
+
key,val = elt.split('=')
|
15
|
+
rv[key.strip] = val.nil? ? "" : val.strip
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
rv
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
#
|
24
|
+
# Utility method to convert to a standard header value.
|
25
|
+
#
|
26
|
+
def self.hash2header(value)
|
27
|
+
return nil if (value.nil?)
|
28
|
+
raise Atmos::Exceptions::ArgumentException, "The 'value' parameter must be a Hash" if (!value.kind_of?(Hash))
|
29
|
+
|
30
|
+
rv = ""
|
31
|
+
if (!value.nil?)
|
32
|
+
value.each do |k,v|
|
33
|
+
rv += "#{k}=#{v}, "
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
rv[0..-3]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Atmos
|
2
|
+
|
3
|
+
# Version number of this library.
|
4
|
+
VERSION = "1.0.3"
|
5
|
+
|
6
|
+
# Array of version strings this library has been tested against.
|
7
|
+
SUPPORTED_VERSIONS = ["1.2.7", "1.3.4", "1.4.0", "1.4.1", "2.0.1"].freeze
|
8
|
+
|
9
|
+
# The logger used by the entire gem.
|
10
|
+
LOG = Log4r::Logger.get('atmos')
|
11
|
+
|
12
|
+
end
|
data/test/credentials.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
module Atmos
|
2
|
+
module Test
|
3
|
+
class Util
|
4
|
+
$stdout.sync = true
|
5
|
+
@use_proxy = false
|
6
|
+
@proxy = 'http://127.0.0.1:3128'
|
7
|
+
@store = nil
|
8
|
+
@server = :atmosonline
|
9
|
+
@servers =
|
10
|
+
{:alma => {
|
11
|
+
:url => 'https://10.5.113.71',
|
12
|
+
:redirect_url=> nil,
|
13
|
+
:version => '2.0.1',
|
14
|
+
:default_tag => 'atmos-ruby',
|
15
|
+
:tenant => '69eb3dc3bf9746f895d1ce12ae1d9589',
|
16
|
+
:user => 'dragaf-test',
|
17
|
+
:group => 'other',
|
18
|
+
:secret => 'p97mki4AkiAyVi+/7QpdxFAU/jY=',
|
19
|
+
:other_user => nil,
|
20
|
+
:other_group => nil,
|
21
|
+
},
|
22
|
+
:atmosonline => {
|
23
|
+
:url => 'https://accesspoint.atmosonline.com',
|
24
|
+
:redirect_url=> 'http://accesspoint.atmosonline.com',
|
25
|
+
:version => '1.3.4',
|
26
|
+
:default_tag => 'atmos-ruby',
|
27
|
+
:tenant => 'b245ad26f5c94bcbbaffa315a833f27a',
|
28
|
+
:user => 'A79755852684b2e05d00',
|
29
|
+
:group => 'other',
|
30
|
+
:secret => 'sM6oN/k6e03iW7lNSUzFav9rwck=',
|
31
|
+
:other_user => 'A797558526171ea693ce',
|
32
|
+
:other_group => 'grouptest',
|
33
|
+
},
|
34
|
+
:cambridge_71 => {
|
35
|
+
:url => 'https://10.5.113.74',
|
36
|
+
:redirect_url=> nil,
|
37
|
+
:version => '1.4.1',
|
38
|
+
:default_tag => 'atmos-ruby',
|
39
|
+
:tenant => 'ab9090e754b549eeb460a468abdf7fc2',
|
40
|
+
:user => 'dragaf-test-tenant-user1',
|
41
|
+
:group => 'other',
|
42
|
+
:secret => 't5R1ftRNLXQ3ejv6fvJLNFMFrPo=',
|
43
|
+
:other_user => 'another',
|
44
|
+
:other_group => nil,
|
45
|
+
},
|
46
|
+
:matt => {
|
47
|
+
:url => 'http://137.69.164.126',
|
48
|
+
:redirect_url=> nil,
|
49
|
+
:version => "1.4.0",
|
50
|
+
:default_tag => 'atmos-ruby',
|
51
|
+
#:tenant => 'fdragan-atmos-ruby-test',
|
52
|
+
:tenant => '4aba2817d7eb4a2d93dfdccb3caedb9f',
|
53
|
+
:user => 'testuser02',
|
54
|
+
:group => 'other',
|
55
|
+
:secret => 'sWNxtrhorOpi0R3PNPSo1uKV4Vo=',
|
56
|
+
:other_user => 'testuser01',
|
57
|
+
:other_group => nil,
|
58
|
+
},
|
59
|
+
}
|
60
|
+
|
61
|
+
def self.parser_type
|
62
|
+
Atmos::Parser::NOKOGIRI
|
63
|
+
#Atmos::Parser::REXML
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Provides the same store object to all who request it.
|
68
|
+
# This is the default for running tests. If tests fail
|
69
|
+
# you can change the mode to get a new store each time
|
70
|
+
# and see if that fixes it. If so, you know that something
|
71
|
+
# weird is going on with the Atmos::Store object.
|
72
|
+
#
|
73
|
+
def self.static_store
|
74
|
+
if (@store.nil?)
|
75
|
+
Atmos::Parser::parser = parser_type
|
76
|
+
@store = Atmos::Store.new(:url => url,
|
77
|
+
:uid => uid,
|
78
|
+
:secret => secret,
|
79
|
+
:proxy => proxy
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
return @store
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.new_store
|
87
|
+
Atmos::Parser::parser = parser_type
|
88
|
+
Atmos::Store.new(:url => url,
|
89
|
+
:uid => uid,
|
90
|
+
:secret => secret,
|
91
|
+
:proxy => proxy
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def self.server
|
97
|
+
@server
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.use_proxy=(bool)
|
101
|
+
@use_proxy = bool
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.proxy
|
105
|
+
(@use_proxy == true) ? @proxy : nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.small_text_filename
|
109
|
+
File.join(File.dirname(__FILE__),
|
110
|
+
'files/something.txt')
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.small_binary_filename
|
114
|
+
File.join(File.dirname(__FILE__),
|
115
|
+
'files/dragaf-tiny-from-vsphere.ova')
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.large_binary_filename
|
119
|
+
File.join(File.dirname(__FILE__),
|
120
|
+
'SmallImageForTest.iso')
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.test_server_info(key)
|
124
|
+
@servers[key]
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.uid
|
128
|
+
return "#{Atmos::Test::Util.tenant}/#{Atmos::Test::Util.user}"
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.method_missing(sym, *args)
|
132
|
+
if (@servers[@server].has_key?(sym))
|
133
|
+
return @servers[@server][sym]
|
134
|
+
else
|
135
|
+
return super.method_missing(sym, *args)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/test/esutest.rb
ADDED
@@ -0,0 +1,499 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'EsuApi'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
class Esutest < Test::Unit::TestCase
|
8
|
+
def initialize( id )
|
9
|
+
super(id)
|
10
|
+
@esu = EsuApi::EsuRestApi.new( "192.168.15.115",80,"connectic","D7qsp4j16PBHWSiUbc/bt3lbPBY=")
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@cleanup = []
|
15
|
+
@cleanfiles = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
@cleanup.each { |id| @esu.delete_object( id ) }
|
20
|
+
@cleanfiles.each { |file| file.close! }
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Test creating one empty object. No metadata, no content.
|
25
|
+
#
|
26
|
+
def test_create_empty_object()
|
27
|
+
id = @esu.create_object( nil, nil, nil, nil )
|
28
|
+
assert_not_nil( id, "nil ID returned" );
|
29
|
+
@cleanup.push( id )
|
30
|
+
|
31
|
+
# Read back the content
|
32
|
+
content = @esu.read_object( id, nil, nil )
|
33
|
+
assert_equal( "", content, "object content wrong" );
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_hmac
|
37
|
+
str = "Hello World"
|
38
|
+
value = HMAC::SHA1.digest( Base64.decode64( "D7qsp4j16PBHWSiUbc/bt3lbPBY=" ), str )
|
39
|
+
signature = Base64.encode64( value ).chomp()
|
40
|
+
print "String to sign: #{str}\nSignature: #{signature}\nValue: #{value}\n"
|
41
|
+
assert_equal( "kFcjtduMr0rljJHxJRqF8i1DNp4=", signature, "HMAC failed to validate" )
|
42
|
+
end
|
43
|
+
|
44
|
+
# def test_create_empty_object_on_path()
|
45
|
+
# op = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
|
46
|
+
# id = @esu.create_object_on_path( op, nil, nil, nil, nil )
|
47
|
+
# assert_not_nil( id, "nil ID returned" );
|
48
|
+
# @cleanup.push( id )
|
49
|
+
#
|
50
|
+
# # Read back the content
|
51
|
+
# content = @esu.read_object( id, nil, nil )
|
52
|
+
# assert_equal( "", content, "object content wrong" );
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
def test_create_object_with_content()
|
56
|
+
id = @esu.create_object( nil, nil, "hello", "text/plain" )
|
57
|
+
assert_not_nil( id, "nil ID returned" );
|
58
|
+
@cleanup.push( id )
|
59
|
+
|
60
|
+
# Read back the content
|
61
|
+
content = @esu.read_object( id, nil, nil )
|
62
|
+
assert_equal( "hello", content, "object content wrong" );
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_update_object
|
66
|
+
id = @esu.create_object( nil, nil, "hello", "text/plain" )
|
67
|
+
assert_not_nil( id, "nil ID returned" );
|
68
|
+
@cleanup.push( id )
|
69
|
+
|
70
|
+
# Change the content
|
71
|
+
@esu.update_object( id, nil, nil, "Hello World", "text/plain" )
|
72
|
+
|
73
|
+
# Read back the content
|
74
|
+
content = @esu.read_object( id, nil, nil )
|
75
|
+
assert_equal( "Hello World", content, "object content wrong" );
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# def test_create_object_with_stream()
|
81
|
+
# stream = createTestStream( 40 )
|
82
|
+
# id = @esu.create_object( nil, nil, stream.open, "text/plain" )
|
83
|
+
#
|
84
|
+
# @cleanup.push( id )
|
85
|
+
#
|
86
|
+
# # Read back the content
|
87
|
+
# content = @esu.read_object( id, nil, nil )
|
88
|
+
# assert_equal( content, stream.open.readlines, "object content wrong" );
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# def test_create_object_with_metadata()
|
92
|
+
# meta = {}
|
93
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
94
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
95
|
+
# meta['listable2'] = EsuApi::Metadata.new( "listable2", "foo2 foo2", true )
|
96
|
+
# meta['unlistable2'] = EsuApi::Metadata.new( "unlistable2", "bar2 bar2", false )
|
97
|
+
# id = @esu.create_object( nil, meta, nil, nil )
|
98
|
+
# @cleanup.push( id )
|
99
|
+
#
|
100
|
+
# # Read back and check
|
101
|
+
# meta = @esu.get_user_metadata( id )
|
102
|
+
#
|
103
|
+
# assert_equal( "foo", meta["listable"].value, "Value of listable wrong" )
|
104
|
+
# assert_equal( "bar", meta["unlistable"].value, "Value of unlistable wrong" )
|
105
|
+
# assert_equal( "foo2 foo2", meta["listable2"].value, "Value of listable2 wrong" )
|
106
|
+
# assert_equal( "bar2 bar2", meta["unlistable2"].value, "Value of unlistable2 wrong" )
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# def test_acl
|
110
|
+
# acl = createAcl
|
111
|
+
# id = @esu.create_object( acl, nil, nil, nil )
|
112
|
+
# @cleanup.push( id )
|
113
|
+
#
|
114
|
+
# # Read back and check
|
115
|
+
# newacl = @esu.getAcl( id )
|
116
|
+
# check_acl( acl, newacl )
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# def test_acl_on_path
|
120
|
+
# acl = createAcl
|
121
|
+
# op = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
|
122
|
+
# id = @esu.create_object_on_path( op, acl, nil, nil, nil )
|
123
|
+
# @cleanup.push( id )
|
124
|
+
#
|
125
|
+
# # Read back and check
|
126
|
+
# newacl = @esu.get_acl( id )
|
127
|
+
# check_acl( acl, newacl )
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# def test_delete_user_metadata
|
131
|
+
# meta = {}
|
132
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
133
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
134
|
+
# meta['listable2'] = EsuApi::Metadata.new( "listable2", "foo2 foo2", true )
|
135
|
+
# meta['unlistable2'] = EsuApi::Metadata.new( "unlistable2", "bar2 bar2", false )
|
136
|
+
# id = @esu.create_object( nil, meta, nil, nil )
|
137
|
+
# @cleanup.push( id )
|
138
|
+
#
|
139
|
+
# # Delete some metadata
|
140
|
+
# deleteList = [ 'listable', 'unlistable' ]
|
141
|
+
# @esu.delete_user_metadata( id, deleteList )
|
142
|
+
#
|
143
|
+
# # Read back and check
|
144
|
+
# meta = @esu.get_user_metadata( id )
|
145
|
+
#
|
146
|
+
# assert_nil( meta["listable"], "listable should have been deleted" )
|
147
|
+
# assert_nil( meta["unlistable"], "unlistable should have been deleted" )
|
148
|
+
# assert_equal( "foo2 foo2", meta["listable2"].value, "Value of listable2 wrong" )
|
149
|
+
# assert_equal( "bar2 bar2", meta["unlistable2"].value, "Value of unlistable2 wrong" )
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# def test_delete_version
|
153
|
+
# id = @esu.create_object( nil, nil, nil, nil )
|
154
|
+
# @cleanup.push( id )
|
155
|
+
#
|
156
|
+
# # Create some versions
|
157
|
+
# vid1 = @esu.version_object( id );
|
158
|
+
# vid2 = @esu.version_object( id );
|
159
|
+
#
|
160
|
+
# # Delete one of the versions
|
161
|
+
# @esu.delete_version( vid1 )
|
162
|
+
#
|
163
|
+
# # List back the versions
|
164
|
+
# vlist = @esu.listVersions( id );
|
165
|
+
# assert_equal( 1, vlist.size, "Only expected one version" )
|
166
|
+
# assert_equal( vid2, vlist[0], "Expected second vid" )
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# def test_restore_version
|
170
|
+
# id = @esu.create_object( nil, nil, "Original Content", "text/plain" )
|
171
|
+
# @cleanup.push( id )
|
172
|
+
#
|
173
|
+
# # Version the object
|
174
|
+
# vid1 = @esu.version_object( id )
|
175
|
+
#
|
176
|
+
# # Change the content
|
177
|
+
# @esu.update_object( id, nil, nil, "New content you should never see", "text/plain" )
|
178
|
+
#
|
179
|
+
# # restore the first version
|
180
|
+
# @esu.restore_version( id, vid1 )
|
181
|
+
#
|
182
|
+
# # Read back the content
|
183
|
+
# content = @esu.read_object( id )
|
184
|
+
# assert_equal( "Original Content", content, "Expected original content" )
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
# def test_get_system_metadata
|
188
|
+
# id = @esu.create_object( nil, nil, "12345", "text/plain" )
|
189
|
+
# @cleanup.push( id )
|
190
|
+
#
|
191
|
+
# tags = [ 'ctime', 'size' ]
|
192
|
+
# smeta = @esu.get_system_metadata( id, tags )
|
193
|
+
#
|
194
|
+
# assert_not_nil( smeta['ctime'], "Expected ctime to be set" )
|
195
|
+
# assert_equal( 5, smeta['size'].value, "Expected object size to be five" )
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# def test_list_objects
|
199
|
+
# meta = {}
|
200
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
201
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
202
|
+
# meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
|
203
|
+
# meta['unlistable2'] = EsuApi::Metadata.new( "un/list/able2", "bar2 bar2", false )
|
204
|
+
# id = @esu.create_object( nil, meta, nil, nil )
|
205
|
+
# @cleanup.push( id )
|
206
|
+
#
|
207
|
+
# # List tags and check membership
|
208
|
+
# objects = @esu.list_objects( "listable" );
|
209
|
+
# assert_true( objects.include?(id), "Expected object to be listable" );
|
210
|
+
#
|
211
|
+
# objects = @esu.list_objects( "unlistable" )
|
212
|
+
# assert_true( !objects.include?(id), "Expected object to not be unlistable" )
|
213
|
+
#
|
214
|
+
# objects = @esu.list_objects( "list/able/2" )
|
215
|
+
# assert_true( objects.include?(id), "Expected object to be listable" )
|
216
|
+
# end
|
217
|
+
#
|
218
|
+
# def test_list_objects_with_metadata
|
219
|
+
# meta = {}
|
220
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
221
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
222
|
+
# meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
|
223
|
+
# meta['unlistable2'] = EsuApi::Metadata.new( "un/list/able2", "bar2 bar2", false )
|
224
|
+
# id = @esu.create_object( nil, meta, nil, nil )
|
225
|
+
# @cleanup.push( id )
|
226
|
+
#
|
227
|
+
# # List tags and check membership
|
228
|
+
# objects = @esu.list_objects_with_metadata( "listable" );
|
229
|
+
# assert_true( objects.include?(id), "Expected object to be listable" );
|
230
|
+
#
|
231
|
+
# oid = objects[ objects.index(id) ]
|
232
|
+
#
|
233
|
+
# # Check metadata
|
234
|
+
# assert_equal( "foo", oid.meta['listable'], "Expected metadata to be set on object" )
|
235
|
+
# end
|
236
|
+
#
|
237
|
+
# def test_get_listable_tags
|
238
|
+
# meta = {}
|
239
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
240
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
241
|
+
# meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
|
242
|
+
# meta['unlistable2'] = EsuApi::Metadata.new( "list/able/not", "bar2 bar2", false )
|
243
|
+
# id = @esu.create_object( nil, meta, nil, nil )
|
244
|
+
# @cleanup.push( id )
|
245
|
+
#
|
246
|
+
# # Check root tags
|
247
|
+
# tags = @esu.get_listable_tags( nil )
|
248
|
+
# assert( tags.include?('listable'), "Expected listable in root" )
|
249
|
+
# assert( tags.include?('list'), "Expected list in root" )
|
250
|
+
# assert( !tags.include?('unlistable'), "Expected unlistable to be missing" )
|
251
|
+
#
|
252
|
+
# # Check deeper tag
|
253
|
+
# tags = @esu.get_listable_tags( 'list/able' )
|
254
|
+
# assert( tags.include?( '2' ), "Expected child tag" )
|
255
|
+
# assert( !tags.include?( 'listable' ), "Root tag found in child" )
|
256
|
+
# assert( !tags.include?( 'not' ), "Found unlistable tag" )
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# def test_list_user_metadata_tags
|
260
|
+
# meta = {}
|
261
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
262
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
263
|
+
# meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
|
264
|
+
# meta['unlistable2'] = EsuApi::Metadata.new( "list/able/not", "bar2 bar2", false )
|
265
|
+
# id = @esu.create_object( nil, meta, nil, nil )
|
266
|
+
# @cleanup.push( id )
|
267
|
+
#
|
268
|
+
# # Check tags
|
269
|
+
# tags = @esu.list_user_metadata_tags( id )
|
270
|
+
# assert( tags.include?('listable'), "Metadata listable tag missing" );
|
271
|
+
# assert( tags.include?('unlistable'), "Metadata unlistable tag missing" );
|
272
|
+
# assert( tags.include?('list/able/2'), "Metadata list/able/2 tag missing" );
|
273
|
+
# assert( tags.include?('list/able/not'), "Metadata list/able/not tag missing" );
|
274
|
+
# end
|
275
|
+
#
|
276
|
+
# def test_update_object
|
277
|
+
# meta = {}
|
278
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
279
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
280
|
+
# id = @esu.create_object( nil, meta, "Four score and seven years ago", "text/plain" )
|
281
|
+
# @cleanup.push( id )
|
282
|
+
#
|
283
|
+
# # Update object
|
284
|
+
# meta = {}
|
285
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "xxx", true )
|
286
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "yyy", false )
|
287
|
+
# @esu.update_object( nil, meta, "New content here", "text/plain" )
|
288
|
+
#
|
289
|
+
# # Read back metadata and check
|
290
|
+
# meta = @esu.get_user_metadata( id )
|
291
|
+
#
|
292
|
+
# assert_equal( "xxx", meta["listable"].value, "Value of listable wrong" )
|
293
|
+
# assert_equal( "yyy", meta["unlistable"].value, "Value of unlistable wrong" )
|
294
|
+
#
|
295
|
+
# # Read back the content
|
296
|
+
# content = @esu.read_object( id, nil, nil )
|
297
|
+
# assert_equal( "New content here", content, "object content wrong" );
|
298
|
+
# end
|
299
|
+
#
|
300
|
+
# def test_update_object_with_stream()
|
301
|
+
# stream = createTestStream( 40 )
|
302
|
+
# id = @esu.create_object( nil, nil, stream.open, "text/plain" )
|
303
|
+
#
|
304
|
+
# @cleanup.push( id )
|
305
|
+
#
|
306
|
+
# stream2 = createTestStream( 45 )
|
307
|
+
# @esu.update_object( nil, nil, stream2.open(), "text/plain" )
|
308
|
+
#
|
309
|
+
# # Read back the content
|
310
|
+
# content = @esu.read_object( id, nil, nil )
|
311
|
+
# assert_equal( content, stream2.open.readlines, "object content wrong" );
|
312
|
+
# end
|
313
|
+
#
|
314
|
+
# def test_list_directory()
|
315
|
+
# dir = '/' + randomstr( 8 )
|
316
|
+
#
|
317
|
+
# file1 = EsuApi::ObjectPath.new( dir + '/' + randomstr( 8 ) )
|
318
|
+
# file2 = EsuApi::ObjectPath.new( dir + '/' + randomstr( 8 ) )
|
319
|
+
# dir2 = EsuApi::ObjectPath.new( dir + '/' + randomstr( 8 ) + '/' )
|
320
|
+
# id1 = @esu.create_object_on_path( file1, nil, nil, nil, nil )
|
321
|
+
# @cleanup.push( id1 )
|
322
|
+
# id2 = @esu.create_object_on_path( file2, nil, nil, nil, nil )
|
323
|
+
# @cleanup.push( id2 )
|
324
|
+
# id3 = @esu.create_object_on_path( dir2, nil, nil, nil, nil )
|
325
|
+
# @cleanup.push( id3 )
|
326
|
+
#
|
327
|
+
# dirlist = @esu.list_directory( EsuApi::ObjectPath.new( dir + '/' ) )
|
328
|
+
# assert( dirlist.find { |entry| entry == file1 }, "could not locate " + file1 )
|
329
|
+
# assert( dirlist.find { |entry| entry == file2 }, "could not locate " + file2 )
|
330
|
+
# assert( dirlist.find { |entry| entry == dir2 }, "could not locate " + dir2 )
|
331
|
+
# end
|
332
|
+
#
|
333
|
+
# def test_get_all_metadata()
|
334
|
+
# meta = {}
|
335
|
+
# meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
|
336
|
+
# meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
|
337
|
+
# meta['listable2'] = EsuApi::Metadata.new( "listable2", "foo2 foo2", true )
|
338
|
+
# meta['unlistable2'] = EsuApi::Metadata.new( "unlistable2", "bar2 bar2", false )
|
339
|
+
# acl = createAcl
|
340
|
+
# op = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
|
341
|
+
# id = @esu.create_object_on_path( op, acl, meta, "object content", "text/plain" )
|
342
|
+
#
|
343
|
+
# om = @esu.get_object_metadata( op )
|
344
|
+
#
|
345
|
+
# check_acl( acl, om.acl )
|
346
|
+
# assert_equal( "text/plain", om.mimetype, "wrong mimetype" )
|
347
|
+
# assert_equal( "foo", om.meta["listable"].value, "Value of listable wrong" )
|
348
|
+
# assert_equal( "bar", om.meta["unlistable"].value, "Value of unlistable wrong" )
|
349
|
+
# assert_equal( "foo2 foo2", om.meta["listable2"].value, "Value of listable2 wrong" )
|
350
|
+
# assert_equal( "bar2 bar2", om.meta["unlistable2"].value, "Value of unlistable2 wrong" )
|
351
|
+
# end
|
352
|
+
#
|
353
|
+
# def test_get_shareable_url()
|
354
|
+
# text = "The quick brown fox jumped over the lazy dog"
|
355
|
+
# id = @esu.create_object( nil, nil, text, 'text/plain' )
|
356
|
+
# @cleanup.push( id )
|
357
|
+
#
|
358
|
+
# expires = Time.new()
|
359
|
+
# expires += 3600
|
360
|
+
# url = @esu.get_shareable_url( id, expires )
|
361
|
+
#
|
362
|
+
# uri = URI.parse( url )
|
363
|
+
# io = uri.open()
|
364
|
+
#
|
365
|
+
# assert_equal( text, io.readlines, "object content wrong" )
|
366
|
+
# end
|
367
|
+
#
|
368
|
+
# def test_read_object_stream()
|
369
|
+
# text = "The quick brown fox jumped over the lazy dog"
|
370
|
+
# id = @esu.create_object( nil, nil, text, 'text/plain' )
|
371
|
+
# @cleanup.push( id )
|
372
|
+
#
|
373
|
+
# io = @esu.read_object_stream( id )
|
374
|
+
# assert_equal( text, io.readlines, "object content wrong" )
|
375
|
+
# end
|
376
|
+
#
|
377
|
+
# def test_checksum()
|
378
|
+
# text = "hello world"
|
379
|
+
#
|
380
|
+
# ck = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
|
381
|
+
# ck.update( text )
|
382
|
+
# assert_equal( "SHA0/11/9fce82c34887c1953b40b3a2883e18850c4fa8a6", ck.to_s(), "Checkum test failed" )
|
383
|
+
# end
|
384
|
+
#
|
385
|
+
# def test_create_checksum()
|
386
|
+
# ck = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
|
387
|
+
# ObjectId id = @esu.create_object( nil, nil, "hello world", "text/plain", ck );
|
388
|
+
# @cleanup.push( id )
|
389
|
+
# end
|
390
|
+
#
|
391
|
+
# def test_rename()
|
392
|
+
# op1 = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
|
393
|
+
# op2 = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
|
394
|
+
#
|
395
|
+
# id = @esu.create_object_on_path( op1, nil, nil, "hello world", "text/plain" )
|
396
|
+
# @cleanup.push( id )
|
397
|
+
#
|
398
|
+
# # Rename it
|
399
|
+
# @esu.rename( op1, op2 )
|
400
|
+
#
|
401
|
+
# # Check loading from new name
|
402
|
+
# text = @esu.read_object( op2 )
|
403
|
+
#
|
404
|
+
# assert_equals( "hello world", text, "Renamed object content wrong" )
|
405
|
+
# end
|
406
|
+
#
|
407
|
+
# def test_overwrite()
|
408
|
+
# op1 = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
|
409
|
+
# op2 = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
|
410
|
+
#
|
411
|
+
# id = @esu.create_object_on_path( op1, nil, nil, "hello world", "text/plain" )
|
412
|
+
# @cleanup.push( id )
|
413
|
+
# @esu.create_object_on_path( op2, nil, nil, "you shouldn't see me", "text/plain" )
|
414
|
+
#
|
415
|
+
# # Rename it and overwrite
|
416
|
+
# @esu.rename( op1, op2, true )
|
417
|
+
#
|
418
|
+
# # Wait 5 seconds for server to overwrite object
|
419
|
+
# sleep( 5 )
|
420
|
+
#
|
421
|
+
# # Check loading from new name
|
422
|
+
# text = @esu.read_object( op2 )
|
423
|
+
#
|
424
|
+
# assert_equals( "hello world", text, "Renamed object content wrong" )
|
425
|
+
# end
|
426
|
+
#
|
427
|
+
#
|
428
|
+
# def test_get_service_information()
|
429
|
+
# si = @esu.get_service_information()
|
430
|
+
#
|
431
|
+
# assert_not_nil( si.atmos_version, "Atmos version is nil" )
|
432
|
+
# end
|
433
|
+
#
|
434
|
+
# # Tests readback with checksum verification. In order to test this, create a policy
|
435
|
+
# # with erasure coding and then set a policy selector with "policy=erasure" to invoke
|
436
|
+
# # the erasure coding policy.
|
437
|
+
# def test_read_checksum()
|
438
|
+
# meta = {}
|
439
|
+
# meta["policy"] = EsuApi::Metadata.new( "policy", "erasure", false )
|
440
|
+
# ck = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
|
441
|
+
# id = @esu.create_object( nil, meta, "hello world", "text/plain", ck )
|
442
|
+
# @cleanup.push( id )
|
443
|
+
#
|
444
|
+
# ck2 = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
|
445
|
+
# text = @esu.read_object( id, nil, nil, ck2 )
|
446
|
+
# assert_equal( "hello world", text, "object content wrong" )
|
447
|
+
# assert_equal( ck1.to_s(), ck2.to_s(), "checksums don't match" )
|
448
|
+
# assert_equal( ck2.expected_value, ck2.to_s(), "checksum doesn't match expected value" )
|
449
|
+
# end
|
450
|
+
#
|
451
|
+
# private
|
452
|
+
#
|
453
|
+
# #
|
454
|
+
# # Generate a random string that does not start or end with a space but can
|
455
|
+
# # contain a space.
|
456
|
+
# #
|
457
|
+
# def randomstr( len )
|
458
|
+
# chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + " ".to_a
|
459
|
+
# endchars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
|
460
|
+
# newstr = ""
|
461
|
+
# newstr << endchars[rand(endchars.size-1)]
|
462
|
+
# 2.upto(len-1) { |i| newstr << chars[rand(chars.size-1)] }
|
463
|
+
# newstr << endchars[rand(endchars.size-1)]
|
464
|
+
# return newstr
|
465
|
+
# end
|
466
|
+
#
|
467
|
+
# #
|
468
|
+
# # Creates a file/stream with the given count of
|
469
|
+
# # random characters
|
470
|
+
# #
|
471
|
+
# def createTestStream( len )
|
472
|
+
# tmpfile = Tempfile.new( "esutest" )
|
473
|
+
# @cleanfiles.push( tmpfile )
|
474
|
+
#
|
475
|
+
# tmpfile.open() do |aFile|
|
476
|
+
# aFile << randomstr( len )
|
477
|
+
# end
|
478
|
+
#
|
479
|
+
# return tmpfile
|
480
|
+
# end
|
481
|
+
#
|
482
|
+
# def createAcl
|
483
|
+
# acl = []
|
484
|
+
#
|
485
|
+
# acl.push( EsuApi::Grant.new( EsuApi::Grantee( @uid, EsuApi::Grantee::USER ), EsuApi::Grant::FULL_CONTROL ) )
|
486
|
+
# acl.push( EsuApi::Grant::OTHER, EsuApi::Grant::READ )
|
487
|
+
#
|
488
|
+
# return acl
|
489
|
+
# end
|
490
|
+
#
|
491
|
+
# #
|
492
|
+
# # Check to make sure that all the entries in acl1 exist
|
493
|
+
# # in ACL2. We do it this way because some Atmos servers
|
494
|
+
# # are configured to add default grants to objects
|
495
|
+
# #
|
496
|
+
# def checkAcl( acl1, acl2 )
|
497
|
+
# acl1.each { |entry| assert( acl2.include?(entry), "ACL entry" + entry + " not found in " + acl2 ) }
|
498
|
+
# end
|
499
|
+
end
|