You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by ma...@redhat.com on 2012/08/01 13:38:14 UTC
[PATCH 1/2] API TESTS - moves common collections tests to separate file
From: marios <ma...@redhat.com>
Signed-off-by: marios <ma...@redhat.com>
---
tests/deltacloud/buckets_test.rb | 135 ++++++++++----------------
tests/deltacloud/common_tests_collections.rb | 105 ++++++++++++++++++++
tests/deltacloud/test_setup.rb | 23 ++++-
3 files changed, 178 insertions(+), 85 deletions(-)
create mode 100644 tests/deltacloud/common_tests_collections.rb
diff --git a/tests/deltacloud/buckets_test.rb b/tests/deltacloud/buckets_test.rb
index e8732b1..e16e743 100644
--- a/tests/deltacloud/buckets_test.rb
+++ b/tests/deltacloud/buckets_test.rb
@@ -61,19 +61,63 @@ describe 'Deltacloud API buckets collection' do
end
}
- it 'must advertise the buckets collection in API entrypoint' do
+ #Run the 'common' tests for all collections defined in common_tests_collections.rb
+ test_collection = "buckets"
+ $:.unshift File.join(File.dirname(__FILE__), '..')
+ eval File.read('deltacloud/common_tests_collections.rb')
- res = get("/").xml
- (res/'api/link[@rel=buckets]').wont_be_empty
+ #Now run the bucket-specific tests:
+ it 'must have the "size" element defined for each bucket in collection' do
+ res = get(BUCKETS, :accept => :xml)
+ (res.xml/'buckets/bucket').each do |r|
+ (r/'size').wont_be_nil
+ (r/'size').wont_be_empty
+ end
end
- it 'must require authentication to access the "bucket" collection' do
- proc { get(BUCKETS, :noauth => true) }.must_raise RestClient::Request::Unauthorized
+ it 'all "blob" elements for the bucket should match the ones in collection' do
+ res = get(BUCKETS, :accept => :xml)
+ (res.xml/'buckets/bucket').each do |r|
+ bucket = get(BUCKETS+"/#{r[:id]}", :accept=>:xml)
+ (bucket.xml/'bucket/blob').each do |b|
+ b[:id].wont_be_nil
+ b[:href].wont_be_nil
+ b[:href].must_match /^http/
+ b[:href].must_match /#{r[:id]}\/#{b[:id]}$/
+ end
+ end
end
- it 'should respond with HTTP_OK when accessing the :buckets collection with authentication' do
- res = get(BUCKETS)
- res.code.must_equal 200
+ it 'must allow to get all blobs details and the details should be set correctly' do
+ res = get(BUCKETS, :accept => :xml)
+ (res.xml/'buckets/bucket').each do |r|
+ bucket = get(BUCKETS+"/#{r[:id]}", :accept=>:xml)
+ (bucket.xml/'bucket/blob').each do |b|
+ blob = get(BUCKETS+"/#{r[:id]}/#{b[:id]}", :accept=>:xml)
+ blob.xml.root.name.must_equal 'blob'
+ blob.xml.root[:id].must_equal b[:id]
+ (blob.xml/'bucket').wont_be_empty
+ (blob.xml/'bucket').size.must_equal 1
+ (blob.xml/'bucket').first.text.wont_be_nil
+ (blob.xml/'bucket').first.text.must_equal r[:id]
+ (blob.xml/'content_length').wont_be_empty
+ (blob.xml/'content_length').size.must_equal 1
+ (blob.xml/'content_length').first.text.must_match /^(\d+)$/
+ (blob.xml/'content_type').wont_be_empty
+ (blob.xml/'content_type').size.must_equal 1
+ (blob.xml/'content_type').first.text.wont_be_nil
+ (blob.xml/'last_modified').wont_be_empty
+ (blob.xml/'last_modified').size.must_equal 1
+ (blob.xml/'last_modified').first.text.wont_be_empty
+ (blob.xml/'content').wont_be_empty
+ (blob.xml/'content').size.must_equal 1
+ (blob.xml/'content').first[:rel].wont_be_nil
+ (blob.xml/'content').first[:rel].must_equal 'blob_content'
+ (blob.xml/'content').first[:href].wont_be_nil
+ (blob.xml/'content').first[:href].must_match /^http/
+ (blob.xml/'content').first[:href].must_match /\/content$/
+ end
+ end
end
it 'should be possible to create bucket with POST /api/buckets and delete it with DELETE /api/buckets/:id' do
@@ -179,64 +223,6 @@ describe 'Deltacloud API buckets collection' do
end
end
- it 'should support the JSON media type' do
- res = get(BUCKETS, :accept=>:json)
- res.code.must_equal 200
- res.headers[:content_type].must_equal 'application/json'
- assert_silent {JSON.parse(res)}
- end
-
- it 'must include the ETag in HTTP headers' do
- res = get(BUCKETS)
- res.headers[:etag].wont_be_nil
- end
-
- it 'must have the "buckets" element on top level' do
- res = get(BUCKETS, :accept=>:xml)
- res.xml.root.name.must_equal 'buckets'
- end
-
- it 'must have some "bucket" elements inside "buckets"' do
- res = get(BUCKETS, :accept=>:xml)
- (res.xml/'buckets/bucket').wont_be_empty
- end
-
- it 'must provide the :id attribute for each bucket in collection' do
- res = get(BUCKETS, :accept=>:xml)
- (res.xml/'buckets/bucket').each do |r|
- r[:id].wont_be_nil
- end
- end
-
- it 'must include the :href attribute for each "bucket" element in collection' do
- res = get(BUCKETS, :accept=>:xml)
- (res.xml/'buckets/bucket').each do |r|
- r[:href].wont_be_nil
- end
- end
-
- it 'must use the absolute URL in each :href attribute' do
- res = get(BUCKETS, :accept=>:xml)
- (res.xml/'buckets/bucket').each do |r|
- r[:href].must_match /^http/
- end
- end
-
- it 'must have the URL ending with the :id of the bucket' do
- res = get(BUCKETS, :accept=>:xml)
- (res.xml/'buckets/bucket').each do |r|
- r[:href].must_match /#{r[:id]}$/
- end
- end
-
- it 'must have the "name" element defined for each bucket in collection' do
- res = get(BUCKETS, :accept => :xml)
- (res.xml/'buckets/bucket').each do |r|
- (r/'name').wont_be_nil
- (r/'name').wont_be_empty
- end
- end
-
it 'must have the "size" element defined for each bucket in collection' do
res = get(BUCKETS, :accept => :xml)
(res.xml/'buckets/bucket').each do |r|
@@ -245,23 +231,6 @@ describe 'Deltacloud API buckets collection' do
end
end
- it 'must return 200 OK when following the URL in bucket element' do
- res = get(BUCKETS, :accept => :xml)
- (res.xml/'buckets/bucket').each do |r|
- bucket_res = get r[:href]
- bucket_res.code.must_equal 200
- end
- end
-
- it 'must have the "name" element for the bucket and it should match with the one in collection' do
- res = get(BUCKETS, :accept => :xml)
- (res.xml/'buckets/bucket').each do |r|
- bucket = get(BUCKETS+"/#{r[:id]}", :accept=>:xml)
- (bucket.xml/'name').wont_be_empty
- (bucket.xml/'name').first.text.must_equal((r/'name').first.text)
- end
- end
-
it 'all "blob" elements for the bucket should match the ones in collection' do
res = get(BUCKETS, :accept => :xml)
(res.xml/'buckets/bucket').each do |r|
diff --git a/tests/deltacloud/common_tests_collections.rb b/tests/deltacloud/common_tests_collections.rb
new file mode 100644
index 0000000..9a98cf5
--- /dev/null
+++ b/tests/deltacloud/common_tests_collections.rb
@@ -0,0 +1,105 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+ it "must advertise the #{test_collection} collection in API entrypoint" do
+ res = get("/").xml
+ (res/"api/link[@rel=#{test_collection}]").wont_be_empty
+ end
+
+ it "must require authentication to access the #{test_collection} collection" do
+ proc { get(test_collection, :noauth => true) }.must_raise RestClient::Request::Unauthorized
+ end
+
+ it "should respond with HTTP_OK when accessing the #{test_collection} collection with authentication" do
+ res = get(test_collection)
+ res.code.must_equal 200
+ end
+
+ it 'should support the JSON media type' do
+ res = get(test_collection, :accept=>:json)
+ res.code.must_equal 200
+ res.headers[:content_type].must_equal 'application/json'
+ assert_silent {JSON.parse(res)}
+ end
+
+ it 'must include the ETag in HTTP headers' do
+ res = get(test_collection)
+ res.headers[:etag].wont_be_nil
+ end
+
+ it "must have the #{test_collection} element on top level" do
+ res = get(test_collection, :accept=>:xml)
+ res.xml.root.name.must_equal test_collection
+ end
+
+ it "must have some #{test_collection.singularize} elements inside #{test_collection} " do
+ res = get(test_collection, :accept=>:xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").wont_be_empty
+ end
+
+ it "must provide the :id attribute for each #{test_collection.singularize} in collection" do
+ res = get(test_collection, :accept=>:xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").each do |r|
+ r[:id].wont_be_nil
+ end
+ end
+
+ it "must include the :href attribute for each #{test_collection} element in collection" do
+ res = get(test_collection, :accept=>:xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").each do |r|
+ r[:href].wont_be_nil
+ end
+ end
+
+ it 'must use the absolute URL in each :href attribute' do
+ res = get(test_collection, :accept=>:xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").each do |r|
+ r[:href].must_match /^http/
+ end
+ end
+
+ it "must have the URL ending with the :id of the #{test_collection.singularize}" do
+ res = get(test_collection, :accept=>:xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").each do |r|
+ r[:href].must_match /#{r[:id]}$/
+ end
+ end
+
+ it "must have the \"name\" element defined for each #{test_collection.singularize} in collection" do
+ res = get(test_collection, :accept => :xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").each do |r|
+ (r/'name').wont_be_nil
+ (r/'name').wont_be_empty
+ end
+ end
+
+ it "must return 200 OK when following the URL in #{test_collection.singularize} element" do
+ res = get(test_collection, :accept => :xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").each do |r|
+ element_res = get r[:href]
+ element_res.code.must_equal 200
+ end
+ end
+
+ it "must have the \"name\" element for the #{test_collection.singularize} and it should match with the one in collection" do
+ res = get(test_collection, :accept => :xml)
+ (res.xml/"#{test_collection}/#{test_collection.singularize}").each do |r|
+ element = get(test_collection+"/#{r[:id]}", :accept=>:xml)
+ (element.xml/'name').wont_be_empty
+ (element.xml/'name').first.text.must_equal((r/'name').first.text)
+ end
+ end
+
diff --git a/tests/deltacloud/test_setup.rb b/tests/deltacloud/test_setup.rb
index a3bae4f..ab95035 100644
--- a/tests/deltacloud/test_setup.rb
+++ b/tests/deltacloud/test_setup.rb
@@ -37,6 +37,14 @@ module RestClient::Response
end
end
+class String
+ def singularize
+ return self.gsub(/ies$/, 'y') if self =~ /ies$/
+ return self.gsub(/es$/, '') if self =~ /sses$/
+ self.gsub(/s$/, '')
+ end
+end
+
module Deltacloud
module Test
@@ -64,6 +72,14 @@ module Deltacloud
@hash[driver]["bucket_locations"]
end
+ def instances_config
+ @hash[driver]["instances"] || {}
+ end
+
+ def preferred_provider
+ @hash[driver]["preferred_provider"]
+ end
+
def driver
xml.root[:driver]
end
@@ -139,6 +155,9 @@ module Deltacloud::Test::Methods
end
def post(path, post_body, params={})
+ if api.preferred_provider and not params[:provider]
+ params[:provider] = api.preferred_provider
+ end
url, headers = process_url_params(path, params)
RestClient.post url, post_body, headers
end
@@ -147,7 +166,7 @@ module Deltacloud::Test::Methods
url, headers = process_url_params(path, params)
if body.is_a?(File)
#set timeouts http://rdoc.info/github/archiloque/rest-client/RestClient/Resource
- resource = RestClient::Resource.new(url, :open_timeout => 10, :timeout=> 9999)
+ resource = RestClient::Resource.new(url, :open_timeout => 120, :timeout=> 9999)
resource.put body.read, headers
else
RestClient.put url, body, headers
@@ -200,7 +219,7 @@ module Deltacloud::Test::Methods
if path =~ /^https?:/
url = path
else
- url = api.url + path
+ url = path.start_with?("/", ";") ? api.url + path : api.url+"/"+ path
end
url += "?" + params.map { |k,v| "#{k}=#{v}" }.join("&") unless params.empty?
if ENV["LOG"] && ENV["LOG"].include?("requests")
--
1.7.6.5
Re: [PATCH 2/2] API TESTS: adds images and instances tests
Posted by David Lutterkort <lu...@redhat.com>.
On Thu, 2012-08-02 at 10:56 +0300, marios@redhat.com wrote:
> On 02/08/12 03:11, David Lutterkort wrote:
> > On Wed, 2012-08-01 at 14:38 +0300, marios@redhat.com wrote:
> >> From: marios <ma...@redhat.com>
> >>
> >>
> >> Signed-off-by: marios <ma...@redhat.com>
> >> ---
> >> tests/config.yaml | 19 ++-
> >> tests/deltacloud/base_api_test.rb | 8 +-
> >> tests/deltacloud/images_test.rb | 75 ++++++++
> >> tests/deltacloud/instances_test.rb | 353 ++++++++++++++++++++++++++++++++++++
> >> 4 files changed, 448 insertions(+), 7 deletions(-)
> >
> > When I run 'rake test:deltacloud' I get a failure in buckets_test.rb:200
> > ("should be possible to GET blob data with
> > GET /api/buckets/:id/blob/content") that kills my server and makes all
> > subsequent tests die with Errno::ECONNREFUSED. The server dies with
> > 'TypeError - can't modify frozen array:' with a very impressive
> > stacktrace (attached)
>
> yes, this is the GET blob content issue I was telling you about and
> which we decided to put on ice until after the testing framework was
> somewhat more complete. I guess I could just skip this test for now
Yes, skipping the test is the right thing for now.
David
Re: [PATCH 2/2] API TESTS: adds images and instances tests
Posted by "marios@redhat.com" <ma...@redhat.com>.
On 02/08/12 03:11, David Lutterkort wrote:
> On Wed, 2012-08-01 at 14:38 +0300, marios@redhat.com wrote:
>> From: marios <ma...@redhat.com>
>>
>>
>> Signed-off-by: marios <ma...@redhat.com>
>> ---
>> tests/config.yaml | 19 ++-
>> tests/deltacloud/base_api_test.rb | 8 +-
>> tests/deltacloud/images_test.rb | 75 ++++++++
>> tests/deltacloud/instances_test.rb | 353 ++++++++++++++++++++++++++++++++++++
>> 4 files changed, 448 insertions(+), 7 deletions(-)
>
> When I run 'rake test:deltacloud' I get a failure in buckets_test.rb:200
> ("should be possible to GET blob data with
> GET /api/buckets/:id/blob/content") that kills my server and makes all
> subsequent tests die with Errno::ECONNREFUSED. The server dies with
> 'TypeError - can't modify frozen array:' with a very impressive
> stacktrace (attached)
yes, this is the GET blob content issue I was telling you about and
which we decided to put on ice until after the testing framework was
somewhat more complete. I guess I could just skip this test for now
>
> Also, can we please not set t.options='-v' in the Rakefile ? People who
> want the extra verbiage can always pass TESTOPT="-v" to rake
>
>> diff --git a/tests/deltacloud/base_api_test.rb b/tests/deltacloud/base_api_test.rb
>> index bd37b46..12e1e4d 100644
>> --- a/tests/deltacloud/base_api_test.rb
>> +++ b/tests/deltacloud/base_api_test.rb
>> @@ -120,17 +120,17 @@ describe "Deltacloud API Entry Point" do
>> end
>>
>> it 'must change the API PROVIDER using the /api;provider matrix parameter in URI' do
>> - res = get(';provider=test1', :public => true)
>> + res = get("\;provider=test1", {:accept=>:xml, :noauth=>true})
>
> Do we really need to escape the ';' in those strings ? Shouldn't be
> necessary.
>
> David
>
Re: [PATCH 2/2] API TESTS: adds images and instances tests
Posted by David Lutterkort <lu...@redhat.com>.
On Wed, 2012-08-01 at 14:38 +0300, marios@redhat.com wrote:
> From: marios <ma...@redhat.com>
>
>
> Signed-off-by: marios <ma...@redhat.com>
> ---
> tests/config.yaml | 19 ++-
> tests/deltacloud/base_api_test.rb | 8 +-
> tests/deltacloud/images_test.rb | 75 ++++++++
> tests/deltacloud/instances_test.rb | 353 ++++++++++++++++++++++++++++++++++++
> 4 files changed, 448 insertions(+), 7 deletions(-)
When I run 'rake test:deltacloud' I get a failure in buckets_test.rb:200
("should be possible to GET blob data with
GET /api/buckets/:id/blob/content") that kills my server and makes all
subsequent tests die with Errno::ECONNREFUSED. The server dies with
'TypeError - can't modify frozen array:' with a very impressive
stacktrace (attached)
Also, can we please not set t.options='-v' in the Rakefile ? People who
want the extra verbiage can always pass TESTOPT="-v" to rake
> diff --git a/tests/deltacloud/base_api_test.rb b/tests/deltacloud/base_api_test.rb
> index bd37b46..12e1e4d 100644
> --- a/tests/deltacloud/base_api_test.rb
> +++ b/tests/deltacloud/base_api_test.rb
> @@ -120,17 +120,17 @@ describe "Deltacloud API Entry Point" do
> end
>
> it 'must change the API PROVIDER using the /api;provider matrix parameter in URI' do
> - res = get(';provider=test1', :public => true)
> + res = get("\;provider=test1", {:accept=>:xml, :noauth=>true})
Do we really need to escape the ';' in those strings ? Shouldn't be
necessary.
David
Re: [PATCH 2/2] API TESTS: adds images and instances tests
Posted by "marios@redhat.com" <ma...@redhat.com>.
On 02/08/12 01:23, Ronelle Landy wrote:
> Two comments (so far):
>
> 1. running >> rake test:deltacloud produces a bunch of warnings like:
> /home/dcloud/workspace/deltacloud/tests/deltacloud/instances_test.rb:28:
> warning: class variable access from toplevel
>
> 2: tests take a really long time to complete (tests are still running ...). Maybe there is just a lot of testing going on but it looks like some of the tests sit and query the provider over and over again? (open to more explanation here)
>
yes, the tests are obviously running against a 'real' provider... if
this is ec2 then the images tests are the likely culprit for the delay
you are seeing. Lets talk about this some more when you are online,
marios
>>
>> From: marios <ma...@redhat.com>
>>
>>
>> Signed-off-by: marios <ma...@redhat.com>
>> ---
>> tests/config.yaml | 19 ++-
>> tests/deltacloud/base_api_test.rb | 8 +-
>> tests/deltacloud/images_test.rb | 75 ++++++++
>> tests/deltacloud/instances_test.rb | 353
>> ++++++++++++++++++++++++++++++++++++
>> 4 files changed, 448 insertions(+), 7 deletions(-)
>>
>> diff --git a/tests/config.yaml b/tests/config.yaml
>> index 3070b56..5f905a6 100644
>> --- a/tests/config.yaml
>> +++ b/tests/config.yaml
>> @@ -4,15 +4,28 @@ api_url: "http://localhost:3001/api"
>> mock:
>> user: "mockuser"
>> password: "mockpassword"
>> +#OPENSTACK DRIVER CONFIG
>> +openstack:
>> + user:
>> + password:
>> + #used for instances tests:
>> + instances:
>> + preferred_image: "14075"
>> #EC2 DRIVER CONFIG:
>> ec2:
>> - user: #EC2 KEY
>> - password: #EC2 SECRET KEY
>> + user:
>> + password:
>> bucket_locations:
>> - #location constraint : provider
>> + #location constraint
>> - "EU"
>> - "sa-east-1"
>> - "us-west-1"
>> - "us-west-2"
>> - "ap-southeast-1"
>> - "ap-northeast-1"
>> + preferred_provider: "us-east-1"
>> + #used for instances tests:
>> + instances:
>> + preferred_image: "ami-2b5fba42"
>> + preferred_hwp: "m1.small"
>> + preferred_realm: "us-east-1b"
>> diff --git a/tests/deltacloud/base_api_test.rb
>> b/tests/deltacloud/base_api_test.rb
>> index bd37b46..12e1e4d 100644
>> --- a/tests/deltacloud/base_api_test.rb
>> +++ b/tests/deltacloud/base_api_test.rb
>> @@ -120,17 +120,17 @@ describe "Deltacloud API Entry Point" do
>> end
>>
>> it 'must change the API PROVIDER using the /api;provider matrix
>> parameter in URI' do
>> - res = get(';provider=test1', :public => true)
>> + res = get("\;provider=test1", {:accept=>:xml, :noauth=>true})
>> res.xml.root[:provider].wont_be_nil
>> res.xml.root[:provider].must_equal 'test1'
>> - res = get(';provider=test2', :public => true)
>> + res = get("\;provider=test2", {:accept=>:xml, :noauth=>true})
>> res.xml.root[:provider].must_equal 'test2'
>> end
>>
>> it 'must change the API DRIVER using the /api;driver matrix
>> parameter in URI' do
>> - res = get(';driver=ec2', :public => true)
>> + res = get("\;driver=ec2", {:accept=>:xml, :noauth=>true})
>> res.xml.root[:driver].must_equal 'ec2'
>> - res = get(';driver=mock', :public => true)
>> + res = get("\;driver=mock", {:accept=>:xml, :noauth=>true})
>> res.xml.root[:driver].must_equal 'mock'
>> end
>>
>> diff --git a/tests/deltacloud/images_test.rb
>> b/tests/deltacloud/images_test.rb
>> index e69de29..a6bd840 100644
>> --- a/tests/deltacloud/images_test.rb
>> +++ b/tests/deltacloud/images_test.rb
>> @@ -0,0 +1,75 @@
>> +#
>> +# Licensed to the Apache Software Foundation (ASF) under one or more
>> +# contributor license agreements. See the NOTICE file distributed
>> with
>> +# this work for additional information regarding copyright
>> ownership. The
>> +# ASF licenses this file to you under the Apache License, Version
>> 2.0 (the
>> +# "License"); you may not use this file except in compliance with
>> the
>> +# License. You may obtain a copy of the License at
>> +#
>> +# http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +# Unless required by applicable law or agreed to in writing,
>> software
>> +# distributed under the License is distributed on an "AS IS" BASIS,
>> WITHOUT
>> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> See the
>> +# License for the specific language governing permissions and
>> limitations
>> +# under the License.
>> +
>> +$:.unshift File.join(File.dirname(__FILE__), '..')
>> +require "deltacloud/test_setup.rb"
>> +
>> +IMAGES = "/images"
>> +
>> +describe 'Deltacloud API Images collection' do
>> + include Deltacloud::Test::Methods
>> +
>> + need_collection :images
>> +
>> + def each_image_xml(&block)
>> + res = get(IMAGES, :accept=> :xml)
>> + (res.xml/'images/image').each do |r|
>> + image_res = get(IMAGES + '/' + r[:id], :accept => :xml)
>> + yield image_res.xml
>> + end
>> + end
>> +
>> + #Run the 'common' tests for all collections defined in
>> common_tests_collections.rb
>> + test_collection = "images"
>> + $:.unshift File.join(File.dirname(__FILE__), '..')
>> + eval File.read('deltacloud/common_tests_collections.rb')
>> +
>> + #Now run the images-specific tests:
>> + it 'should have the "owner_id", "description", "architecure" and
>> "state" element for each image' do
>> + each_image_xml do |image_xml|
>> + (image_xml/'state').wont_be_empty
>> + (image_xml/'owner_id').wont_be_empty
>> + (image_xml/'architecture').wont_be_empty
>> + (image_xml/'description').wont_be_empty
>> + end
>> + end
>> +
>> + it 'should include the list of compatible hardware_profiles for
>> each image' do
>> + each_image_xml do |image_xml|
>> + (image_xml/'hardware_profiles/hardware_profile').wont_be_empty
>> + (image_xml/'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
>> + each_image_xml do |image_xml|
>> + (image_xml/'actions/link').wont_be_empty
>> + (image_xml/'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
>> +
>> +end
>> diff --git a/tests/deltacloud/instances_test.rb
>> b/tests/deltacloud/instances_test.rb
>> index e69de29..852b00b 100644
>> --- a/tests/deltacloud/instances_test.rb
>> +++ b/tests/deltacloud/instances_test.rb
>> @@ -0,0 +1,353 @@
>> +#
>> +# Licensed to the Apache Software Foundation (ASF) under one or more
>> +# contributor license agreements. See the NOTICE file distributed
>> with
>> +# this work for additional information regarding copyright
>> ownership. The
>> +# ASF licenses this file to you under the Apache License, Version
>> 2.0 (the
>> +# "License"); you may not use this file except in compliance with
>> the
>> +# License. You may obtain a copy of the License at
>> +#
>> +# http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +# Unless required by applicable law or agreed to in writing,
>> software
>> +# distributed under the License is distributed on an "AS IS" BASIS,
>> WITHOUT
>> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> See the
>> +# License for the specific language governing permissions and
>> limitations
>> +# under the License.
>> +
>> +$:.unshift File.join(File.dirname(__FILE__), '..')
>> +require "deltacloud/test_setup.rb"
>> +
>> +INSTANCES = "/instances"
>> +
>> +describe 'Deltacloud API instances collection' do
>> + include Deltacloud::Test::Methods
>> + need_collection :instances
>> + #make sure we have at least one instance to test
>> + begin
>> + #keep track of what we create for deletion after tests:
>> + @@created_resources = {:instances=>[], :keys=>[], :images=>[],
>> :firewalls=>[]}
>> + if api.instances_config["preferred_image"]
>> + image_id = api.instances_config["preferred_image"]
>> + else
>> + image_list = get("/images", {:accept => :xml})
>> + image_id = (image_list.xml/'images/image').to_a.choice[:id]
>> + end
>> + res = post(INSTANCES, :image_id=>image_id)
>> + unless res.code == 201
>> + raise Exception.new("Failed to create instance from image_id
>> #{image_id}")
>> + end
>> + @@my_instance_id = (res.xml/'instance')[0][:id]
>> + @@created_resources[:instances] << @@my_instance_id
>> + end
>> +
>> + #stop/destroy the resources we created for the tests
>> + MiniTest::Unit.after_tests {
>> +puts "CLEANING UP... resources for deletion:
>> #{@@created_resources.inspect}"
>> + #instances:
>> + @@created_resources[:instances].each_index do |i|
>> + attempts = 0
>> + begin
>> + stop_res =
>> post(INSTANCES+"/"+@@created_resources[:instances][i]+"/stop", "")
>> + @@created_resources[:instances][i] = nil if stop_res.code ==
>> 202
>> + rescue Exception => e
>> + sleep(10)
>> + attempts += 1
>> + retry if (attempts <= 5)
>> + end
>> + end
>> + @@created_resources[:instances].compact!
>> + @@created_resources.delete(:instances) if
>> @@created_resources[:instances].empty?
>> + #keys
>> + [:keys, :images, :firewalls].each do |col|
>> + @@created_resources[col].each do |k|
>> + res = delete("/#{col}/#{k}")
>> + @@created_resources[col].delete(k) if res.code == 204
>> + end
>> + @@created_resources.delete(col) if
>> @@created_resources[col].empty?
>> + end
>> +puts "CLEANUP attempt finished... resources looks like:
>> #{@@created_resources.inspect}"
>> + raise Exception.new("Unable to delete all created resources -
>> please check: #{@@created_resources.inspect}") unless
>> @@created_resources.empty?
>> + }
>> +
>> + def each_instance_xml(&block)
>> + res = get(INSTANCES, :accept=> :xml)
>> + (res.xml/'instances/instance').each do |r|
>> + instance_res = get(INSTANCES + '/' + r[:id], :accept => :xml)
>> + yield instance_res.xml
>> + end
>> + end
>> +
>> + def get_image
>> + if api.instances_config["preferred_image"]
>> + image_id = api.instances_config["preferred_image"]
>> + else
>> + image_list = get("/images", {:accept => :xml})
>> + image_id = (image_list.xml/'images/image').to_a.choice[:id]
>> + end
>> + end
>> +
>> + def get_realm
>> + if api.instances_config["preferred_realm"]
>> + realm_id = api.instances_config["preferred_realm"]
>> + else
>> + realms_list = get("/realms", {:accept => :xml})
>> + realm_id = (realms_list.xml/'realms/realm').to_a.choice[:id]
>> + end
>> + end
>> +
>> + def get_hwp
>> + if api.instances_config["preferred_hwp"]
>> + hwp_id = api.instances_config["preferred_hwp"]
>> + else
>> + hw_profile_list = get("/hardware_profiles", {:accept => :xml})
>> + hwp_id =
>> (hw_profile_list.xml/'hardware_profiles/hardware_profile').to_a.choice[:id]
>> + end
>> + end
>> +
>> + #Run the 'common' tests for all collections defined in
>> common_tests_collections.rb
>> + test_collection = "instances"
>> + $:.unshift File.join(File.dirname(__FILE__), '..')
>> + eval File.read('deltacloud/common_tests_collections.rb')
>> +
>> + #Now run the instances-specific tests:
>> +
>> + it 'must have the "state" element defined for each instance in
>> collection' do
>> + res = get(INSTANCES, :accept=> :xml)
>> + (res.xml/'instances/instance').each do |r|
>> + (r/'state').wont_be_empty
>> + (r/'state').first.must_match /(RUNNING|STOPPED|PENDING)/
>> + end
>> + end
>> +
>> + it 'must have the "owner_id" element for each instance and it
>> should match with the one in collection' do
>> + res = get(INSTANCES, :accept=> :xml)
>> + (res.xml/'instances/instance').each do |r|
>> + instance_res = get(INSTANCES + '/' + r[:id], :accept => :xml)
>> + (instance_res.xml/'owner_id').wont_be_empty
>> +
>> (instance_res.xml/'owner_id').first.text.must_equal((r/'owner_id').first.text)
>> + end
>> + end
>> +
>> + it 'each instance must link to the realm that was used during
>> instance creation' do
>> + each_instance_xml do |instance_xml|
>> + (instance_xml/'realm').wont_be_empty
>> + (instance_xml/'realm').size.must_equal 1
>> + (instance_xml/'realm').first[:id].wont_be_nil
>> + (instance_xml/'realm').first[:href].wont_be_nil
>> + (instance_xml/'realm').first[:href].must_match
>> /\/#{(instance_xml/'realm').first[:id]}$/
>> + end
>> + end
>> +
>> + it 'each instance must link to the image that was used to during
>> instance creation' do
>> + each_instance_xml do |instance_xml|
>> + (instance_xml/'image').wont_be_empty
>> + (instance_xml/'image').size.must_equal 1
>> + (instance_xml/'image').first[:id].wont_be_nil
>> + (instance_xml/'image').first[:href].wont_be_nil
>> + (instance_xml/'image').first[:href].must_match
>> /\/#{(instance_xml/'image').first[:id]}$/
>> + end
>> + end
>> +
>> + it 'each instance must link to the hardware_profile that was used
>> to during instance creation' do
>> + each_instance_xml do |instance_xml|
>> + (instance_xml/'hardware_profile').wont_be_empty
>> + (instance_xml/'hardware_profile').size.must_equal 1
>> + (instance_xml/'hardware_profile').first[:id].wont_be_nil
>> + (instance_xml/'hardware_profile').first[:href].wont_be_nil
>> + (instance_xml/'hardware_profile').first[:href].must_match
>> /\/#{(instance_xml/'hardware_profile').first[:id]}$/
>> + end
>> + end
>> +
>> + it 'each (NON-STOPPED) instance should advertise the public and
>> private addresses of the instance' do
>> + each_instance_xml do |instance_xml|
>> + #skip this instance if it is in STOPPED state
>> + next if (instance_xml/'instance/state').text == "STOPPED"
>> + (instance_xml/'public_addresses').wont_be_empty
>> + (instance_xml/'public_addresses').size.must_equal 1
>> + (instance_xml/'public_addresses/address').each do |a|
>> + a[:type].wont_be_nil
>> + a.text.strip.wont_be_empty
>> + end
>> + (instance_xml/'private_addresses').wont_be_empty
>> + (instance_xml/'private_addresses').size.must_equal 1
>> + (instance_xml/'private_addresses/address').each do |a|
>> + a[:type].wont_be_nil
>> + a.text.strip.wont_be_empty
>> + end
>> + end
>> + end
>> +
>> + it 'each instance should advertise the storage volumes used by the
>> instance' do
>> + each_instance_xml do |i|
>> + (i/'storage_volumes').wont_be_empty
>> + end
>> + end
>> +
>> + it 'each instance should advertise the list of actions that can be
>> executed for each instance' do
>> + each_instance_xml do |instance_xml|
>> + (instance_xml/'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 new instance using image without realm'
>> do
>> + #random image and create instance
>> + image_id = get_image
>> + image_id.wont_be_nil
>> + res = post(INSTANCES, :image_id=>image_id)
>> + res.code.must_equal 201
>> + res.headers[:location].wont_be_nil
>> + created_instance_id = (res.xml/'instance')[0][:id]
>> + #GET the instance
>> + res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
>> + res.code.must_equal 200
>> + (res.xml/'instance').first[:id].must_equal created_instance_id
>> + (res.xml/'instance/image').first[:id].must_equal image_id
>> + #mark it for stopping after tests run:
>> + @@created_resources[:instances] << created_instance_id
>> + end
>> +
>> + it 'should allow to create new instance using image and realm' do
>> + #random image, realm and create instance
>> + image_id = get_image
>> + image_id.wont_be_nil
>> + realm_id = get_realm
>> + realm_id.wont_be_nil
>> + res = post(INSTANCES, :image_id=>image_id, :realm_id=>realm_id)
>> + res.code.must_equal 201
>> + res.headers[:location].wont_be_nil
>> + created_instance_id = (res.xml/'instance')[0][:id]
>> + #GET the instance
>> + res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
>> + res.code.must_equal 200
>> + (res.xml/'instance').first[:id].must_equal created_instance_id
>> + (res.xml/'instance/image').first[:id].must_equal image_id
>> + (res.xml/'instance/realm').first[:id].must_equal realm_id
>> + #mark it for stopping after tests run:
>> + @@created_resources[:instances] << created_instance_id
>> + end
>> +
>> + it 'should allow to create new instance using image, realm and
>> hardware_profile' do
>> + #random image, realm, hardware_profile and create instance
>> + image_id = get_image
>> + image_id.wont_be_nil
>> + #check if this image defines compatible hw_profiles:
>> + res = get("/images/"+image_id, {:accept =>:xml})
>> + if (res.xml/'image/hardware_profiles').empty?
>> + hwp_id = get_hwp
>> + else
>> + hwp_id =
>> (res.xml/'image/hardware_profiles/hardware_profile').to_a.choice[:id]
>> + end
>> + hwp_id.wont_be_nil
>> + #random realm:
>> + realm_id = get_realm
>> + realm_id.wont_be_nil
>> + res = post(INSTANCES, :image_id=>image_id, :realm_id=>realm_id,
>> :hwp_id => hwp_id)
>> + res.code.must_equal 201
>> + res.headers[:location].wont_be_nil
>> + created_instance_id = (res.xml/'instance')[0][:id]
>> + #GET the instance
>> + res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
>> + res.code.must_equal 200
>> + (res.xml/'instance').first[:id].must_equal created_instance_id
>> + (res.xml/'instance/image').first[:id].must_equal image_id
>> + (res.xml/'instance/realm').first[:id].must_equal realm_id
>> + (res.xml/'instance/hardware_profile').first[:id].must_equal
>> hwp_id
>> + #mark it for stopping after tests run:
>> + @@created_resources[:instances] << created_instance_id
>> + end
>> +
>> +#snapshot (make image)
>> +
>> + it 'should allow to snapshot running instance if supported by
>> provider' do
>> + #check if created instance allows creating image
>> + res = get(INSTANCES+"/"+@@my_instance_id, {:accept=>:xml})
>> + instance_actions =
>> (res.xml/'actions/link').to_a.inject([]){|actions, current| actions
>> << current[:rel]; actions}
>> + skip "no create image support for instance #{@@my_instance_id}"
>> unless instance_actions.include?("create_image")
>> + #create image
>> + res = post("/images", :instance_id => @@my_instance_id,
>> :name=>random_name)
>> + res.code.must_equal 201
>> + my_image_id = (res.xml/'image')[0][:id]
>> + #mark for deletion later:
>> + @@created_resources[:images] << my_image_id
>> + end
>> +#
>> +#create with key
>> +
>> + describe "create instance with auth key" do
>> +
>> + need_collection :keys
>> + need_feature :instances, :authentication_key
>> +
>> + it 'should allow specification of auth key for created
>> instance when supported' do
>> + #create a key to use
>> + key_name = random_name
>> + key_res = post("/keys", :name=>key_name)
>> + key_res.code.must_equal 201
>> + key_id = (key_res.xml/'key')[0][:id]
>> + #create instance with this key:
>> + image_id = get_image
>> + res = post(INSTANCES, :image_id => image_id, :keyname =>
>> key_id)
>> + res.code.must_equal 201
>> + instance_id = (res.xml/'instance')[0][:id]
>> + #check the key:
>> + key_used =
>> (res.xml/'instance/authentication/login/keyname')[0].text
>> + key_used.must_equal key_id
>> + #mark them for deletion after tests run:
>> + @@created_resources[:instances] << instance_id
>> + @@created_resources[:keys] << key_id
>> + end
>> +
>> + end
>> +
>> +#specify user name (feature)
>> + describe "create instance with user defined name" do
>> +
>> + need_feature :instances, :user_name
>> +
>> + it 'should allow specification of name for created instance when
>> supported' do
>> + instance_name = random_name
>> + image_id = get_image
>> + res = post(INSTANCES, :image_id => image_id, :name =>
>> instance_name)
>> + res.code.must_equal 201
>> + instance_id = (res.xml/'instance')[0][:id]
>> + #check the name:
>> + created_name = (res.xml/'instance/name')[0].text
>> + created_name.must_equal instance_name
>> + #mark for deletion:
>> + @@created_resources[:instances] << instance_id
>> + end
>> + end
>> +
>> +#create with firewall (feature)
>> + describe "create instance with firewall" do
>> +
>> + need_collection :firewalls
>> + need_feature :instances, :firewalls
>> +
>> + it 'should be able to create instance using specified firewall'
>> do
>> + #create a firewall to use
>> + fw_name = random_name
>> + fw_res = post("/firewalls", :name=>fw_name,
>> :description=>"firewall created for instances API test on
>> #{Time.now}")
>> + fw_res.code.must_equal 201
>> + fw_id = (fw_res.xml/'firewall')[0][:id]
>> + ((fw_res.xml/'firewall/name')[0].text).must_equal fw_name
>> + #create instance with this firewall:
>> + image_id = get_image
>> + res = post(INSTANCES, :image_id => image_id, :firewalls1 =>
>> fw_id)
>> + res.code.must_equal 201
>> + instance_id = (res.xml/'instance')[0][:id]
>> + #check the firewall:
>> + fw_used = (res.xml/'instance/firewalls/firewall')[0][:id]
>> + fw_used.must_equal fw_id
>> + #mark for deletion:
>> + @@created_resources[:instances] << instance_id
>> + @@created_resources[:firewalls] << fw_id
>> + end
>> +
>> + end
>> +end
>> --
>> 1.7.6.5
>>
>>
Re: [PATCH 2/2] API TESTS: adds images and instances tests
Posted by Ronelle Landy <rl...@redhat.com>.
Two comments (so far):
1. running >> rake test:deltacloud produces a bunch of warnings like:
/home/dcloud/workspace/deltacloud/tests/deltacloud/instances_test.rb:28:
warning: class variable access from toplevel
2: tests take a really long time to complete (tests are still running ...). Maybe there is just a lot of testing going on but it looks like some of the tests sit and query the provider over and over again? (open to more explanation here)
>
> From: marios <ma...@redhat.com>
>
>
> Signed-off-by: marios <ma...@redhat.com>
> ---
> tests/config.yaml | 19 ++-
> tests/deltacloud/base_api_test.rb | 8 +-
> tests/deltacloud/images_test.rb | 75 ++++++++
> tests/deltacloud/instances_test.rb | 353
> ++++++++++++++++++++++++++++++++++++
> 4 files changed, 448 insertions(+), 7 deletions(-)
>
> diff --git a/tests/config.yaml b/tests/config.yaml
> index 3070b56..5f905a6 100644
> --- a/tests/config.yaml
> +++ b/tests/config.yaml
> @@ -4,15 +4,28 @@ api_url: "http://localhost:3001/api"
> mock:
> user: "mockuser"
> password: "mockpassword"
> +#OPENSTACK DRIVER CONFIG
> +openstack:
> + user:
> + password:
> + #used for instances tests:
> + instances:
> + preferred_image: "14075"
> #EC2 DRIVER CONFIG:
> ec2:
> - user: #EC2 KEY
> - password: #EC2 SECRET KEY
> + user:
> + password:
> bucket_locations:
> - #location constraint : provider
> + #location constraint
> - "EU"
> - "sa-east-1"
> - "us-west-1"
> - "us-west-2"
> - "ap-southeast-1"
> - "ap-northeast-1"
> + preferred_provider: "us-east-1"
> + #used for instances tests:
> + instances:
> + preferred_image: "ami-2b5fba42"
> + preferred_hwp: "m1.small"
> + preferred_realm: "us-east-1b"
> diff --git a/tests/deltacloud/base_api_test.rb
> b/tests/deltacloud/base_api_test.rb
> index bd37b46..12e1e4d 100644
> --- a/tests/deltacloud/base_api_test.rb
> +++ b/tests/deltacloud/base_api_test.rb
> @@ -120,17 +120,17 @@ describe "Deltacloud API Entry Point" do
> end
>
> it 'must change the API PROVIDER using the /api;provider matrix
> parameter in URI' do
> - res = get(';provider=test1', :public => true)
> + res = get("\;provider=test1", {:accept=>:xml, :noauth=>true})
> res.xml.root[:provider].wont_be_nil
> res.xml.root[:provider].must_equal 'test1'
> - res = get(';provider=test2', :public => true)
> + res = get("\;provider=test2", {:accept=>:xml, :noauth=>true})
> res.xml.root[:provider].must_equal 'test2'
> end
>
> it 'must change the API DRIVER using the /api;driver matrix
> parameter in URI' do
> - res = get(';driver=ec2', :public => true)
> + res = get("\;driver=ec2", {:accept=>:xml, :noauth=>true})
> res.xml.root[:driver].must_equal 'ec2'
> - res = get(';driver=mock', :public => true)
> + res = get("\;driver=mock", {:accept=>:xml, :noauth=>true})
> res.xml.root[:driver].must_equal 'mock'
> end
>
> diff --git a/tests/deltacloud/images_test.rb
> b/tests/deltacloud/images_test.rb
> index e69de29..a6bd840 100644
> --- a/tests/deltacloud/images_test.rb
> +++ b/tests/deltacloud/images_test.rb
> @@ -0,0 +1,75 @@
> +#
> +# Licensed to the Apache Software Foundation (ASF) under one or more
> +# contributor license agreements. See the NOTICE file distributed
> with
> +# this work for additional information regarding copyright
> ownership. The
> +# ASF licenses this file to you under the Apache License, Version
> 2.0 (the
> +# "License"); you may not use this file except in compliance with
> the
> +# License. You may obtain a copy of the License at
> +#
> +# http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing,
> software
> +# distributed under the License is distributed on an "AS IS" BASIS,
> WITHOUT
> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> See the
> +# License for the specific language governing permissions and
> limitations
> +# under the License.
> +
> +$:.unshift File.join(File.dirname(__FILE__), '..')
> +require "deltacloud/test_setup.rb"
> +
> +IMAGES = "/images"
> +
> +describe 'Deltacloud API Images collection' do
> + include Deltacloud::Test::Methods
> +
> + need_collection :images
> +
> + def each_image_xml(&block)
> + res = get(IMAGES, :accept=> :xml)
> + (res.xml/'images/image').each do |r|
> + image_res = get(IMAGES + '/' + r[:id], :accept => :xml)
> + yield image_res.xml
> + end
> + end
> +
> + #Run the 'common' tests for all collections defined in
> common_tests_collections.rb
> + test_collection = "images"
> + $:.unshift File.join(File.dirname(__FILE__), '..')
> + eval File.read('deltacloud/common_tests_collections.rb')
> +
> + #Now run the images-specific tests:
> + it 'should have the "owner_id", "description", "architecure" and
> "state" element for each image' do
> + each_image_xml do |image_xml|
> + (image_xml/'state').wont_be_empty
> + (image_xml/'owner_id').wont_be_empty
> + (image_xml/'architecture').wont_be_empty
> + (image_xml/'description').wont_be_empty
> + end
> + end
> +
> + it 'should include the list of compatible hardware_profiles for
> each image' do
> + each_image_xml do |image_xml|
> + (image_xml/'hardware_profiles/hardware_profile').wont_be_empty
> + (image_xml/'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
> + each_image_xml do |image_xml|
> + (image_xml/'actions/link').wont_be_empty
> + (image_xml/'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
> +
> +end
> diff --git a/tests/deltacloud/instances_test.rb
> b/tests/deltacloud/instances_test.rb
> index e69de29..852b00b 100644
> --- a/tests/deltacloud/instances_test.rb
> +++ b/tests/deltacloud/instances_test.rb
> @@ -0,0 +1,353 @@
> +#
> +# Licensed to the Apache Software Foundation (ASF) under one or more
> +# contributor license agreements. See the NOTICE file distributed
> with
> +# this work for additional information regarding copyright
> ownership. The
> +# ASF licenses this file to you under the Apache License, Version
> 2.0 (the
> +# "License"); you may not use this file except in compliance with
> the
> +# License. You may obtain a copy of the License at
> +#
> +# http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing,
> software
> +# distributed under the License is distributed on an "AS IS" BASIS,
> WITHOUT
> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> See the
> +# License for the specific language governing permissions and
> limitations
> +# under the License.
> +
> +$:.unshift File.join(File.dirname(__FILE__), '..')
> +require "deltacloud/test_setup.rb"
> +
> +INSTANCES = "/instances"
> +
> +describe 'Deltacloud API instances collection' do
> + include Deltacloud::Test::Methods
> + need_collection :instances
> + #make sure we have at least one instance to test
> + begin
> + #keep track of what we create for deletion after tests:
> + @@created_resources = {:instances=>[], :keys=>[], :images=>[],
> :firewalls=>[]}
> + if api.instances_config["preferred_image"]
> + image_id = api.instances_config["preferred_image"]
> + else
> + image_list = get("/images", {:accept => :xml})
> + image_id = (image_list.xml/'images/image').to_a.choice[:id]
> + end
> + res = post(INSTANCES, :image_id=>image_id)
> + unless res.code == 201
> + raise Exception.new("Failed to create instance from image_id
> #{image_id}")
> + end
> + @@my_instance_id = (res.xml/'instance')[0][:id]
> + @@created_resources[:instances] << @@my_instance_id
> + end
> +
> + #stop/destroy the resources we created for the tests
> + MiniTest::Unit.after_tests {
> +puts "CLEANING UP... resources for deletion:
> #{@@created_resources.inspect}"
> + #instances:
> + @@created_resources[:instances].each_index do |i|
> + attempts = 0
> + begin
> + stop_res =
> post(INSTANCES+"/"+@@created_resources[:instances][i]+"/stop", "")
> + @@created_resources[:instances][i] = nil if stop_res.code ==
> 202
> + rescue Exception => e
> + sleep(10)
> + attempts += 1
> + retry if (attempts <= 5)
> + end
> + end
> + @@created_resources[:instances].compact!
> + @@created_resources.delete(:instances) if
> @@created_resources[:instances].empty?
> + #keys
> + [:keys, :images, :firewalls].each do |col|
> + @@created_resources[col].each do |k|
> + res = delete("/#{col}/#{k}")
> + @@created_resources[col].delete(k) if res.code == 204
> + end
> + @@created_resources.delete(col) if
> @@created_resources[col].empty?
> + end
> +puts "CLEANUP attempt finished... resources looks like:
> #{@@created_resources.inspect}"
> + raise Exception.new("Unable to delete all created resources -
> please check: #{@@created_resources.inspect}") unless
> @@created_resources.empty?
> + }
> +
> + def each_instance_xml(&block)
> + res = get(INSTANCES, :accept=> :xml)
> + (res.xml/'instances/instance').each do |r|
> + instance_res = get(INSTANCES + '/' + r[:id], :accept => :xml)
> + yield instance_res.xml
> + end
> + end
> +
> + def get_image
> + if api.instances_config["preferred_image"]
> + image_id = api.instances_config["preferred_image"]
> + else
> + image_list = get("/images", {:accept => :xml})
> + image_id = (image_list.xml/'images/image').to_a.choice[:id]
> + end
> + end
> +
> + def get_realm
> + if api.instances_config["preferred_realm"]
> + realm_id = api.instances_config["preferred_realm"]
> + else
> + realms_list = get("/realms", {:accept => :xml})
> + realm_id = (realms_list.xml/'realms/realm').to_a.choice[:id]
> + end
> + end
> +
> + def get_hwp
> + if api.instances_config["preferred_hwp"]
> + hwp_id = api.instances_config["preferred_hwp"]
> + else
> + hw_profile_list = get("/hardware_profiles", {:accept => :xml})
> + hwp_id =
> (hw_profile_list.xml/'hardware_profiles/hardware_profile').to_a.choice[:id]
> + end
> + end
> +
> + #Run the 'common' tests for all collections defined in
> common_tests_collections.rb
> + test_collection = "instances"
> + $:.unshift File.join(File.dirname(__FILE__), '..')
> + eval File.read('deltacloud/common_tests_collections.rb')
> +
> + #Now run the instances-specific tests:
> +
> + it 'must have the "state" element defined for each instance in
> collection' do
> + res = get(INSTANCES, :accept=> :xml)
> + (res.xml/'instances/instance').each do |r|
> + (r/'state').wont_be_empty
> + (r/'state').first.must_match /(RUNNING|STOPPED|PENDING)/
> + end
> + end
> +
> + it 'must have the "owner_id" element for each instance and it
> should match with the one in collection' do
> + res = get(INSTANCES, :accept=> :xml)
> + (res.xml/'instances/instance').each do |r|
> + instance_res = get(INSTANCES + '/' + r[:id], :accept => :xml)
> + (instance_res.xml/'owner_id').wont_be_empty
> +
> (instance_res.xml/'owner_id').first.text.must_equal((r/'owner_id').first.text)
> + end
> + end
> +
> + it 'each instance must link to the realm that was used during
> instance creation' do
> + each_instance_xml do |instance_xml|
> + (instance_xml/'realm').wont_be_empty
> + (instance_xml/'realm').size.must_equal 1
> + (instance_xml/'realm').first[:id].wont_be_nil
> + (instance_xml/'realm').first[:href].wont_be_nil
> + (instance_xml/'realm').first[:href].must_match
> /\/#{(instance_xml/'realm').first[:id]}$/
> + end
> + end
> +
> + it 'each instance must link to the image that was used to during
> instance creation' do
> + each_instance_xml do |instance_xml|
> + (instance_xml/'image').wont_be_empty
> + (instance_xml/'image').size.must_equal 1
> + (instance_xml/'image').first[:id].wont_be_nil
> + (instance_xml/'image').first[:href].wont_be_nil
> + (instance_xml/'image').first[:href].must_match
> /\/#{(instance_xml/'image').first[:id]}$/
> + end
> + end
> +
> + it 'each instance must link to the hardware_profile that was used
> to during instance creation' do
> + each_instance_xml do |instance_xml|
> + (instance_xml/'hardware_profile').wont_be_empty
> + (instance_xml/'hardware_profile').size.must_equal 1
> + (instance_xml/'hardware_profile').first[:id].wont_be_nil
> + (instance_xml/'hardware_profile').first[:href].wont_be_nil
> + (instance_xml/'hardware_profile').first[:href].must_match
> /\/#{(instance_xml/'hardware_profile').first[:id]}$/
> + end
> + end
> +
> + it 'each (NON-STOPPED) instance should advertise the public and
> private addresses of the instance' do
> + each_instance_xml do |instance_xml|
> + #skip this instance if it is in STOPPED state
> + next if (instance_xml/'instance/state').text == "STOPPED"
> + (instance_xml/'public_addresses').wont_be_empty
> + (instance_xml/'public_addresses').size.must_equal 1
> + (instance_xml/'public_addresses/address').each do |a|
> + a[:type].wont_be_nil
> + a.text.strip.wont_be_empty
> + end
> + (instance_xml/'private_addresses').wont_be_empty
> + (instance_xml/'private_addresses').size.must_equal 1
> + (instance_xml/'private_addresses/address').each do |a|
> + a[:type].wont_be_nil
> + a.text.strip.wont_be_empty
> + end
> + end
> + end
> +
> + it 'each instance should advertise the storage volumes used by the
> instance' do
> + each_instance_xml do |i|
> + (i/'storage_volumes').wont_be_empty
> + end
> + end
> +
> + it 'each instance should advertise the list of actions that can be
> executed for each instance' do
> + each_instance_xml do |instance_xml|
> + (instance_xml/'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 new instance using image without realm'
> do
> + #random image and create instance
> + image_id = get_image
> + image_id.wont_be_nil
> + res = post(INSTANCES, :image_id=>image_id)
> + res.code.must_equal 201
> + res.headers[:location].wont_be_nil
> + created_instance_id = (res.xml/'instance')[0][:id]
> + #GET the instance
> + res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
> + res.code.must_equal 200
> + (res.xml/'instance').first[:id].must_equal created_instance_id
> + (res.xml/'instance/image').first[:id].must_equal image_id
> + #mark it for stopping after tests run:
> + @@created_resources[:instances] << created_instance_id
> + end
> +
> + it 'should allow to create new instance using image and realm' do
> + #random image, realm and create instance
> + image_id = get_image
> + image_id.wont_be_nil
> + realm_id = get_realm
> + realm_id.wont_be_nil
> + res = post(INSTANCES, :image_id=>image_id, :realm_id=>realm_id)
> + res.code.must_equal 201
> + res.headers[:location].wont_be_nil
> + created_instance_id = (res.xml/'instance')[0][:id]
> + #GET the instance
> + res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
> + res.code.must_equal 200
> + (res.xml/'instance').first[:id].must_equal created_instance_id
> + (res.xml/'instance/image').first[:id].must_equal image_id
> + (res.xml/'instance/realm').first[:id].must_equal realm_id
> + #mark it for stopping after tests run:
> + @@created_resources[:instances] << created_instance_id
> + end
> +
> + it 'should allow to create new instance using image, realm and
> hardware_profile' do
> + #random image, realm, hardware_profile and create instance
> + image_id = get_image
> + image_id.wont_be_nil
> + #check if this image defines compatible hw_profiles:
> + res = get("/images/"+image_id, {:accept =>:xml})
> + if (res.xml/'image/hardware_profiles').empty?
> + hwp_id = get_hwp
> + else
> + hwp_id =
> (res.xml/'image/hardware_profiles/hardware_profile').to_a.choice[:id]
> + end
> + hwp_id.wont_be_nil
> + #random realm:
> + realm_id = get_realm
> + realm_id.wont_be_nil
> + res = post(INSTANCES, :image_id=>image_id, :realm_id=>realm_id,
> :hwp_id => hwp_id)
> + res.code.must_equal 201
> + res.headers[:location].wont_be_nil
> + created_instance_id = (res.xml/'instance')[0][:id]
> + #GET the instance
> + res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
> + res.code.must_equal 200
> + (res.xml/'instance').first[:id].must_equal created_instance_id
> + (res.xml/'instance/image').first[:id].must_equal image_id
> + (res.xml/'instance/realm').first[:id].must_equal realm_id
> + (res.xml/'instance/hardware_profile').first[:id].must_equal
> hwp_id
> + #mark it for stopping after tests run:
> + @@created_resources[:instances] << created_instance_id
> + end
> +
> +#snapshot (make image)
> +
> + it 'should allow to snapshot running instance if supported by
> provider' do
> + #check if created instance allows creating image
> + res = get(INSTANCES+"/"+@@my_instance_id, {:accept=>:xml})
> + instance_actions =
> (res.xml/'actions/link').to_a.inject([]){|actions, current| actions
> << current[:rel]; actions}
> + skip "no create image support for instance #{@@my_instance_id}"
> unless instance_actions.include?("create_image")
> + #create image
> + res = post("/images", :instance_id => @@my_instance_id,
> :name=>random_name)
> + res.code.must_equal 201
> + my_image_id = (res.xml/'image')[0][:id]
> + #mark for deletion later:
> + @@created_resources[:images] << my_image_id
> + end
> +#
> +#create with key
> +
> + describe "create instance with auth key" do
> +
> + need_collection :keys
> + need_feature :instances, :authentication_key
> +
> + it 'should allow specification of auth key for created
> instance when supported' do
> + #create a key to use
> + key_name = random_name
> + key_res = post("/keys", :name=>key_name)
> + key_res.code.must_equal 201
> + key_id = (key_res.xml/'key')[0][:id]
> + #create instance with this key:
> + image_id = get_image
> + res = post(INSTANCES, :image_id => image_id, :keyname =>
> key_id)
> + res.code.must_equal 201
> + instance_id = (res.xml/'instance')[0][:id]
> + #check the key:
> + key_used =
> (res.xml/'instance/authentication/login/keyname')[0].text
> + key_used.must_equal key_id
> + #mark them for deletion after tests run:
> + @@created_resources[:instances] << instance_id
> + @@created_resources[:keys] << key_id
> + end
> +
> + end
> +
> +#specify user name (feature)
> + describe "create instance with user defined name" do
> +
> + need_feature :instances, :user_name
> +
> + it 'should allow specification of name for created instance when
> supported' do
> + instance_name = random_name
> + image_id = get_image
> + res = post(INSTANCES, :image_id => image_id, :name =>
> instance_name)
> + res.code.must_equal 201
> + instance_id = (res.xml/'instance')[0][:id]
> + #check the name:
> + created_name = (res.xml/'instance/name')[0].text
> + created_name.must_equal instance_name
> + #mark for deletion:
> + @@created_resources[:instances] << instance_id
> + end
> + end
> +
> +#create with firewall (feature)
> + describe "create instance with firewall" do
> +
> + need_collection :firewalls
> + need_feature :instances, :firewalls
> +
> + it 'should be able to create instance using specified firewall'
> do
> + #create a firewall to use
> + fw_name = random_name
> + fw_res = post("/firewalls", :name=>fw_name,
> :description=>"firewall created for instances API test on
> #{Time.now}")
> + fw_res.code.must_equal 201
> + fw_id = (fw_res.xml/'firewall')[0][:id]
> + ((fw_res.xml/'firewall/name')[0].text).must_equal fw_name
> + #create instance with this firewall:
> + image_id = get_image
> + res = post(INSTANCES, :image_id => image_id, :firewalls1 =>
> fw_id)
> + res.code.must_equal 201
> + instance_id = (res.xml/'instance')[0][:id]
> + #check the firewall:
> + fw_used = (res.xml/'instance/firewalls/firewall')[0][:id]
> + fw_used.must_equal fw_id
> + #mark for deletion:
> + @@created_resources[:instances] << instance_id
> + @@created_resources[:firewalls] << fw_id
> + end
> +
> + end
> +end
> --
> 1.7.6.5
>
>
[PATCH 2/2] API TESTS: adds images and instances tests
Posted by ma...@redhat.com.
From: marios <ma...@redhat.com>
Signed-off-by: marios <ma...@redhat.com>
---
tests/config.yaml | 19 ++-
tests/deltacloud/base_api_test.rb | 8 +-
tests/deltacloud/images_test.rb | 75 ++++++++
tests/deltacloud/instances_test.rb | 353 ++++++++++++++++++++++++++++++++++++
4 files changed, 448 insertions(+), 7 deletions(-)
diff --git a/tests/config.yaml b/tests/config.yaml
index 3070b56..5f905a6 100644
--- a/tests/config.yaml
+++ b/tests/config.yaml
@@ -4,15 +4,28 @@ api_url: "http://localhost:3001/api"
mock:
user: "mockuser"
password: "mockpassword"
+#OPENSTACK DRIVER CONFIG
+openstack:
+ user:
+ password:
+ #used for instances tests:
+ instances:
+ preferred_image: "14075"
#EC2 DRIVER CONFIG:
ec2:
- user: #EC2 KEY
- password: #EC2 SECRET KEY
+ user:
+ password:
bucket_locations:
- #location constraint : provider
+ #location constraint
- "EU"
- "sa-east-1"
- "us-west-1"
- "us-west-2"
- "ap-southeast-1"
- "ap-northeast-1"
+ preferred_provider: "us-east-1"
+ #used for instances tests:
+ instances:
+ preferred_image: "ami-2b5fba42"
+ preferred_hwp: "m1.small"
+ preferred_realm: "us-east-1b"
diff --git a/tests/deltacloud/base_api_test.rb b/tests/deltacloud/base_api_test.rb
index bd37b46..12e1e4d 100644
--- a/tests/deltacloud/base_api_test.rb
+++ b/tests/deltacloud/base_api_test.rb
@@ -120,17 +120,17 @@ describe "Deltacloud API Entry Point" do
end
it 'must change the API PROVIDER using the /api;provider matrix parameter in URI' do
- res = get(';provider=test1', :public => true)
+ res = get("\;provider=test1", {:accept=>:xml, :noauth=>true})
res.xml.root[:provider].wont_be_nil
res.xml.root[:provider].must_equal 'test1'
- res = get(';provider=test2', :public => true)
+ res = get("\;provider=test2", {:accept=>:xml, :noauth=>true})
res.xml.root[:provider].must_equal 'test2'
end
it 'must change the API DRIVER using the /api;driver matrix parameter in URI' do
- res = get(';driver=ec2', :public => true)
+ res = get("\;driver=ec2", {:accept=>:xml, :noauth=>true})
res.xml.root[:driver].must_equal 'ec2'
- res = get(';driver=mock', :public => true)
+ res = get("\;driver=mock", {:accept=>:xml, :noauth=>true})
res.xml.root[:driver].must_equal 'mock'
end
diff --git a/tests/deltacloud/images_test.rb b/tests/deltacloud/images_test.rb
index e69de29..a6bd840 100644
--- a/tests/deltacloud/images_test.rb
+++ b/tests/deltacloud/images_test.rb
@@ -0,0 +1,75 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+$:.unshift File.join(File.dirname(__FILE__), '..')
+require "deltacloud/test_setup.rb"
+
+IMAGES = "/images"
+
+describe 'Deltacloud API Images collection' do
+ include Deltacloud::Test::Methods
+
+ need_collection :images
+
+ def each_image_xml(&block)
+ res = get(IMAGES, :accept=> :xml)
+ (res.xml/'images/image').each do |r|
+ image_res = get(IMAGES + '/' + r[:id], :accept => :xml)
+ yield image_res.xml
+ end
+ end
+
+ #Run the 'common' tests for all collections defined in common_tests_collections.rb
+ test_collection = "images"
+ $:.unshift File.join(File.dirname(__FILE__), '..')
+ eval File.read('deltacloud/common_tests_collections.rb')
+
+ #Now run the images-specific tests:
+ it 'should have the "owner_id", "description", "architecure" and "state" element for each image' do
+ each_image_xml do |image_xml|
+ (image_xml/'state').wont_be_empty
+ (image_xml/'owner_id').wont_be_empty
+ (image_xml/'architecture').wont_be_empty
+ (image_xml/'description').wont_be_empty
+ end
+ end
+
+ it 'should include the list of compatible hardware_profiles for each image' do
+ each_image_xml do |image_xml|
+ (image_xml/'hardware_profiles/hardware_profile').wont_be_empty
+ (image_xml/'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
+ each_image_xml do |image_xml|
+ (image_xml/'actions/link').wont_be_empty
+ (image_xml/'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
+
+end
diff --git a/tests/deltacloud/instances_test.rb b/tests/deltacloud/instances_test.rb
index e69de29..852b00b 100644
--- a/tests/deltacloud/instances_test.rb
+++ b/tests/deltacloud/instances_test.rb
@@ -0,0 +1,353 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+$:.unshift File.join(File.dirname(__FILE__), '..')
+require "deltacloud/test_setup.rb"
+
+INSTANCES = "/instances"
+
+describe 'Deltacloud API instances collection' do
+ include Deltacloud::Test::Methods
+ need_collection :instances
+ #make sure we have at least one instance to test
+ begin
+ #keep track of what we create for deletion after tests:
+ @@created_resources = {:instances=>[], :keys=>[], :images=>[], :firewalls=>[]}
+ if api.instances_config["preferred_image"]
+ image_id = api.instances_config["preferred_image"]
+ else
+ image_list = get("/images", {:accept => :xml})
+ image_id = (image_list.xml/'images/image').to_a.choice[:id]
+ end
+ res = post(INSTANCES, :image_id=>image_id)
+ unless res.code == 201
+ raise Exception.new("Failed to create instance from image_id #{image_id}")
+ end
+ @@my_instance_id = (res.xml/'instance')[0][:id]
+ @@created_resources[:instances] << @@my_instance_id
+ end
+
+ #stop/destroy the resources we created for the tests
+ MiniTest::Unit.after_tests {
+puts "CLEANING UP... resources for deletion: #{@@created_resources.inspect}"
+ #instances:
+ @@created_resources[:instances].each_index do |i|
+ attempts = 0
+ begin
+ stop_res = post(INSTANCES+"/"+@@created_resources[:instances][i]+"/stop", "")
+ @@created_resources[:instances][i] = nil if stop_res.code == 202
+ rescue Exception => e
+ sleep(10)
+ attempts += 1
+ retry if (attempts <= 5)
+ end
+ end
+ @@created_resources[:instances].compact!
+ @@created_resources.delete(:instances) if @@created_resources[:instances].empty?
+ #keys
+ [:keys, :images, :firewalls].each do |col|
+ @@created_resources[col].each do |k|
+ res = delete("/#{col}/#{k}")
+ @@created_resources[col].delete(k) if res.code == 204
+ end
+ @@created_resources.delete(col) if @@created_resources[col].empty?
+ end
+puts "CLEANUP attempt finished... resources looks like: #{@@created_resources.inspect}"
+ raise Exception.new("Unable to delete all created resources - please check: #{@@created_resources.inspect}") unless @@created_resources.empty?
+ }
+
+ def each_instance_xml(&block)
+ res = get(INSTANCES, :accept=> :xml)
+ (res.xml/'instances/instance').each do |r|
+ instance_res = get(INSTANCES + '/' + r[:id], :accept => :xml)
+ yield instance_res.xml
+ end
+ end
+
+ def get_image
+ if api.instances_config["preferred_image"]
+ image_id = api.instances_config["preferred_image"]
+ else
+ image_list = get("/images", {:accept => :xml})
+ image_id = (image_list.xml/'images/image').to_a.choice[:id]
+ end
+ end
+
+ def get_realm
+ if api.instances_config["preferred_realm"]
+ realm_id = api.instances_config["preferred_realm"]
+ else
+ realms_list = get("/realms", {:accept => :xml})
+ realm_id = (realms_list.xml/'realms/realm').to_a.choice[:id]
+ end
+ end
+
+ def get_hwp
+ if api.instances_config["preferred_hwp"]
+ hwp_id = api.instances_config["preferred_hwp"]
+ else
+ hw_profile_list = get("/hardware_profiles", {:accept => :xml})
+ hwp_id = (hw_profile_list.xml/'hardware_profiles/hardware_profile').to_a.choice[:id]
+ end
+ end
+
+ #Run the 'common' tests for all collections defined in common_tests_collections.rb
+ test_collection = "instances"
+ $:.unshift File.join(File.dirname(__FILE__), '..')
+ eval File.read('deltacloud/common_tests_collections.rb')
+
+ #Now run the instances-specific tests:
+
+ it 'must have the "state" element defined for each instance in collection' do
+ res = get(INSTANCES, :accept=> :xml)
+ (res.xml/'instances/instance').each do |r|
+ (r/'state').wont_be_empty
+ (r/'state').first.must_match /(RUNNING|STOPPED|PENDING)/
+ end
+ end
+
+ it 'must have the "owner_id" element for each instance and it should match with the one in collection' do
+ res = get(INSTANCES, :accept=> :xml)
+ (res.xml/'instances/instance').each do |r|
+ instance_res = get(INSTANCES + '/' + r[:id], :accept => :xml)
+ (instance_res.xml/'owner_id').wont_be_empty
+ (instance_res.xml/'owner_id').first.text.must_equal((r/'owner_id').first.text)
+ end
+ end
+
+ it 'each instance must link to the realm that was used during instance creation' do
+ each_instance_xml do |instance_xml|
+ (instance_xml/'realm').wont_be_empty
+ (instance_xml/'realm').size.must_equal 1
+ (instance_xml/'realm').first[:id].wont_be_nil
+ (instance_xml/'realm').first[:href].wont_be_nil
+ (instance_xml/'realm').first[:href].must_match /\/#{(instance_xml/'realm').first[:id]}$/
+ end
+ end
+
+ it 'each instance must link to the image that was used to during instance creation' do
+ each_instance_xml do |instance_xml|
+ (instance_xml/'image').wont_be_empty
+ (instance_xml/'image').size.must_equal 1
+ (instance_xml/'image').first[:id].wont_be_nil
+ (instance_xml/'image').first[:href].wont_be_nil
+ (instance_xml/'image').first[:href].must_match /\/#{(instance_xml/'image').first[:id]}$/
+ end
+ end
+
+ it 'each instance must link to the hardware_profile that was used to during instance creation' do
+ each_instance_xml do |instance_xml|
+ (instance_xml/'hardware_profile').wont_be_empty
+ (instance_xml/'hardware_profile').size.must_equal 1
+ (instance_xml/'hardware_profile').first[:id].wont_be_nil
+ (instance_xml/'hardware_profile').first[:href].wont_be_nil
+ (instance_xml/'hardware_profile').first[:href].must_match /\/#{(instance_xml/'hardware_profile').first[:id]}$/
+ end
+ end
+
+ it 'each (NON-STOPPED) instance should advertise the public and private addresses of the instance' do
+ each_instance_xml do |instance_xml|
+ #skip this instance if it is in STOPPED state
+ next if (instance_xml/'instance/state').text == "STOPPED"
+ (instance_xml/'public_addresses').wont_be_empty
+ (instance_xml/'public_addresses').size.must_equal 1
+ (instance_xml/'public_addresses/address').each do |a|
+ a[:type].wont_be_nil
+ a.text.strip.wont_be_empty
+ end
+ (instance_xml/'private_addresses').wont_be_empty
+ (instance_xml/'private_addresses').size.must_equal 1
+ (instance_xml/'private_addresses/address').each do |a|
+ a[:type].wont_be_nil
+ a.text.strip.wont_be_empty
+ end
+ end
+ end
+
+ it 'each instance should advertise the storage volumes used by the instance' do
+ each_instance_xml do |i|
+ (i/'storage_volumes').wont_be_empty
+ end
+ end
+
+ it 'each instance should advertise the list of actions that can be executed for each instance' do
+ each_instance_xml do |instance_xml|
+ (instance_xml/'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 new instance using image without realm' do
+ #random image and create instance
+ image_id = get_image
+ image_id.wont_be_nil
+ res = post(INSTANCES, :image_id=>image_id)
+ res.code.must_equal 201
+ res.headers[:location].wont_be_nil
+ created_instance_id = (res.xml/'instance')[0][:id]
+ #GET the instance
+ res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
+ res.code.must_equal 200
+ (res.xml/'instance').first[:id].must_equal created_instance_id
+ (res.xml/'instance/image').first[:id].must_equal image_id
+ #mark it for stopping after tests run:
+ @@created_resources[:instances] << created_instance_id
+ end
+
+ it 'should allow to create new instance using image and realm' do
+ #random image, realm and create instance
+ image_id = get_image
+ image_id.wont_be_nil
+ realm_id = get_realm
+ realm_id.wont_be_nil
+ res = post(INSTANCES, :image_id=>image_id, :realm_id=>realm_id)
+ res.code.must_equal 201
+ res.headers[:location].wont_be_nil
+ created_instance_id = (res.xml/'instance')[0][:id]
+ #GET the instance
+ res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
+ res.code.must_equal 200
+ (res.xml/'instance').first[:id].must_equal created_instance_id
+ (res.xml/'instance/image').first[:id].must_equal image_id
+ (res.xml/'instance/realm').first[:id].must_equal realm_id
+ #mark it for stopping after tests run:
+ @@created_resources[:instances] << created_instance_id
+ end
+
+ it 'should allow to create new instance using image, realm and hardware_profile' do
+ #random image, realm, hardware_profile and create instance
+ image_id = get_image
+ image_id.wont_be_nil
+ #check if this image defines compatible hw_profiles:
+ res = get("/images/"+image_id, {:accept =>:xml})
+ if (res.xml/'image/hardware_profiles').empty?
+ hwp_id = get_hwp
+ else
+ hwp_id = (res.xml/'image/hardware_profiles/hardware_profile').to_a.choice[:id]
+ end
+ hwp_id.wont_be_nil
+ #random realm:
+ realm_id = get_realm
+ realm_id.wont_be_nil
+ res = post(INSTANCES, :image_id=>image_id, :realm_id=>realm_id, :hwp_id => hwp_id)
+ res.code.must_equal 201
+ res.headers[:location].wont_be_nil
+ created_instance_id = (res.xml/'instance')[0][:id]
+ #GET the instance
+ res = get(INSTANCES+"/"+created_instance_id, {:accept=>:xml})
+ res.code.must_equal 200
+ (res.xml/'instance').first[:id].must_equal created_instance_id
+ (res.xml/'instance/image').first[:id].must_equal image_id
+ (res.xml/'instance/realm').first[:id].must_equal realm_id
+ (res.xml/'instance/hardware_profile').first[:id].must_equal hwp_id
+ #mark it for stopping after tests run:
+ @@created_resources[:instances] << created_instance_id
+ end
+
+#snapshot (make image)
+
+ it 'should allow to snapshot running instance if supported by provider' do
+ #check if created instance allows creating image
+ res = get(INSTANCES+"/"+@@my_instance_id, {:accept=>:xml})
+ instance_actions = (res.xml/'actions/link').to_a.inject([]){|actions, current| actions << current[:rel]; actions}
+ skip "no create image support for instance #{@@my_instance_id}" unless instance_actions.include?("create_image")
+ #create image
+ res = post("/images", :instance_id => @@my_instance_id, :name=>random_name)
+ res.code.must_equal 201
+ my_image_id = (res.xml/'image')[0][:id]
+ #mark for deletion later:
+ @@created_resources[:images] << my_image_id
+ end
+#
+#create with key
+
+ describe "create instance with auth key" do
+
+ need_collection :keys
+ need_feature :instances, :authentication_key
+
+ it 'should allow specification of auth key for created instance when supported' do
+ #create a key to use
+ key_name = random_name
+ key_res = post("/keys", :name=>key_name)
+ key_res.code.must_equal 201
+ key_id = (key_res.xml/'key')[0][:id]
+ #create instance with this key:
+ image_id = get_image
+ res = post(INSTANCES, :image_id => image_id, :keyname => key_id)
+ res.code.must_equal 201
+ instance_id = (res.xml/'instance')[0][:id]
+ #check the key:
+ key_used = (res.xml/'instance/authentication/login/keyname')[0].text
+ key_used.must_equal key_id
+ #mark them for deletion after tests run:
+ @@created_resources[:instances] << instance_id
+ @@created_resources[:keys] << key_id
+ end
+
+ end
+
+#specify user name (feature)
+ describe "create instance with user defined name" do
+
+ need_feature :instances, :user_name
+
+ it 'should allow specification of name for created instance when supported' do
+ instance_name = random_name
+ image_id = get_image
+ res = post(INSTANCES, :image_id => image_id, :name => instance_name)
+ res.code.must_equal 201
+ instance_id = (res.xml/'instance')[0][:id]
+ #check the name:
+ created_name = (res.xml/'instance/name')[0].text
+ created_name.must_equal instance_name
+ #mark for deletion:
+ @@created_resources[:instances] << instance_id
+ end
+ end
+
+#create with firewall (feature)
+ describe "create instance with firewall" do
+
+ need_collection :firewalls
+ need_feature :instances, :firewalls
+
+ it 'should be able to create instance using specified firewall' do
+ #create a firewall to use
+ fw_name = random_name
+ fw_res = post("/firewalls", :name=>fw_name, :description=>"firewall created for instances API test on #{Time.now}")
+ fw_res.code.must_equal 201
+ fw_id = (fw_res.xml/'firewall')[0][:id]
+ ((fw_res.xml/'firewall/name')[0].text).must_equal fw_name
+ #create instance with this firewall:
+ image_id = get_image
+ res = post(INSTANCES, :image_id => image_id, :firewalls1 => fw_id)
+ res.code.must_equal 201
+ instance_id = (res.xml/'instance')[0][:id]
+ #check the firewall:
+ fw_used = (res.xml/'instance/firewalls/firewall')[0][:id]
+ fw_used.must_equal fw_id
+ #mark for deletion:
+ @@created_resources[:instances] << instance_id
+ @@created_resources[:firewalls] << fw_id
+ end
+
+ end
+end
--
1.7.6.5
Re: [PATCH 1/2] API TESTS - moves common collections tests to
separate file
Posted by David Lutterkort <lu...@redhat.com>.
On Wed, 2012-08-01 at 14:38 +0300, marios@redhat.com wrote:
> From: marios <ma...@redhat.com>
>
>
> Signed-off-by: marios <ma...@redhat.com>
> ---
> tests/deltacloud/buckets_test.rb | 135 ++++++++++----------------
> tests/deltacloud/common_tests_collections.rb | 105 ++++++++++++++++++++
> tests/deltacloud/test_setup.rb | 23 ++++-
> 3 files changed, 178 insertions(+), 85 deletions(-)
> create mode 100644 tests/deltacloud/common_tests_collections.rb
>
> diff --git a/tests/deltacloud/buckets_test.rb b/tests/deltacloud/buckets_test.rb
> index e8732b1..e16e743 100644
> --- a/tests/deltacloud/buckets_test.rb
> +++ b/tests/deltacloud/buckets_test.rb
> @@ -61,19 +61,63 @@ describe 'Deltacloud API buckets collection' do
> end
> }
>
> - it 'must advertise the buckets collection in API entrypoint' do
> + #Run the 'common' tests for all collections defined in common_tests_collections.rb
> + test_collection = "buckets"
> + $:.unshift File.join(File.dirname(__FILE__), '..')
> + eval File.read('deltacloud/common_tests_collections.rb')
NAK; can we define these common tests in a module and include that ?
David