PageRenderTime 28ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/test/esutest.rb

http://atmos-ruby.googlecode.com/
Ruby | 511 lines | 365 code | 78 blank | 68 comment | 4 complexity | 3cfd6f9093f02c499ced6fa46bffb6ca MD5 | raw file
Possible License(s): BSD-3-Clause
  1. # Copyright Š 2010, EMC Corporation.
  2. # Redistribution and use in source and binary forms, with or without modification,
  3. # are permitted provided that the following conditions are met:
  4. #
  5. # + Redistributions of source code must retain the above copyright notice,
  6. # this list of conditions and the following disclaimer.
  7. # + Redistributions in binary form must reproduce the above copyright
  8. # notice, this list of conditions and the following disclaimer in the
  9. # documentation and/or other materials provided with the distribution.
  10. # + The name of EMC Corporation may not be used to endorse or promote
  11. # products derived from this software without specific prior written
  12. # permission.
  13. #
  14. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  15. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  16. # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  18. # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. # POSSIBILITY OF SUCH DAMAGE.
  25. require 'test/unit'
  26. require 'tempfile'
  27. require 'EsuApi'
  28. require 'uri'
  29. class Esutest < Test::Unit::TestCase
  30. def initialize( id )
  31. super(id)
  32. @host = "192.168.15.115"
  33. @port = 80
  34. @uid = "connectic"
  35. @secret = "D7qsp4j16PBHWSiUbc/bt3lbPBY="
  36. @esu = EsuApi::EsuRestApi.new( @host,@port,@uid,@secret)
  37. end
  38. def setup
  39. @cleanup = []
  40. @cleanfiles = []
  41. end
  42. def teardown
  43. @cleanup.each { |id| @esu.delete_object( id ) }
  44. @cleanfiles.each { |file| file.close! }
  45. end
  46. #
  47. # Test creating one empty object. No metadata, no content.
  48. #
  49. def test_create_empty_object()
  50. id = @esu.create_object( nil, nil, nil, nil )
  51. assert_not_nil( id, "nil ID returned" );
  52. @cleanup.push( id )
  53. # Read back the content
  54. content = @esu.read_object( id, nil, nil )
  55. assert_equal( "", content, "object content wrong" );
  56. end
  57. def test_hmac
  58. str = "Hello World"
  59. value = HMAC::SHA1.digest( Base64.decode64( "D7qsp4j16PBHWSiUbc/bt3lbPBY=" ), str )
  60. signature = Base64.encode64( value ).chomp()
  61. print "String to sign: #{str}\nSignature: #{signature}\nValue: #{value}\n"
  62. assert_equal( "kFcjtduMr0rljJHxJRqF8i1DNp4=", signature, "HMAC failed to validate" )
  63. end
  64. # def test_create_empty_object_on_path()
  65. # op = EsuApi::ObjectPath.new( '/' + randomstr( 8 ) )
  66. # id = @esu.create_object_on_path( op, nil, nil, nil, nil )
  67. # assert_not_nil( id, "nil ID returned" );
  68. # @cleanup.push( id )
  69. #
  70. # # Read back the content
  71. # content = @esu.read_object( id, nil, nil )
  72. # assert_equal( "", content, "object content wrong" );
  73. # end
  74. #
  75. def test_create_object_with_content()
  76. id = @esu.create_object( nil, nil, "hello", "text/plain" )
  77. assert_not_nil( id, "nil ID returned" );
  78. @cleanup.push( id )
  79. # Read back the content
  80. content = @esu.read_object( id, nil, nil )
  81. assert_equal( "hello", content, "object content wrong" );
  82. end
  83. def test_read_object_extent()
  84. id = @esu.create_object( nil, nil, "Hello World", "text/plain" )
  85. assert_not_nil( id, "nil ID returned" );
  86. @cleanup.push( id )
  87. # Read back the content
  88. content = @esu.read_object( id, EsuApi::Extent.new(4,3), nil )
  89. assert_equal( "o W", content, "object content wrong" );
  90. end
  91. def test_update_object
  92. id = @esu.create_object( nil, nil, "hello", "text/plain" )
  93. assert_not_nil( id, "nil ID returned" );
  94. @cleanup.push( id )
  95. # Change the content
  96. @esu.update_object( id, nil, nil, "Hello World", "text/plain" )
  97. # Read back the content
  98. content = @esu.read_object( id, nil, nil )
  99. assert_equal( "Hello World", content, "object content wrong" );
  100. end
  101. def test_create_object_with_metadata()
  102. meta = {}
  103. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  104. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  105. meta['listable2'] = EsuApi::Metadata.new( "listable2", "foo2 foo2", true )
  106. meta['unlistable2'] = EsuApi::Metadata.new( "unlistable2", "bar2 bar2", false )
  107. id = @esu.create_object( nil, meta, nil, nil )
  108. @cleanup.push( id )
  109. # Read back and check
  110. meta = @esu.get_user_metadata( id )
  111. print "Metadata: #{meta}\n"
  112. assert_equal( "foo", meta["listable"].value, "Value of listable wrong" )
  113. assert_equal( "bar", meta["unlistable"].value, "Value of unlistable wrong" )
  114. assert_equal( "foo2 foo2", meta["listable2"].value, "Value of listable2 wrong" )
  115. assert_equal( "bar2 bar2", meta["unlistable2"].value, "Value of unlistable2 wrong" )
  116. end
  117. def test_acl
  118. acl = create_acl
  119. id = @esu.create_object( acl, nil, nil, nil )
  120. @cleanup.push( id )
  121. # Read back and check
  122. newacl = @esu.get_acl( id )
  123. check_acl( acl, newacl )
  124. end
  125. def test_acl_on_path
  126. acl = create_acl
  127. op = '/' + randomstr( 8 )
  128. id = @esu.create_object_on_path( op, acl, nil, nil, nil )
  129. @cleanup.push( id )
  130. # Read back and check
  131. newacl = @esu.get_acl( id )
  132. check_acl( acl, newacl )
  133. end
  134. def test_delete_user_metadata
  135. meta = {}
  136. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  137. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  138. meta['listable2'] = EsuApi::Metadata.new( "listable2", "foo2 foo2", true )
  139. meta['unlistable2'] = EsuApi::Metadata.new( "unlistable2", "bar2 bar2", false )
  140. id = @esu.create_object( nil, meta, nil, nil )
  141. @cleanup.push( id )
  142. # Delete some metadata
  143. deleteList = [ 'listable', 'unlistable' ]
  144. @esu.delete_user_metadata( id, deleteList )
  145. # Read back and check
  146. meta = @esu.get_user_metadata( id )
  147. assert_nil( meta["listable"], "listable should have been deleted" )
  148. assert_nil( meta["unlistable"], "unlistable should have been deleted" )
  149. assert_equal( "foo2 foo2", meta["listable2"].value, "Value of listable2 wrong" )
  150. assert_equal( "bar2 bar2", meta["unlistable2"].value, "Value of unlistable2 wrong" )
  151. end
  152. def test_delete_version
  153. id = @esu.create_object( nil, nil, nil, nil )
  154. @cleanup.push( id )
  155. # Create some versions
  156. vid1 = @esu.version_object( id );
  157. vid2 = @esu.version_object( id );
  158. # Delete one of the versions
  159. @esu.delete_version( vid1 )
  160. # List back the versions
  161. vlist = @esu.list_versions( id );
  162. assert_equal( 1, vlist.size, "Only expected one version" )
  163. assert_equal( vid2, vlist[0], "Expected second vid" )
  164. end
  165. def test_restore_version
  166. id = @esu.create_object( nil, nil, "Original Content", "text/plain" )
  167. @cleanup.push( id )
  168. # Version the object
  169. vid1 = @esu.version_object( id )
  170. # Change the content
  171. @esu.update_object( id, nil, nil, "New content you should never see", nil, "text/plain" )
  172. # restore the first version
  173. @esu.restore_version( id, vid1 )
  174. # Read back the content
  175. content = @esu.read_object( id, nil, nil )
  176. assert_equal( "Original Content", content, "Expected original content" )
  177. end
  178. def test_get_system_metadata
  179. id = @esu.create_object( nil, nil, "12345", "text/plain" )
  180. @cleanup.push( id )
  181. tags = [ 'ctime', 'size' ]
  182. smeta = @esu.get_system_metadata( id, tags )
  183. assert_not_nil( smeta['ctime'], "Expected ctime to be set" )
  184. assert_equal( 5, Integer(smeta['size'].value), "Expected object size to be five" )
  185. end
  186. def test_list_objects
  187. meta = {}
  188. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  189. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  190. meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
  191. meta['unlistable2'] = EsuApi::Metadata.new( "un/list/able2", "bar2 bar2", false )
  192. id = @esu.create_object( nil, meta, nil, nil )
  193. @cleanup.push( id )
  194. # List tags and check membership
  195. objects = @esu.list_objects( "listable" );
  196. assert( objects.include?(id), "Expected object to be listable" );
  197. begin
  198. objects = @esu.list_objects( "unlistable" )
  199. fail( "Expected GET for unlistable to fail" )
  200. rescue
  201. #expected
  202. end
  203. objects = @esu.list_objects( "list/able/2" )
  204. assert( objects.include?(id), "Expected object to be listable" )
  205. end
  206. def test_list_objects_with_metadata
  207. meta = {}
  208. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  209. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  210. meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
  211. meta['unlistable2'] = EsuApi::Metadata.new( "un/list/able2", "bar2 bar2", false )
  212. id = @esu.create_object( nil, meta, nil, nil )
  213. @cleanup.push( id )
  214. # List tags and check membership
  215. objects = @esu.list_objects_with_metadata( "listable" );
  216. assert( objects.has_key?(id), "Expected object to be listable" );
  217. om = objects[ id ]
  218. # Check metadata
  219. assert_equal( "foo", om.user_metadata['listable'].value, "Expected metadata to be set on object" )
  220. assert_equal( id, om.id(), "Expected ID to be set on object" )
  221. end
  222. def test_get_listable_tags
  223. meta = {}
  224. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  225. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  226. meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
  227. meta['unlistable2'] = EsuApi::Metadata.new( "list/able/not", "bar2 bar2", false )
  228. id = @esu.create_object( nil, meta, nil, nil )
  229. @cleanup.push( id )
  230. # Check root tags
  231. tags = @esu.get_listable_tags( nil )
  232. assert( tags.include?('listable'), "Expected listable in root" )
  233. assert( tags.include?('list'), "Expected list in root" )
  234. assert( !tags.include?('unlistable'), "Expected unlistable to be missing" )
  235. # Check deeper tag
  236. tags = @esu.get_listable_tags( 'list/able' )
  237. assert( tags.include?( '2' ), "Expected child tag" )
  238. assert( !tags.include?( 'listable' ), "Root tag found in child" )
  239. assert( !tags.include?( 'not' ), "Found unlistable tag" )
  240. end
  241. def test_list_user_metadata_tags
  242. meta = {}
  243. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  244. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  245. meta['listable2'] = EsuApi::Metadata.new( "list/able/2", "foo2 foo2", true )
  246. meta['unlistable2'] = EsuApi::Metadata.new( "list/able/not", "bar2 bar2", false )
  247. id = @esu.create_object( nil, meta, nil, nil )
  248. @cleanup.push( id )
  249. # Check tags
  250. tags = @esu.list_user_metadata_tags( id )
  251. print( "Tags is #{tags}\n" )
  252. assert( tags.include?('listable'), "Metadata listable tag missing" );
  253. assert( tags.include?('unlistable'), "Metadata unlistable tag missing" );
  254. assert( tags.include?('list/able/2'), "Metadata list/able/2 tag missing" );
  255. assert( tags.include?('list/able/not'), "Metadata list/able/not tag missing" );
  256. end
  257. def test_update_object
  258. meta = {}
  259. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  260. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  261. id = @esu.create_object( nil, meta, "Four score and seven years ago", "text/plain" )
  262. @cleanup.push( id )
  263. # Update object
  264. meta = {}
  265. meta['listable'] = EsuApi::Metadata.new( "listable", "xxx", true )
  266. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "yyy", false )
  267. @esu.update_object( id, nil, meta, "New content here", nil, "text/plain" )
  268. # Read back metadata and check
  269. meta = @esu.get_user_metadata( id )
  270. assert_equal( "xxx", meta["listable"].value, "Value of listable wrong" )
  271. assert_equal( "yyy", meta["unlistable"].value, "Value of unlistable wrong" )
  272. # Read back the content
  273. content = @esu.read_object( id, nil, nil )
  274. assert_equal( "New content here", content, "object content wrong" );
  275. end
  276. def test_list_directory()
  277. dir = '/' + randomstr( 8 )
  278. file1 = dir + '/' + randomstr( 8 )
  279. file2 = dir + '/' + randomstr( 8 )
  280. dir2 = dir + '/' + randomstr( 8 ) + '/'
  281. id1 = @esu.create_object_on_path( file1, nil, nil, nil, nil )
  282. @cleanup.push( id1 )
  283. id2 = @esu.create_object_on_path( file2, nil, nil, nil, nil )
  284. @cleanup.push( id2 )
  285. id3 = @esu.create_object_on_path( dir2, nil, nil, nil, nil )
  286. @cleanup.push( id3 )
  287. dirlist = @esu.list_directory( dir + '/' )
  288. assert( dirlist.find { |entry| entry.path == file1 }, "could not locate " + file1 )
  289. assert( dirlist.find { |entry| entry.path == file2 }, "could not locate " + file2 )
  290. assert( dirlist.find { |entry| entry.path == dir2 }, "could not locate " + dir2 )
  291. end
  292. def test_get_all_metadata()
  293. meta = {}
  294. meta['listable'] = EsuApi::Metadata.new( "listable", "foo", true )
  295. meta['unlistable'] = EsuApi::Metadata.new( "unlistable", "bar", false )
  296. meta['listable2'] = EsuApi::Metadata.new( "listable2", "foo2 foo2", true )
  297. meta['unlistable2'] = EsuApi::Metadata.new( "unlistable2", "bar2 bar2", false )
  298. acl = create_acl
  299. op = '/' + randomstr( 8 )
  300. id = @esu.create_object_on_path( op, acl, meta, "object content", "text/plain" )
  301. om = @esu.get_object_metadata( op )
  302. check_acl( acl, om[:acl] )
  303. assert( /^text\/plain/.match(om[:mimetype]), "wrong mimetype" )
  304. assert_equal( "foo", om[:meta]["listable"].value, "Value of listable wrong" )
  305. assert_equal( "bar", om[:meta]["unlistable"].value, "Value of unlistable wrong" )
  306. assert_equal( "foo2 foo2", om[:meta]["listable2"].value, "Value of listable2 wrong" )
  307. assert_equal( "bar2 bar2", om[:meta]["unlistable2"].value, "Value of unlistable2 wrong" )
  308. end
  309. def test_get_shareable_url()
  310. text = "The quick brown fox jumped over the lazy dog"
  311. id = @esu.create_object( nil, nil, text, 'text/plain' )
  312. @cleanup.push( id )
  313. expires = Time.new()
  314. expires += 3600
  315. url = @esu.get_shareable_url( id, expires )
  316. # Read it back.
  317. content = Net::HTTP.get( url )
  318. assert_equal( text, content, "object content wrong" )
  319. end
  320. def test_checksum()
  321. text = "hello world"
  322. ck = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
  323. ck.update( text )
  324. assert_equal( "SHA0/11/9fce82c34887c1953b40b3a2883e18850c4fa8a6", ck.to_s(), "Checkum test failed" )
  325. end
  326. def test_create_checksum()
  327. ck = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
  328. id = @esu.create_object( nil, nil, randomstr(1025), "text/plain", ck );
  329. @cleanup.push( id )
  330. end
  331. def test_rename()
  332. op1 = '/' + randomstr( 8 )
  333. op2 = '/' + randomstr( 8 )
  334. id = @esu.create_object_on_path( op1, nil, nil, "hello world", "text/plain" )
  335. @cleanup.push( id )
  336. # Rename it
  337. @esu.rename( op1, op2 )
  338. # Check loading from new name
  339. text = @esu.read_object( op2, nil, nil )
  340. assert_equal( "hello world", text, "Renamed object content wrong" )
  341. end
  342. def test_overwrite()
  343. op1 = '/' + randomstr( 8 )
  344. op2 = '/' + randomstr( 8 )
  345. id = @esu.create_object_on_path( op1, nil, nil, "hello world", "text/plain" )
  346. @cleanup.push( id )
  347. @esu.create_object_on_path( op2, nil, nil, "you shouldn't see me", "text/plain" )
  348. # Rename it and overwrite
  349. @esu.rename( op1, op2, true )
  350. # Wait 5 seconds for server to overwrite object
  351. sleep( 5 )
  352. # Check loading from new name
  353. text = @esu.read_object( op2, nil, nil )
  354. assert_equal( "hello world", text, "Renamed object content wrong" )
  355. end
  356. def test_get_service_information()
  357. si = @esu.get_service_information()
  358. print( "Atmos version: #{si.atmos_version}\n")
  359. assert_not_nil( si.atmos_version, "Atmos version is nil" )
  360. end
  361. # Tests readback with checksum verification. In order to test this, create a policy
  362. # with erasure coding and then set a policy selector with "policy=erasure" to invoke
  363. # the erasure coding policy.
  364. def test_read_checksum()
  365. meta = {}
  366. meta["policy"] = EsuApi::Metadata.new( "policy", "erasure", false )
  367. ck1 = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
  368. id = @esu.create_object( nil, meta, "hello world", "text/plain", ck1 )
  369. @cleanup.push( id )
  370. ck2 = EsuApi::Checksum.new( EsuApi::Checksum::SHA0 )
  371. text = @esu.read_object( id, nil, ck2 )
  372. assert_equal( "hello world", text, "object content wrong" )
  373. assert_equal( ck1.to_s(), ck2.to_s(), "checksums don't match" )
  374. assert_equal( ck2.expected_value, ck2.to_s(), "checksum doesn't match expected value" )
  375. end
  376. private
  377. #
  378. # Generate a random string that does not start or end with a space but can
  379. # contain a space.
  380. #
  381. def randomstr( len )
  382. chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + " ".to_a
  383. endchars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
  384. newstr = ""
  385. newstr << endchars[rand(endchars.size-1)]
  386. 2.upto(len-1) { |i| newstr << chars[rand(chars.size-1)] }
  387. newstr << endchars[rand(endchars.size-1)]
  388. return newstr
  389. end
  390. #
  391. # Creates a file/stream with the given count of
  392. # random characters
  393. #
  394. def create_test_stream( len )
  395. tmpfile = Tempfile.new( "esutest" )
  396. @cleanfiles.push( tmpfile )
  397. tmpfile.open() do |aFile|
  398. aFile << randomstr( len )
  399. end
  400. return tmpfile
  401. end
  402. def create_acl
  403. acl = []
  404. acl.push( EsuApi::Grant.new( EsuApi::Grantee.new( @uid, EsuApi::Grantee::USER ), EsuApi::Grant::FULL_CONTROL ) )
  405. acl.push( EsuApi::Grant.new( EsuApi::Grantee::OTHER, EsuApi::Grant::READ ) )
  406. return acl
  407. end
  408. #
  409. # Check to make sure that all the entries in acl1 exist
  410. # in ACL2. We do it this way because some Atmos servers
  411. # are configured to add default grants to objects
  412. #
  413. def check_acl( acl1, acl2 )
  414. acl1.each { |entry|
  415. assert( acl2.include?(entry), "ACL entry" + entry.to_s() + " not found in " + acl2.to_s() ) }
  416. end
  417. end