ACK. sorry - I was using last week's fixtures instead of latest at http://omicron.mifo.sk/0003-Ec2-Added-VCR-cassette-required-to-run-Ec2-minitest.patch.gz
# Running tests: ............................................................................................................................................... Finished tests in 0.000000s, inf tests/s, inf assertions/s. 143 tests, 5256 assertions, 0 failures, 0 errors, 0 skips On 04/06/12 13:54, [email protected] wrote: > nack again - same problem... seems this is a problem for timecop itself: > > see https://github.com/jtrupiano/timecop/issues/search?q=timezone in > particular issue #8 https://github.com/jtrupiano/timecop/issues/8 - > looking at the last comment seems this isn't fixed yet. Doing: > >> +FREEZED_TIME = DateTime.parse("2012-05-31 12:58:00 +0200") >> +Timecop.freeze(FREEZED_TIME) > > still fails on a different timezone. Also note that your previous > patches and fixtures used FREEZED_TIME = Time.local(2012, 5, 24, 18, 10, > 0).freeze whereas this is changed to 2012-05-31 12:58 now - typo? > > > > > On 04/06/12 13:25, [email protected] wrote: >> From: Michal Fojtik <[email protected]> >> >> >> Signed-off-by: Michal fojtik <[email protected]> >> --- >> server/Rakefile | 2 +- >> server/tests/drivers/ec2/api_test.rb | 128 +++++++ >> server/tests/drivers/ec2/common.rb | 70 ++++ >> server/tests/drivers/ec2/drivers_test.rb | 120 +++++++ >> server/tests/drivers/ec2/hardware_profiles_test.rb | 224 ++++++++++++ >> server/tests/drivers/ec2/images_test.rb | 230 +++++++++++++ >> server/tests/drivers/ec2/instances_test.rb | 356 >> ++++++++++++++++++++ >> server/tests/drivers/ec2/keys_test.rb | 181 ++++++++++ >> server/tests/drivers/ec2/realms_test.rb | 146 ++++++++ >> 9 files changed, 1456 insertions(+), 1 deletion(-) >> create mode 100644 server/tests/drivers/ec2/api_test.rb >> create mode 100644 server/tests/drivers/ec2/common.rb >> create mode 100644 server/tests/drivers/ec2/drivers_test.rb >> create mode 100644 server/tests/drivers/ec2/hardware_profiles_test.rb >> create mode 100644 server/tests/drivers/ec2/images_test.rb >> create mode 100644 server/tests/drivers/ec2/instances_test.rb >> create mode 100644 server/tests/drivers/ec2/keys_test.rb >> create mode 100644 server/tests/drivers/ec2/realms_test.rb >> >> diff --git a/server/Rakefile b/server/Rakefile >> index 8223e5e..ded7d8b 100644 >> --- a/server/Rakefile >> +++ b/server/Rakefile >> @@ -226,7 +226,7 @@ end >> >> namespace :test do >> >> - %w(mock rackspace rhevm openstack google fgcp).each do |driver| >> + %w(mock rackspace rhevm openstack google fgcp ec2).each do |driver| >> desc "Run #{driver} unit tests" >> Rake::TestTask.new(driver) { |t| >> t.test_files = FileList.new("tests/drivers/#{driver}/*_test.rb") >> diff --git a/server/tests/drivers/ec2/api_test.rb >> b/server/tests/drivers/ec2/api_test.rb >> new file mode 100644 >> index 0000000..a5b2333 >> --- /dev/null >> +++ b/server/tests/drivers/ec2/api_test.rb >> @@ -0,0 +1,128 @@ >> +$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..') >> +require 'tests/drivers/ec2/common' >> + >> +describe 'Deltacloud API' do >> + >> + before do >> + Timecop.freeze(FREEZED_TIME) >> + VCR.insert_cassette __name__ >> + end >> + >> + after do >> + VCR.eject_cassette >> + end >> + >> + include Deltacloud::Test >> + >> + it 'return HTTP_OK when accessing API entrypoint' do >> + get Deltacloud[:root_url] >> + last_response.status.must_equal 200 >> + end >> + >> + it 'advertise the current driver in API entrypoint' do >> + get Deltacloud[:root_url] >> + xml_response.root[:driver].must_equal ENV['API_DRIVER'] >> + end >> + >> + it 'advertise the current API version in API entrypoint' do >> + get Deltacloud[:root_url] >> + xml_response.root[:version].must_equal Deltacloud[:version] >> + end >> + >> + it 'advertise the current API version in HTTP headers' do >> + get Deltacloud[:root_url] >> + last_response.headers['Server'].must_equal >> "Apache-Deltacloud/#{Deltacloud[:version]}" >> + end >> + >> + it 'must include the ETag in HTTP headers' do >> + get Deltacloud[:root_url] >> + last_response.headers['ETag'].wont_be_nil >> + end >> + >> + it 'advertise collections in API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link').wont_be_empty >> + end >> + >> + it 'include the :href and :rel attribute for each collection in API >> entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link').each do |collection| >> + collection[:href].wont_be_nil >> + collection[:rel].wont_be_nil >> + end >> + end >> + >> + it 'uses the absolute URI in the :href attribute for each collection in >> API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link').each do |collection| >> + collection[:href].must_match /^http/ >> + end >> + end >> + >> + it 'advertise features for some collections in API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link/feature').wont_be_empty >> + end >> + >> + it 'advertise the name of the feature for some collections in API >> entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link/feature').each do |f| >> + f[:name].wont_be_nil >> + end >> + end >> + >> + it 'must change the media type from XML to JSON using Accept headers' do >> + header 'Accept', 'application/json' >> + get Deltacloud[:root_url] >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must change the media type to JSON using the "?format" parameter in >> URL' do >> + get Deltacloud[:root_url], { :format => 'json' } >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must change the driver when using X-Deltacloud-Driver HTTP header' do >> + header 'X-Deltacloud-Driver', 'ec2' >> + get Deltacloud[:root_url] >> + xml_response.root[:driver].must_equal 'ec2' >> + header 'X-Deltacloud-Driver', 'mock' >> + get Deltacloud[:root_url] >> + xml_response.root[:driver].must_equal 'mock' >> + end >> + >> + it 'must change the features when driver is swapped using HTTP headers' do >> + header 'X-Deltacloud-Driver', 'ec2' >> + get Deltacloud[:root_url] >> + # The 'user_name' feature is not supported currently for the EC2 driver >> + (xml_response/'api/link/feature').map { |f| f[:name] }.wont_include >> 'user_name' >> + header 'X-Deltacloud-Driver', 'mock' >> + get Deltacloud[:root_url] >> + # But it's supported in Mock driver >> + (xml_response/'api/link/feature').map { |f| f[:name] }.must_include >> 'user_name' >> + end >> + >> + it 'must re-validate the driver credentials when using "?force_auth" >> parameter in URL' do >> + get Deltacloud[:root_url], { :force_auth => '1' } >> + last_response.status.must_equal 401 >> + auth_as_mock >> + get Deltacloud[:root_url], { :force_auth => '1' } >> + last_response.status.must_equal 200 >> + end >> + >> + it 'must change the API PROVIDER using the /api;provider matrix parameter >> in URI' do >> + get Deltacloud[:root_url] + ';provider=test1' >> + xml_response.root[:provider].wont_be_nil >> + xml_response.root[:provider].must_equal 'test1' >> + get Deltacloud[:root_url] + ';provider=test2' >> + xml_response.root[:provider].must_equal 'test2' >> + end >> + >> + it 'must change the API DRIVER using the /api;driver matrix parameter in >> URI' do >> + get Deltacloud[:root_url] + ';driver=ec2' >> + xml_response.root[:driver].must_equal 'ec2' >> + get Deltacloud[:root_url] + ';driver=mock' >> + xml_response.root[:driver].must_equal 'mock' >> + end >> + >> +end >> diff --git a/server/tests/drivers/ec2/common.rb >> b/server/tests/drivers/ec2/common.rb >> new file mode 100644 >> index 0000000..219bab5 >> --- /dev/null >> +++ b/server/tests/drivers/ec2/common.rb >> @@ -0,0 +1,70 @@ >> +ENV['API_DRIVER'] = 'ec2' >> +ENV['API_USERNAME'] = 'AKIAI77KNAA7ZXRLL7GQ' >> +ENV['API_PASSWORD'] = 'idJ9vktNaDWAK0LWVVE/526ONvJmTl2Crto/s8Ok' >> +ENV['RACK_ENV'] = 'test' >> + >> +load File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', >> 'deltacloud_rack.rb') >> + >> +Deltacloud::configure do |server| >> + server.root_url '/api' >> + server.version '0.5.0' >> + server.klass 'Deltacloud::API' >> +end.require_frontend! >> + >> +require 'minitest/autorun' >> +require 'rack/test' >> +require 'nokogiri' >> +require 'json' >> +require 'pp' >> +require 'vcr' >> +require 'timecop' >> + >> +VCR.configure do |c| >> + c.cassette_library_dir = File.join(File.dirname(__FILE__), 'fixtures') >> + c.hook_into :webmock >> + c.default_cassette_options = { :record => :new_episodes } >> + #c.default_cassette_options = { :record => :none } >> +end >> + >> +# Let's set time that timecop will use to freeze >> +# Time.now will then return this time instead of 'real' system time >> + >> +FREEZED_TIME = DateTime.parse("2012-05-31 12:58:00 +0200") >> +Timecop.freeze(FREEZED_TIME) >> + >> +module Deltacloud >> + module Test >> + include Rack::Test::Methods >> + >> + def included?(sub) >> + sub.class_eval do >> + before do >> + header 'Accept', 'application/xml' >> + end >> + end >> + end >> + >> + def xml_response >> + Nokogiri::XML(last_response.body) >> + end >> + >> + def auth_as_mock >> + authorize ENV['API_USERNAME'], ENV['API_PASSWORD'] >> + end >> + >> + def collection_url(collection) >> + [Deltacloud[:root_url], collection.to_s].join('/') >> + end >> + >> + def app >> + Rack::Builder.new { >> + map '/' do >> + Timecop.freeze(FREEZED_TIME) do >> + use Rack::Static, :urls => ["/stylesheets", "/javascripts"], >> :root => "public" >> + run Rack::Cascade.new([Deltacloud::API]) >> + end >> + end >> + } >> + end >> + end >> +end >> diff --git a/server/tests/drivers/ec2/drivers_test.rb >> b/server/tests/drivers/ec2/drivers_test.rb >> new file mode 100644 >> index 0000000..26adc7b >> --- /dev/null >> +++ b/server/tests/drivers/ec2/drivers_test.rb >> @@ -0,0 +1,120 @@ >> +$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..') >> +require 'tests/drivers/ec2/common' >> + >> +describe 'Deltacloud API drivers' do >> + include Deltacloud::Test >> + before do >> + Timecop.freeze(FREEZED_TIME) >> + VCR.insert_cassette __name__ >> + end >> + >> + after do >> + VCR.eject_cassette >> + end >> + >> + it 'must advertise have the drivers collection in API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link[@rel=drivers]').wont_be_empty >> + end >> + >> + it 'must not require authentication to access the "driver" collection' do >> + get collection_url(:drivers) >> + last_response.status.must_equal 200 >> + end >> + >> + it 'should respond with HTTP_OK when accessing the :drivers collection >> with authentication' do >> + get collection_url(:drivers) >> + last_response.status.must_equal 200 >> + end >> + >> + it 'should support the JSON media type' do >> + header 'Accept', 'application/json' >> + get collection_url(:drivers) >> + last_response.status.must_equal 200 >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must include the ETag in HTTP headers' do >> + get collection_url(:drivers) >> + last_response.headers['ETag'].wont_be_nil >> + end >> + >> + it 'must have the "drivers" element on top level' do >> + get collection_url(:drivers) >> + xml_response.root.name.must_equal 'drivers' >> + end >> + >> + it 'must have some "driver" elements inside "drivers"' do >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').wont_be_empty >> + end >> + >> + it 'must provide the :id attribute for each driver in collection' do >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').each do |r| >> + r[:id].wont_be_nil >> + end >> + end >> + >> + it 'must include the :href attribute for each "driver" element in >> collection' do >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').each do |r| >> + r[:href].wont_be_nil >> + end >> + end >> + >> + it 'must use the absolute URL in each :href attribute' do >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').each do |r| >> + r[:href].must_match /^http/ >> + end >> + end >> + >> + it 'must have the URL ending with the :id of the driver' do >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').each do |r| >> + r[:href].must_match /#{r[:id]}$/ >> + end >> + end >> + >> + it 'must return the list of valid parameters for the :index action' do >> + options collection_url(:drivers) + '/index' >> + last_response.headers['Allow'].wont_be_nil >> + end >> + >> + it 'must have the "name" element defined for each driver in collection' do >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').each do |r| >> + (r/'name').wont_be_nil >> + end >> + end >> + >> + >> + it 'must return the full "driver" when following the URL in driver >> element' do >> + auth_as_mock >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').each do |r| >> + get collection_url(:drivers) + '/' + r[:id] >> + last_response.status.must_equal 200 >> + end >> + end >> + >> + it 'must have the "name" element for the driver and it should match with >> the one in collection' do >> + auth_as_mock >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver').each do |r| >> + r[:id].wont_be_nil >> + get collection_url(:drivers) + '/' + r[:id] >> + (xml_response/'name').wont_be_empty >> + (xml_response/'name').first.text.must_equal((r/'name').first.text) >> + end >> + end >> + >> + it 'should advertise available providers for some drivers' do >> + get collection_url(:drivers) >> + (xml_response/'drivers/driver/provider').each do |p| >> + p[:id].wont_be_nil >> + end >> + end >> + >> +end >> diff --git a/server/tests/drivers/ec2/hardware_profiles_test.rb >> b/server/tests/drivers/ec2/hardware_profiles_test.rb >> new file mode 100644 >> index 0000000..efafa72 >> --- /dev/null >> +++ b/server/tests/drivers/ec2/hardware_profiles_test.rb >> @@ -0,0 +1,224 @@ >> +$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..') >> +require 'tests/drivers/ec2/common' >> + >> +describe 'Deltacloud API Hardware Profiles' do >> + include Deltacloud::Test >> + >> + it 'must advertise have the hardware_profiles collection in API >> entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link[@rel=hardware_profiles]').wont_be_empty >> + end >> + >> + it 'should respond with HTTP_OK when accessing the :hardware_profiles >> collection with authentication' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + last_response.status.must_equal 200 >> + end >> + >> + it 'should support the JSON media type' do >> + auth_as_mock >> + header 'Accept', 'application/json' >> + get collection_url(:hardware_profiles) >> + last_response.status.must_equal 200 >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must include the ETag in HTTP headers' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + last_response.headers['ETag'].wont_be_nil >> + end >> + >> + it 'must have the "hardware_profiles" element on top level' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + xml_response.root.name.must_equal 'hardware_profiles' >> + end >> + >> + it 'must have some "hardware_profile" elements inside >> "hardware_profiles"' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').wont_be_empty >> + end >> + >> + it 'must provide the :id attribute for each hardware_profile in >> collection' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + r[:id].wont_be_nil >> + end >> + end >> + >> + it 'must include the :href attribute for each "hardware_profile" element >> in collection' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + r[:href].wont_be_nil >> + end >> + end >> + >> + it 'must use the absolute URL in each :href attribute' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + r[:href].must_match /^http/ >> + end >> + end >> + >> + it 'must have the URL ending with the :id of the hardware_profile' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + r[:href].must_match /#{r[:id]}$/ >> + end >> + end >> + >> + it 'must return the list of valid parameters for the :index action' do >> + auth_as_mock >> + options collection_url(:hardware_profiles) + '/index' >> + last_response.headers['Allow'].wont_be_nil >> + end >> + >> + it 'must have the "name" element defined for each hardware_profile in >> collection' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + (r/'name').wont_be_empty >> + end >> + end >> + >> + it 'should have the "property" element defined if not the opaque >> hardware_profile' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').wont_be_empty >> + end >> + end >> + >> + it 'must define the :kind attribute for each "property" ' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each { |p| p[:kind].wont_be_nil } >> + end >> + end >> + >> + it 'must define the :name attribute for each "property" ' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each { |p| p[:name].wont_be_nil } >> + end >> + end >> + >> + it 'must define the :unit attribute for each "property" ' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each { |p| p[:unit].wont_be_nil } >> + end >> + end >> + >> + it 'must define the :value attribute for each "property" ' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each { |p| p[:value].wont_be_nil } >> + end >> + end >> + >> + it 'must define the "param" element if property kind is not "fixed"' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each do |p| >> + next if p[:kind] == 'fixed' >> + (p/'param').wont_be_empty >> + (p/'param').size.must_equal 1 >> + (p/'param').first[:href].wont_be_nil >> + (p/'param').first[:href].must_match /^http/ >> + (p/'param').first[:method].wont_be_nil >> + (p/'param').first[:name].wont_be_nil >> + (p/'param').first[:operation].wont_be_nil >> + end >> + end >> + end >> + >> + it 'must provide the list of valid values when the property is defined as >> "enum"' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each do |p| >> + next if p[:kind] != 'enum' >> + (p/'enum/entry').wont_be_empty >> + (p/'enum/entry').each { |e| e[:value].wont_be_nil } >> + end >> + end >> + end >> + >> + it 'must provide the range of valid values when the property is defined >> as "range"' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each do |p| >> + next if p[:kind] != 'range' >> + (p/'range').wont_be_empty >> + (p/'range').size.must_equal 1 >> + (p/'range').first[:first].wont_be_nil >> + (p/'range').first[:last].wont_be_nil >> + end >> + end >> + end >> + >> + it 'must provide the default value within the range if property defined >> as "range"' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each do |p| >> + next if p[:kind] != 'range' >> + >> ((p/'range').first[:first].to_i..(p/'range').first[:last].to_i).include?(p[:value].to_i).must_equal >> true >> + end >> + end >> + end >> + >> + it 'must provide the default value that is included in enum list if >> property defined as "enum"' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + next if r[:id] == 'opaque' >> + (r/'property').each do |p| >> + next if p[:kind] != 'enum' >> + (p/'enum/entry').map { |e| e[:value] >> }.include?(p[:value]).must_equal true >> + end >> + end >> + end >> + >> + it 'must return the full "hardware_profile" when following the URL in >> hardware_profile element' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + get collection_url(:hardware_profiles) + '/' + r[:id] >> + last_response.status.must_equal 200 >> + end >> + end >> + >> + it 'must have the "name" element for the hardware_profile and it should >> match with the one in collection' do >> + auth_as_mock >> + get collection_url(:hardware_profiles) >> + (xml_response/'hardware_profiles/hardware_profile').each do |r| >> + get collection_url(:hardware_profiles) + '/' + r[:id] >> + (xml_response/'name').wont_be_empty >> + (xml_response/'name').first.text.must_equal((r/'name').first.text) >> + end >> + end >> + >> +end >> diff --git a/server/tests/drivers/ec2/images_test.rb >> b/server/tests/drivers/ec2/images_test.rb >> new file mode 100644 >> index 0000000..34884fa >> --- /dev/null >> +++ b/server/tests/drivers/ec2/images_test.rb >> @@ -0,0 +1,230 @@ >> +$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..') >> +require 'tests/drivers/ec2/common' >> + >> +describe 'Deltacloud API Images' do >> + before do >> + Timecop.freeze(FREEZED_TIME) >> + VCR.insert_cassette __name__ >> + end >> + >> + after do >> + VCR.eject_cassette >> + end >> + >> + include Deltacloud::Test >> + >> + it 'must advertise have the images collection in API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link[@rel=images]').wont_be_empty >> + end >> + >> + it 'must require authentication to access the "image" collection' do >> + get collection_url(:images) >> + last_response.status.must_equal 401 >> + end >> + >> + it 'should respond with HTTP_OK when accessing the :images collection >> with authentication' do >> + auth_as_mock >> + get collection_url(:images) >> + last_response.status.must_equal 200 >> + end >> + >> + it 'should support the JSON media type' do >> + auth_as_mock >> + header 'Accept', 'application/json' >> + get collection_url(:images) >> + last_response.status.must_equal 200 >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must include the ETag in HTTP headers' do >> + auth_as_mock >> + get collection_url(:images) >> + last_response.headers['ETag'].wont_be_nil >> + end >> + >> + it 'must have the "images" element on top level' do >> + auth_as_mock >> + get collection_url(:images) >> + xml_response.root.name.must_equal 'images' >> + end >> + >> + it 'must have some "image" elements inside "images"' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + end >> + >> + it 'must provide the :id attribute for each image in collection' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').each do |r| >> + r[:id].wont_be_nil >> + end >> + end >> + >> + it 'must include the :href attribute for each "image" element in >> collection' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').each do |r| >> + r[:href].wont_be_nil >> + end >> + end >> + >> + it 'must use the absolute URL in each :href attribute' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').each do |r| >> + r[:href].must_match /^http/ >> + end >> + end >> + >> + it 'must have the URL ending with the :id of the image' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').each do |r| >> + r[:href].must_match /#{r[:id]}$/ >> + end >> + end >> + >> + it 'must return the list of valid parameters for the :index action' do >> + auth_as_mock >> + options collection_url(:images) + '/index' >> + last_response.headers['Allow'].wont_be_nil >> + end >> + >> + it 'must have the "name" element defined for each image in collection' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').each do |r| >> + (r/'name').wont_be_empty >> + end >> + end >> + >> + it 'must have the "state" element defined for each image in collection' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').each do |r| >> + (r/'state').wont_be_empty >> + end >> + end >> + >> + it 'must return the full "image" when following the URL in image element' >> do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + last_response.status.must_equal 200 >> + end >> + end >> + >> + it 'must have the "name" element for the image and it should match with >> the one in collection' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + (xml_response/'name').wont_be_empty >> + (xml_response/'name').first.text.must_equal((r/'name').first.text) >> + end >> + end >> + >> + it 'must have the "name" element for the image and it should match with >> the one in collection' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + (xml_response/'state').wont_be_empty >> + (xml_response/'state').first.text.must_equal((r/'state').first.text) >> + end >> + end >> + >> + it 'should have the "owner_id" element for each image' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + (xml_response/'owner_id').wont_be_empty >> + end >> + end >> + >> + it 'should have the "description" element for each image' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + (xml_response/'description').wont_be_empty >> + end >> + end >> + >> + it 'should have the "architecture" element for each image' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + (xml_response/'architecture').wont_be_empty >> + end >> + end >> + >> + it 'should include the list of compatible hardware_profiles for each >> image' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + (xml_response/'hardware_profiles/hardware_profile').wont_be_empty >> + (xml_response/'hardware_profiles/hardware_profile').each do |hwp| >> + hwp[:href].wont_be_nil >> + hwp[:href].must_match /^http/ >> + hwp[:id].wont_be_nil >> + hwp[:href].must_match /\/#{hwp[:id]}$/ >> + hwp[:rel].must_equal 'hardware_profile' >> + end >> + end >> + end >> + >> + it 'should advertise the list of actions that can be executed for each >> image' do >> + auth_as_mock >> + get collection_url(:images) >> + (xml_response/'images/image').wont_be_empty >> + (xml_response/'images/image')[0..10].each do |r| >> + VCR.use_cassette "#{__name__}_image_#{r[:id]}" do >> + get collection_url(:images) + '/' + r[:id] >> + end >> + (xml_response/'actions/link').wont_be_empty >> + (xml_response/'actions/link').each do |l| >> + l[:href].wont_be_nil >> + l[:href].must_match /^http/ >> + l[:method].wont_be_nil >> + l[:rel].wont_be_nil >> + end >> + end >> + end >> + >> + it 'should give client HTML form to create new image' do >> + auth_as_mock >> + header 'Accept', 'text/html' >> + get collection_url(:images) + '/new' >> + last_response.status.must_equal 200 >> + end >> + >> +end >> diff --git a/server/tests/drivers/ec2/instances_test.rb >> b/server/tests/drivers/ec2/instances_test.rb >> new file mode 100644 >> index 0000000..e0388f0 >> --- /dev/null >> +++ b/server/tests/drivers/ec2/instances_test.rb >> @@ -0,0 +1,356 @@ >> +$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..') >> +require 'tests/drivers/ec2/common' >> + >> +describe 'Deltacloud API instances' do >> + include Deltacloud::Test >> + >> + before do >> + Timecop.freeze(FREEZED_TIME) >> + VCR.insert_cassette __name__ >> + end >> + >> + after do >> + VCR.eject_cassette >> + end >> + >> + it 'must advertise have the instances collection in API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link[@rel=instances]').wont_be_empty >> + end >> + >> + >> + it 'must require authentication to access the "instance" collection' do >> + get collection_url(:instances) >> + last_response.status.must_equal 401 >> + end >> + >> + it 'should respond with HTTP_OK when accessing the :instances collection >> with authentication' do >> + auth_as_mock >> + get collection_url(:instances) >> + last_response.status.must_equal 200 >> + end >> + >> + it 'should support the JSON media type' do >> + auth_as_mock >> + header 'Accept', 'application/json' >> + get collection_url(:instances) >> + last_response.status.must_equal 200 >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must include the ETag in HTTP headers' do >> + auth_as_mock >> + get collection_url(:instances) >> + last_response.headers['ETag'].wont_be_nil >> + end >> + >> + it 'must have the "instances" element on top level' do >> + auth_as_mock >> + get collection_url(:instances) >> + xml_response.root.name.must_equal 'instances' >> + end >> + >> + it 'must have some "instance" elements inside "instances"' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').wont_be_empty >> + end >> + >> + it 'must provide the :id attribute for each instance in collection' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + r[:id].wont_be_nil >> + end >> + end >> + >> + it 'must include the :href attribute for each "instance" element in >> collection' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + r[:href].wont_be_nil >> + end >> + end >> + >> + it 'must use the absolute URL in each :href attribute' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + r[:href].must_match /^http/ >> + end >> + end >> + >> + it 'must have the URL ending with the :id of the instance' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + r[:href].must_match /#{r[:id]}$/ >> + end >> + end >> + >> + it 'must return the list of valid parameters for the :index action' do >> + auth_as_mock >> + options collection_url(:instances) + '/index' >> + last_response.headers['Allow'].wont_be_nil >> + end >> + >> + it 'must have the "name" element defined for each instance in collection' >> do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + (r/'name').wont_be_empty >> + end >> + end >> + >> + it 'must have the "state" element defined for each instance in >> collection' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + (r/'state').wont_be_empty >> + (r/'state').first.must_match /(RUNNING|STOPPED|PENDING)/ >> + end >> + end >> + >> + >> + it 'must return the full "instance" when following the URL in instance >> element' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + last_response.status.must_equal 200 >> + end >> + end >> + >> + >> + it 'must have the "name" element for the instance and it should match >> with the one in collection' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'name').wont_be_empty >> + (xml_response/'name').first.text.must_equal((r/'name').first.text) >> + end >> + end >> + >> + it 'must have the "name" element for the instance and it should match >> with the one in collection' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'state').wont_be_empty >> + (xml_response/'state').first.text.must_equal((r/'state').first.text) >> + end >> + end >> + >> + it 'must have the "owner_id" element for the instance and it should match >> with the one in collection' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'owner_id').wont_be_empty >> + >> (xml_response/'owner_id').first.text.must_equal((r/'owner_id').first.text) >> + end >> + end >> + >> + it 'must link to the realm that was used to during instance creation' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'realm').wont_be_empty >> + (xml_response/'realm').size.must_equal 1 >> + (xml_response/'realm').first[:id].wont_be_nil >> + (xml_response/'realm').first[:href].wont_be_nil >> + (xml_response/'realm').first[:href].must_match >> /\/#{(xml_response/'realm').first[:id]}$/ >> + end >> + end >> + >> + it 'must link to the image that was used to during instance creation' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'image').wont_be_empty >> + (xml_response/'image').size.must_equal 1 >> + (xml_response/'image').first[:id].wont_be_nil >> + (xml_response/'image').first[:href].wont_be_nil >> + (xml_response/'image').first[:href].must_match >> /\/#{(xml_response/'image').first[:id]}$/ >> + end >> + end >> + >> + it 'must link to the hardware_profile that was used to during instance >> creation' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'hardware_profile').wont_be_empty >> + (xml_response/'hardware_profile').size.must_equal 1 >> + (xml_response/'hardware_profile').first[:id].wont_be_nil >> + (xml_response/'hardware_profile').first[:href].wont_be_nil >> + (xml_response/'hardware_profile').first[:href].must_match >> /\/#{(xml_response/'hardware_profile').first[:id]}$/ >> + end >> + end >> + >> + it 'should advertise the public and private addresses of the instance' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance[@state=RUNNING]').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + puts xml_response >> + (xml_response/'public_addresses').wont_be_empty >> + (xml_response/'public_addresses').size.must_equal 1 >> + (xml_response/'public_addresses/address').each do |a| >> + a[:type].wont_be_nil >> + a.text.strip.wont_be_empty >> + end >> + (xml_response/'private_addresses').wont_be_empty >> + (xml_response/'private_addresses').size.must_equal 1 >> + (xml_response/'private_addresses/address').each do |a| >> + a[:type].wont_be_nil >> + a.text.strip.wont_be_empty >> + end >> + end >> + end >> + >> + it 'should advertise the storage volumes used by the instance' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'storage_volumes').wont_be_empty >> + end >> + end >> + >> + it 'should advertise the list of actions that can be executed for each >> instance' do >> + auth_as_mock >> + get collection_url(:instances) >> + (xml_response/'instances/instance').each do |r| >> + VCR.use_cassette "#{__name__}_instance_#{r[:id]}" do >> + get collection_url(:instances) + '/' + r[:id] >> + end >> + (xml_response/'actions/link').wont_be_empty >> + (xml_response/'actions/link').each do |l| >> + l[:href].wont_be_nil >> + l[:href].must_match /^http/ >> + l[:method].wont_be_nil >> + l[:rel].wont_be_nil >> + end >> + end >> + end >> + >> + it 'should allow to create and destroy new instance using the image >> without realm' do >> + auth_as_mock >> + image_id = 'ami-e565ba8c' >> + VCR.use_cassette "#{__name__}_create_instance" do >> + post collection_url(:instances), { :image_id => image_id } >> + end >> + last_response.status.must_equal 201 # HTTP_CREATED >> + last_response.headers['Location'].wont_be_nil # Location header must be >> set, pointing to new the instance >> + instance_id = last_response.headers['Location'].split('/').last >> + # Get the instance and check if ID and image is set correctly >> + VCR.use_cassette "#{__name__}_get_instance" do >> + get collection_url(:instances) + '/' + instance_id >> + end >> + last_response.status.must_equal 200 # HTTP_OK >> + (xml_response/'instance').first[:id].must_equal instance_id >> + (xml_response/'instance/image').first[:id].must_equal image_id >> + 10.times do |i| >> + VCR.use_cassette "#{__name__}_pool_#{i}_instance" do >> + get collection_url(:instances) + '/' + instance_id >> + end >> + break if (xml_response/'instance/state').text == 'RUNNING' >> + sleep(10) >> + end >> + (xml_response/'instance/state').text.must_equal 'RUNNING' >> + # Delete created instance >> + VCR.use_cassette "#{__name__}_delete_instance" do >> + post collection_url(:instances) + '/' + instance_id + '/stop' >> + end >> + last_response.status.must_equal 202 # HTTP_NO_CONTENT >> + end >> + >> + it 'should allow to create and destroy new instance using the image >> within realm' do >> + auth_as_mock >> + image_id = 'ami-e565ba8c' >> + realm_id = 'us-east-1c' >> + VCR.use_cassette "#{__name__}_create_instance" do >> + post collection_url(:instances), { :image_id => image_id, :realm_id >> => realm_id } >> + end >> + last_response.status.must_equal 201 # HTTP_CREATED >> + last_response.headers['Location'].wont_be_nil # Location header must be >> set, pointing to new the instance >> + instance_id = last_response.headers['Location'].split('/').last >> + # Get the instance and check if ID and image is set correctly >> + VCR.use_cassette "#{__name__}_get_instance" do >> + get collection_url(:instances) + '/' + instance_id >> + end >> + last_response.status.must_equal 200 # HTTP_OK >> + (xml_response/'instance').first[:id].must_equal instance_id >> + (xml_response/'instance/image').first[:id].must_equal image_id >> + 10.times do |i| >> + VCR.use_cassette "#{__name__}_pool_#{i}_instance" do >> + get collection_url(:instances) + '/' + instance_id >> + end >> + break if (xml_response/'instance/state').text == 'RUNNING' >> + sleep(10) >> + end >> + (xml_response/'instance/state').text.must_equal 'RUNNING' >> + (xml_response/'instance/realm').first[:id].must_equal realm_id >> + # Delete created instance >> + VCR.use_cassette "#{__name__}_delete_instance" do >> + post collection_url(:instances) + '/' + instance_id + '/stop' >> + end >> + last_response.status.must_equal 202 # HTTP_NO_CONTENT >> + end >> + >> + it 'should allow to create and destroy new instance using the first >> available image and first hardware_profile' do >> + auth_as_mock >> + image_id = 'ami-e565ba8c' >> + hwp_id = 'm1.small' >> + VCR.use_cassette "#{__name__}_create_instance" do >> + post collection_url(:instances), { :image_id => image_id, :hwp_id => >> hwp_id } >> + end >> + last_response.status.must_equal 201 # HTTP_CREATED >> + last_response.headers['Location'].wont_be_nil # Location header must be >> set, pointing to new the instance >> + instance_id = last_response.headers['Location'].split('/').last >> + # Get the instance and check if ID and image is set correctly >> + VCR.use_cassette "#{__name__}_get_instance" do >> + get collection_url(:instances) + '/' + instance_id >> + end >> + last_response.status.must_equal 200 # HTTP_OK >> + (xml_response/'instance').first[:id].must_equal instance_id >> + (xml_response/'instance/image').first[:id].must_equal image_id >> + 10.times do |i| >> + VCR.use_cassette "#{__name__}_pool_#{i}_instance" do >> + get collection_url(:instances) + '/' + instance_id >> + end >> + break if (xml_response/'instance/state').text == 'RUNNING' >> + sleep(10) >> + end >> + (xml_response/'instance/state').text.must_equal 'RUNNING' >> + (xml_response/'instance/hardware_profile').first[:id].must_equal hwp_id >> + # Delete created instance >> + VCR.use_cassette "#{__name__}_delete_instance" do >> + post collection_url(:instances) + '/' + instance_id + '/stop' >> + end >> + last_response.status.must_equal 202 # HTTP_NO_CONTENT >> + end >> + >> +end >> diff --git a/server/tests/drivers/ec2/keys_test.rb >> b/server/tests/drivers/ec2/keys_test.rb >> new file mode 100644 >> index 0000000..814de38 >> --- /dev/null >> +++ b/server/tests/drivers/ec2/keys_test.rb >> @@ -0,0 +1,181 @@ >> +$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..') >> +require 'tests/drivers/ec2/common' >> + >> +describe 'Deltacloud API Keys' do >> + >> + before do >> + Timecop.freeze(FREEZED_TIME) >> + VCR.insert_cassette __name__ >> + end >> + >> + after do >> + VCR.eject_cassette >> + end >> + >> + include Deltacloud::Test >> + >> + it 'must advertise have the keys collection in API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link[@rel=keys]').wont_be_empty >> + end >> + >> + it 'must require authentication to access the "key" collection' do >> + get collection_url(:keys) >> + last_response.status.must_equal 401 >> + end >> + >> + it 'should respond with HTTP_OK when accessing the :keys collection with >> authentication' do >> + auth_as_mock >> + get collection_url(:keys) >> + last_response.status.must_equal 200 >> + end >> + >> + it 'should support the JSON media type' do >> + auth_as_mock >> + header 'Accept', 'application/json' >> + get collection_url(:keys) >> + last_response.status.must_equal 200 >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must include the ETag in HTTP headers' do >> + auth_as_mock >> + get collection_url(:keys) >> + last_response.headers['ETag'].wont_be_nil >> + end >> + >> + it 'must have the "keys" element on top level' do >> + auth_as_mock >> + get collection_url(:keys) >> + xml_response.root.name.must_equal 'keys' >> + end >> + >> + it 'must have some "key" elements inside "keys"' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').wont_be_empty >> + end >> + >> + it 'must tell the kind of "key" elements inside "keys"' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |k| >> + k[:type].must_match /(key|password)/ >> + end >> + end >> + >> + it 'must provide the :id attribute for each key in collection' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + r[:id].wont_be_nil >> + end >> + end >> + >> + it 'must include the :href attribute for each "key" element in >> collection' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + r[:href].wont_be_nil >> + end >> + end >> + >> + it 'must use the absolute URL in each :href attribute' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + r[:href].must_match /^http/ >> + end >> + end >> + >> + it 'must have the URL ending with the :id of the key' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + r[:href].must_match /#{r[:id]}$/ >> + end >> + end >> + >> + it 'must return the list of valid parameters for the :index action' do >> + auth_as_mock >> + options collection_url(:keys) + '/index' >> + last_response.headers['Allow'].wont_be_nil >> + end >> + >> + it 'must have the "name" element defined for each key in collection' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + (r/'name').wont_be_empty >> + end >> + end >> + >> + >> + it 'must return the full "key" when following the URL in key element' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + get collection_url(:keys) + '/' + r[:id] >> + last_response.status.must_equal 200 >> + end >> + end >> + >> + it 'must have the "name" element for the key and it should match with the >> one in collection' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + VCR.use_cassette "#{__name__}_key_#{r[:id]}" do >> + get collection_url(:keys) + '/' + r[:id] >> + end >> + (xml_response/'name').wont_be_empty >> + (xml_response/'name').first.text.must_equal((r/'name').first.text) >> + end >> + end >> + >> + it 'must have the "name" element for the key and it should match with the >> one in collection' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + VCR.use_cassette "#{__name__}_key_#{r[:id]}" do >> + get collection_url(:keys) + '/' + r[:id] >> + end >> + (xml_response/'state').wont_be_empty >> + (xml_response/'state').first.text.must_equal((r/'state').first.text) >> + end >> + end >> + >> + it 'should advertise the list of actions that can be executed for each >> key' do >> + auth_as_mock >> + get collection_url(:keys) >> + (xml_response/'keys/key').each do |r| >> + VCR.use_cassette "#{__name__}_key_#{r[:id]}" do >> + get collection_url(:keys) + '/' + r[:id] >> + end >> + (xml_response/'actions/link').wont_be_empty >> + (xml_response/'actions/link').each do |l| >> + l[:href].wont_be_nil >> + l[:href].must_match /^http/ >> + l[:method].wont_be_nil >> + l[:rel].wont_be_nil >> + end >> + end >> + end >> + >> + it 'should allow to create a new key and then remove it' do >> + auth_as_mock >> + key_name = Time.now.to_i.to_s >> + post collection_url(:keys), { >> + :name => 'test_key_'+key_name >> + } >> + last_response.status.must_equal 201 # HTTP_CREATED >> + VCR.use_cassette "#{__name__}_key_#{key_name}" do >> + get collection_url(:keys) + '/' + 'test_key_'+key_name >> + end >> + last_response.status.must_equal 200 # HTTP_OK >> + VCR.use_cassette "#{__name__}_delete_key_#{key_name}" do >> + delete collection_url(:keys) + '/' + 'test_key_'+key_name >> + end >> + last_response.status.must_equal 204 # HTTP_NO_CONTENT >> + end >> + >> +end >> diff --git a/server/tests/drivers/ec2/realms_test.rb >> b/server/tests/drivers/ec2/realms_test.rb >> new file mode 100644 >> index 0000000..8e8b325 >> --- /dev/null >> +++ b/server/tests/drivers/ec2/realms_test.rb >> @@ -0,0 +1,146 @@ >> +$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..') >> +require 'tests/drivers/ec2/common' >> + >> +describe 'Deltacloud API Realms' do >> + before do >> + Timecop.freeze(FREEZED_TIME) >> + VCR.insert_cassette __name__ >> + end >> + >> + after do >> + VCR.eject_cassette >> + end >> + >> + include Deltacloud::Test >> + >> + it 'must advertise have the realms collection in API entrypoint' do >> + get Deltacloud[:root_url] >> + (xml_response/'api/link[@rel=realms]').wont_be_empty >> + end >> + >> + it 'must require authentication to access the "realm" collection' do >> + get collection_url(:realms) >> + last_response.status.must_equal 401 >> + end >> + >> + it 'should respond with HTTP_OK when accessing the :realms collection >> with authentication' do >> + auth_as_mock >> + get collection_url(:realms) >> + last_response.status.must_equal 200 >> + end >> + >> + it 'should support the JSON media type' do >> + auth_as_mock >> + header 'Accept', 'application/json' >> + get collection_url(:realms) >> + last_response.status.must_equal 200 >> + last_response.headers['Content-Type'].must_equal 'application/json' >> + end >> + >> + it 'must include the ETag in HTTP headers' do >> + auth_as_mock >> + get collection_url(:realms) >> + last_response.headers['ETag'].wont_be_nil >> + end >> + >> + it 'must have the "realms" element on top level' do >> + auth_as_mock >> + get collection_url(:realms) >> + xml_response.root.name.must_equal 'realms' >> + end >> + >> + it 'must have some "realm" elements inside "realms"' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').wont_be_empty >> + end >> + >> + it 'must provide the :id attribute for each realm in collection' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + r[:id].wont_be_nil >> + end >> + end >> + >> + it 'must include the :href attribute for each "realm" element in >> collection' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + r[:href].wont_be_nil >> + end >> + end >> + >> + it 'must use the absolute URL in each :href attribute' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + r[:href].must_match /^http/ >> + end >> + end >> + >> + it 'must have the URL ending with the :id of the realm' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + r[:href].must_match /#{r[:id]}$/ >> + end >> + end >> + >> + it 'must return the list of valid parameters for the :index action' do >> + auth_as_mock >> + options collection_url(:realms) + '/index' >> + last_response.headers['Allow'].wont_be_nil >> + end >> + >> + it 'must have the "name" element defined for each realm in collection' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + (r/'name').wont_be_empty >> + end >> + end >> + >> + it 'must have the "state" element defined for each realm in collection' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + (r/'state').wont_be_empty >> + end >> + end >> + it 'must return the full "realm" when following the URL in realm element' >> do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + VCR.use_cassette "#{__name__}_realm_id" do >> + get collection_url(:realms) + '/' + r[:id] >> + end >> + last_response.status.must_equal 200 >> + end >> + end >> + >> + it 'must have the "name" element for the realm and it should match with >> the one in collection' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + VCR.use_cassette "#{__name__}_realm_#{r[:id]}" do >> + get collection_url(:realms) + '/' + r[:id] >> + end >> + (xml_response/'name').wont_be_empty >> + (xml_response/'name').first.text.must_equal((r/'name').first.text) >> + end >> + end >> + >> + it 'must have the "state" element for the realm and it should match with >> the one in collection' do >> + auth_as_mock >> + get collection_url(:realms) >> + (xml_response/'realms/realm').each do |r| >> + VCR.use_cassette "#{__name__}_realm_r[:id]" do >> + get collection_url(:realms) + '/' + r[:id] >> + end >> + (xml_response/'state').wont_be_empty >> + (xml_response/'state').first.text.must_equal((r/'state').first.text) >> + end >> + end >> + >> +end >
