Skip to content
This repository has been archived by the owner on Nov 23, 2020. It is now read-only.

Commit

Permalink
Fix test time sensitivity when checking tasks
Browse files Browse the repository at this point in the history
Integration tests which confirm atomicity and idempotency of updates by
checking the number of tasks generated during an operation were sensitive to
time differences between the clocks on the local machine and vCloud
Director.

This could be reproduced by putting your local clock forward one hour. You'd
get a test failure like the following:

    1) Vcloud::EdgeGatewayServices Test EdgeGatewayServices with multiple services Check update is functional should only create one edgeGateway update task when updating the configuration
       Failure/Error: expect(task_list_after_update.size - task_list_before_update.size).to be(1)

         expected #<Fixnum:3> => 1
              got #<Fixnum:1> => 0

         Compared using equal?, which compares object identity,
         but expected and actual are not the same object. Use
         `expect(actual).to eq(expected)` if you don't care about
         object identity in this example.
       # ./spec/integration/edge_gateway/edge_gateway_services_spec.rb:44:in `block (4 levels) in <module:Vcloud>'

This is because it was using the local time to find all tasks that had
occurred since the beginning of that test and vCloud Director didn't know of
any tasks that had occurred in (what it considers to be) the future.

Fix this by using a previous Edge Gateway task as a marker and find all
tasks that have occurred since that. The timestamp of that last task is
generated by the clock available to vCloud Director, so any difference
between local and remote time is no longer an issue.

In most cases the previous task will be another one of our tests or the
`reset_edge_gateway` before block. The helper will raise an exception if
it's unable to find anything at all. We make sure *that* task is removed
from the elapsed results by matching it's unique `href` field.

The option `pageSize 1` is used in the initial query to optimise the amount
of data we get from vCloud, because we only care about the single most
recent. This depends on a new release of vcloud-core for
gds-operations/vcloud-core#140 - without which it will fetch all results
one-by-one, very slowly.
  • Loading branch information
dcarley committed Nov 10, 2014
1 parent 25a47ea commit ffb54d3
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 58 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,7 @@
## UNRELEASED

Update vCloud Core to 0.14.0 to improve speed of integration tests.

## 1.3.0 (2014-10-14)

Features:
Expand Down
18 changes: 3 additions & 15 deletions spec/integration/edge_gateway/configure_load_balancer_spec.rb
Expand Up @@ -46,14 +46,13 @@ module Vcloud
end

it "should only make one EdgeGateway update task, to minimise EdgeGateway reload events" do
start_time = Time.now.getutc
task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
task_last = IntegrationHelper.get_last_task(@test_params.edge_gateway)
diff = EdgeGateway::Configure.new(@initial_load_balancer_config_file, @vars_config_file).update
task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
tasks_elapsed = IntegrationHelper.get_tasks_since(@test_params.edge_gateway, task_last)

expect(diff.keys).to eq([:LoadBalancerService])
expect(diff[:LoadBalancerService]).to have_at_least(1).items
expect(task_list_after_update.size - task_list_before_update.size).to be(1)
expect(tasks_elapsed).to have(1).items
end

it "should have configured at least one LoadBancer Pool entry" do
Expand Down Expand Up @@ -164,17 +163,6 @@ def edge_gateway_vars_hash
:edge_gateway_ext_network_ip => @test_params.provider_network_ip,
}
end

def get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(timestamp)
vcloud_time = timestamp.strftime('%FT%T.000Z')
q = Vcloud::Core::QueryRunner.new
q.run('task',
:filter =>
"name==networkConfigureEdgeGatewayServices;objectName==#{@test_params.edge_gateway};startDate=ge=#{vcloud_time}",
:sortDesc => 'startDate',
)
end

end

end
Expand Down
40 changes: 12 additions & 28 deletions spec/integration/edge_gateway/configure_multiple_services_spec.rb
Expand Up @@ -37,15 +37,14 @@ module Vcloud
end

it "should only create one edgeGateway update task when updating the configuration" do
start_time = Time.now.getutc
task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
task_last = IntegrationHelper.get_last_task(@test_params.edge_gateway)
diff = EdgeGateway::Configure.new(@initial_config_file, @vars_config_file).update
task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
tasks_elapsed = IntegrationHelper.get_tasks_since(@test_params.edge_gateway, task_last)

expect(diff.keys).to eq([:FirewallService, :NatService])
expect(diff[:FirewallService]).to have_at_least(1).items
expect(diff[:NatService]).to have_at_least(1).items
expect(task_list_after_update.size - task_list_before_update.size).to be(1)
expect(tasks_elapsed).to have(1).items
end

it "should now have nat and firewall rules configured, no load balancer yet" do
Expand All @@ -57,34 +56,31 @@ module Vcloud
end

it "should not update the EdgeGateway again if the config hasn't changed" do
start_time = Time.now.getutc
task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
task_last = IntegrationHelper.get_last_task(@test_params.edge_gateway)
diff = EdgeGateway::Configure.new(@initial_config_file, @vars_config_file).update
task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
tasks_elapsed = IntegrationHelper.get_tasks_since(@test_params.edge_gateway, task_last)

expect(diff).to eq({})
expect(task_list_after_update.size - task_list_before_update.size).to be(0)
expect(tasks_elapsed).to have(0).items
end

it "should only create one additional edgeGateway update task when adding the LoadBalancer config" do
start_time = Time.now.getutc
task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
task_last = IntegrationHelper.get_last_task(@test_params.edge_gateway)
diff = EdgeGateway::Configure.new(@adding_load_balancer_config_file, @vars_config_file).update
task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
tasks_elapsed = IntegrationHelper.get_tasks_since(@test_params.edge_gateway, task_last)

expect(diff.keys).to eq([:LoadBalancerService])
expect(diff[:LoadBalancerService]).to have_at_least(1).items
expect(task_list_after_update.size - task_list_before_update.size).to be(1)
expect(tasks_elapsed).to have(1).items
end

it "should not update the EdgeGateway again if we reapply the 'adding load balancer' config" do
start_time = Time.now.getutc
task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
task_last = IntegrationHelper.get_last_task(@test_params.edge_gateway)
diff = EdgeGateway::Configure.new(@adding_load_balancer_config_file, @vars_config_file).update
task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
tasks_elapsed = IntegrationHelper.get_tasks_since(@test_params.edge_gateway, task_last)

expect(diff).to eq({})
expect(task_list_after_update.size - task_list_before_update.size).to be(0)
expect(tasks_elapsed).to have(0).items
end

end
Expand Down Expand Up @@ -124,18 +120,6 @@ def edge_gateway_vars_hash
edge_gateway_ext_network_ip: @test_params.provider_network_ip,
}
end

def get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(timestamp)
vcloud_time = timestamp.strftime('%FT%T.000Z')
q = Vcloud::Core::QueryRunner.new

q.run('task',
:filter =>
"name==networkConfigureEdgeGatewayServices;objectName==#{@test_params.edge_gateway};startDate=ge=#{vcloud_time}",
:sortDesc => 'startDate',
)
end

end

end
Expand Down
17 changes: 3 additions & 14 deletions spec/integration/edge_gateway/configure_nat_spec.rb
Expand Up @@ -48,14 +48,13 @@ module Vcloud
end

it "should only make one EdgeGateway update task, to minimise EdgeGateway reload events" do
start_time = Time.now.getutc
task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
task_last = IntegrationHelper.get_last_task(@test_params.edge_gateway)
diff = EdgeGateway::Configure.new(@initial_nat_config_file, @vars_config_file).update
task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
tasks_elapsed = IntegrationHelper.get_tasks_since(@test_params.edge_gateway, task_last)

expect(diff.keys).to eq([:NatService])
expect(diff[:NatService]).to have_at_least(1).items
expect(task_list_after_update.size - task_list_before_update.size).to be(1)
expect(tasks_elapsed).to have(1).items
end

it "should have configured at least one NAT rule" do
Expand Down Expand Up @@ -187,16 +186,6 @@ def edge_gateway_vars_hash
:original_ip => @test_params.provider_network_ip,
}
end

def get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(timestamp)
vcloud_time = timestamp.strftime('%FT%T.000Z')
q = Vcloud::Core::QueryRunner.new
q.run('task',
:filter => "name==networkConfigureEdgeGatewayServices;objectName==#{@test_params.edge_gateway};startDate=ge=#{vcloud_time}",
:sortDesc => 'startDate',
)
end

end

end
Expand Down
22 changes: 22 additions & 0 deletions spec/support/integration_helper.rb
Expand Up @@ -13,5 +13,27 @@ def self.remove_temp_config_files(files_to_delete)
}
end

def self.get_last_task(gateway_name)
tasks = Vcloud::Core::QueryRunner.new.run('task',
:filter => "name==networkConfigureEdgeGatewayServices;" + \
"objectName==#{gateway_name}",
:sortDesc => 'startDate',
:pageSize => 1,
)

raise "Unable to find last vCloud task" if tasks.empty?
tasks.first
end

def self.get_tasks_since(gateway_name, task)
tasks = Vcloud::Core::QueryRunner.new.run('task',
:filter => "name==networkConfigureEdgeGatewayServices;" + \
"objectName==#{gateway_name};" + \
"startDate=ge=#{task.fetch(:startDate)}",
:sortDesc => 'startDate',
)

tasks.reject! { |t| t.fetch(:href) == task.fetch(:href) }
tasks
end
end
2 changes: 1 addition & 1 deletion vcloud-edge_gateway.gemspec
Expand Up @@ -21,7 +21,7 @@ Gem::Specification.new do |s|

s.required_ruby_version = '>= 1.9.3'

s.add_runtime_dependency 'vcloud-core', '~> 0.13.0'
s.add_runtime_dependency 'vcloud-core', '~> 0.14.0'
s.add_runtime_dependency 'hashdiff'
s.add_development_dependency 'pry'
s.add_development_dependency 'rake'
Expand Down

0 comments on commit ffb54d3

Please sign in to comment.