diff --git a/lib/fog/aws.rb b/lib/fog/aws.rb index 9322c525c..dd2c8f8eb 100644 --- a/lib/fog/aws.rb +++ b/lib/fog/aws.rb @@ -177,6 +177,8 @@ module Fog class << self alias :reserved_instances_id :request_id alias :reserved_instances_offering_id :request_id + alias :sqs_message_id :request_id + alias :sqs_sender_id :request_id end def self.reservation_id diff --git a/lib/fog/aws/requests/sqs/change_message_visibility.rb b/lib/fog/aws/requests/sqs/change_message_visibility.rb index 2902f7404..7f34281bb 100644 --- a/lib/fog/aws/requests/sqs/change_message_visibility.rb +++ b/lib/fog/aws/requests/sqs/change_message_visibility.rb @@ -27,6 +27,36 @@ module Fog end end + + class Mock + + def change_message_visibility(queue_url, receipt_handle, visibility_timeout) + Excon::Response.new.tap do |response| + if (queue = data[:queues][queue_url]) + message_id, _ = queue[:receipt_handles].find { |message_id, receipts| + receipts.keys.include?(receipt_handle) + } + + if message_id + queue[:messages][message_id]['Attributes']['VisibilityTimeout'] = visibility_timeout + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + } + } + response.status = 200 + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + end + end + + end end end diff --git a/lib/fog/aws/requests/sqs/create_queue.rb b/lib/fog/aws/requests/sqs/create_queue.rb index 610dd7946..4cdccaec9 100644 --- a/lib/fog/aws/requests/sqs/create_queue.rb +++ b/lib/fog/aws/requests/sqs/create_queue.rb @@ -25,7 +25,41 @@ module Fog end end - + + class Mock + def create_queue(name, options = {}) + Excon::Response.new.tap do |response| + response.status = 200 + + now = Time.now + queue_url = "https://queue.amazonaws.com/#{data[:owner_id]}/#{name}" + queue = { + 'QueueName' => name, + 'Attributes' => { + 'VisibilityTimeout' => 30, + 'ApproximateNumberOfMessages' => 0, + 'ApproximateNumberOfMessagesNotVisible' => 0, + 'CreatedTimestamp' => now, + 'LastModifiedTimestamp' => now, + 'QueueArn' => Fog::AWS::Mock.arn('sqs', 'us-east-1', data[:owner_id], name), + 'MaximumMessageSize' => 8192, + 'MessageRetentionPeriod' => 345600 + }, + :messages => {}, + :receipt_handles => {} + } + data[:queues][queue_url] = queue unless data[:queues][queue_url] + + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + }, + 'QueueUrl' => queue_url + } + end + + end + end end end end diff --git a/lib/fog/aws/requests/sqs/delete_message.rb b/lib/fog/aws/requests/sqs/delete_message.rb index c17e65dfe..a69b1c29f 100644 --- a/lib/fog/aws/requests/sqs/delete_message.rb +++ b/lib/fog/aws/requests/sqs/delete_message.rb @@ -25,7 +25,36 @@ module Fog end end + + class Mock + def delete_message(queue_url, receipt_handle) + Excon::Response.new.tap do |response| + if (queue = data[:queues][queue_url]) + message_id, _ = queue[:receipt_handles].find { |msg_id, receipts| + receipts.keys.include?(receipt_handle) + } + + if message_id + queue[:receipt_handles].delete(message_id) + queue[:messages].delete(message_id) + queue['Attributes']['LastModifiedTimestamp'] = Time.now + end + + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + } + } + response.status = 200 + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + end + end + + end end end end diff --git a/lib/fog/aws/requests/sqs/delete_queue.rb b/lib/fog/aws/requests/sqs/delete_queue.rb index 2b5d93a27..8d122f0f0 100644 --- a/lib/fog/aws/requests/sqs/delete_queue.rb +++ b/lib/fog/aws/requests/sqs/delete_queue.rb @@ -23,7 +23,30 @@ module Fog end end - + + class Mock + + def delete_queue(queue_url) + Excon::Response.new.tap do |response| + if (queue = data[:queues][queue_url]) + response.status = 200 + + data[:queues].delete(queue_url) + + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + } + } + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + end + end + + end + end end end diff --git a/lib/fog/aws/requests/sqs/get_queue_attributes.rb b/lib/fog/aws/requests/sqs/get_queue_attributes.rb index ff88b57eb..75e852852 100644 --- a/lib/fog/aws/requests/sqs/get_queue_attributes.rb +++ b/lib/fog/aws/requests/sqs/get_queue_attributes.rb @@ -25,7 +25,28 @@ module Fog end end - + + class Mock + + def get_queue_attributes(queue_url, attribute_name) + Excon::Response.new.tap do |response| + if (queue = data[:queues][queue_url]) + response.status = 200 + + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + }, + 'Attributes' => queue['Attributes'] + } + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + end + end + + end end end end diff --git a/lib/fog/aws/requests/sqs/list_queues.rb b/lib/fog/aws/requests/sqs/list_queues.rb index 05364cc67..9059e6f5c 100644 --- a/lib/fog/aws/requests/sqs/list_queues.rb +++ b/lib/fog/aws/requests/sqs/list_queues.rb @@ -22,7 +22,21 @@ module Fog }.merge!(options)) end end - + + class Mock + def list_queues(options = {}) + Excon::Response.new.tap do |response| + response.status = 200 + + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + }, + 'QueueUrls' => data[:queues].keys + } + end + end + end end end end diff --git a/lib/fog/aws/requests/sqs/receive_message.rb b/lib/fog/aws/requests/sqs/receive_message.rb index b01c42a59..fa4c90366 100644 --- a/lib/fog/aws/requests/sqs/receive_message.rb +++ b/lib/fog/aws/requests/sqs/receive_message.rb @@ -28,7 +28,61 @@ module Fog end end - + + class Mock + + def receive_message(queue_url, options = {}) + Excon::Response.new.tap do |response| + if (queue = data[:queues][queue_url]) + max_number_of_messages = options['MaxNumberOfMessages'] || 1 + now = Time.now + + keys = queue[:messages].keys[0, max_number_of_messages] + + messages = queue[:messages].values_at(*keys).map do |m| + message_id = m['MessageId'] + + invisible = if (received_handles = queue[:receipt_handles][message_id]) + visibility_timeout = m['Attributes']['VisibilityTimeout'] || queue['Attributes']['VisibilityTimeout'] + received_handles.any? { |handle, time| now < time + visibility_timeout } + else + false + end + + if invisible + nil + else + receipt_handle = Fog::Mock.random_base64(300) + + queue[:receipt_handles][message_id] ||= {} + queue[:receipt_handles][message_id][receipt_handle] = now + + m['Attributes'].tap do |attrs| + attrs['ApproximateFirstReceiveTimestamp'] ||= now + attrs['ApproximateReceiveCount'] = (attrs['ApproximateReceiveCount'] || 0) + 1 + end + + m.merge({ + 'ReceiptHandle' => receipt_handle + }) + end + end.compact + + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + }, + 'Message' => messages + } + response.status = 200 + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + end + end + + end end end end diff --git a/lib/fog/aws/requests/sqs/send_message.rb b/lib/fog/aws/requests/sqs/send_message.rb index e066d6202..90d25bae7 100644 --- a/lib/fog/aws/requests/sqs/send_message.rb +++ b/lib/fog/aws/requests/sqs/send_message.rb @@ -25,7 +25,45 @@ module Fog end end - + + class Mock + + def send_message(queue_url, message) + Excon::Response.new.tap do |response| + if (queue = data[:queues][queue_url]) + response.status = 200 + + now = Time.now + message_id = Fog::AWS::Mock.sqs_message_id + md5 = Digest::MD5.hexdigest(message) + + queue[:messages][message_id] = { + 'MessageId' => message_id, + 'Body' => message, + 'MD5OfBody' => md5, + 'Attributes' => { + 'SenderId' => Fog::AWS::Mock.sqs_message_id, + 'SentTimestamp' => now + } + } + + queue['Attributes']['LastModifiedTimestamp'] = now + + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + }, + 'MessageId' => message_id, + 'MD5OfMessageBody' => md5 + } + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + end + end + + end end end end diff --git a/lib/fog/aws/requests/sqs/set_queue_attributes.rb b/lib/fog/aws/requests/sqs/set_queue_attributes.rb index 38811bc4c..10c7032d9 100644 --- a/lib/fog/aws/requests/sqs/set_queue_attributes.rb +++ b/lib/fog/aws/requests/sqs/set_queue_attributes.rb @@ -27,7 +27,25 @@ module Fog end end - + + class Mock + def set_queue_attributes(queue_url, attribute_name, attribute_value) + Excon::Response.new.tap do |response| + if (queue = data[:queues][queue_url]) + response.status = 200 + queue['Attributes'][attribute_name] = attribute_value + response.body = { + 'ResponseMetadata' => { + 'RequestId' => Fog::AWS::Mock.request_id + } + } + else + response.status = 404 + raise(Excon::Errors.status_error({:expects => 200}, response)) + end + end + end + end end end end diff --git a/lib/fog/aws/sqs.rb b/lib/fog/aws/sqs.rb index fe2a7b004..87de2f62c 100644 --- a/lib/fog/aws/sqs.rb +++ b/lib/fog/aws/sqs.rb @@ -19,8 +19,38 @@ module Fog request :set_queue_attributes class Mock + def self.data + @data ||= Hash.new do |hash, region| + owner_id = Fog::AWS::Mock.owner_id + hash[region] = Hash.new do |region_hash, key| + region_hash[key] = { + :owner_id => Fog::AWS::Mock.owner_id, + :queues => {} + } + end + end + end + + def self.reset + @data = nil + end def initialize(options={}) + @aws_access_key_id = options[:aws_access_key_id] + + @region = options[:region] || 'us-east-1' + + unless ['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1'].include?(@region) + raise ArgumentError, "Unknown region: #{@region.inspect}" + end + end + + def data + self.class.data[@region][@aws_access_key_id] + end + + def reset_data + self.class.data[@region].delete(@aws_access_key_id) end end diff --git a/tests/aws/requests/sqs/message_tests.rb b/tests/aws/requests/sqs/message_tests.rb index c4dae8a66..7584bf2b8 100644 --- a/tests/aws/requests/sqs/message_tests.rb +++ b/tests/aws/requests/sqs/message_tests.rb @@ -2,9 +2,7 @@ Shindo.tests('AWS::SQS | message requests', ['aws']) do tests('success') do - unless Fog.mocking? - @queue_url = Fog::AWS[:sqs].create_queue('fog_message_tests').body['QueueUrl'] - end + @queue_url = Fog::AWS[:sqs].create_queue('fog_message_tests').body['QueueUrl'] send_message_format = AWS::SQS::Formats::BASIC.merge({ 'MessageId' => String, @@ -12,7 +10,6 @@ Shindo.tests('AWS::SQS | message requests', ['aws']) do }) tests("#send_message('#{@queue_url}', 'message')").formats(send_message_format) do - pending if Fog.mocking? Fog::AWS[:sqs].send_message(@queue_url, 'message').body end @@ -32,19 +29,16 @@ Shindo.tests('AWS::SQS | message requests', ['aws']) do }) tests("#receive_message").formats(receive_message_format) do - pending if Fog.mocking? data = Fog::AWS[:sqs].receive_message(@queue_url).body @receipt_handle = data['Message'].first['ReceiptHandle'] data end tests("#change_message_visibility('#{@queue_url}, '#{@receipt_handle}', 60)").formats(AWS::SQS::Formats::BASIC) do - pending if Fog.mocking? Fog::AWS[:sqs].change_message_visibility(@queue_url, @receipt_handle, 60).body end tests("#delete_message('#{@queue_url}', '#{@receipt_handle}')").formats(AWS::SQS::Formats::BASIC) do - pending if Fog.mocking? Fog::AWS[:sqs].delete_message(@queue_url, @receipt_handle).body end diff --git a/tests/aws/requests/sqs/queue_tests.rb b/tests/aws/requests/sqs/queue_tests.rb index c5757a626..d06daa49f 100644 --- a/tests/aws/requests/sqs/queue_tests.rb +++ b/tests/aws/requests/sqs/queue_tests.rb @@ -7,7 +7,6 @@ Shindo.tests('AWS::SQS | queue requests', ['aws']) do }) tests("#create_queue('fog_queue_tests')").formats(create_queue_format) do - pending if Fog.mocking? data = Fog::AWS[:sqs].create_queue('fog_queue_tests').body @queue_url = data['QueueUrl'] data @@ -18,12 +17,10 @@ Shindo.tests('AWS::SQS | queue requests', ['aws']) do }) tests("#list_queues").formats(list_queues_format) do - pending if Fog.mocking? Fog::AWS[:sqs].list_queues.body end tests("#set_queue_attributes('#{@queue_url}', 'VisibilityTimeout', 60)").formats(AWS::SQS::Formats::BASIC) do - pending if Fog.mocking? Fog::AWS[:sqs].set_queue_attributes(@queue_url, 'VisibilityTimeout', 60).body end @@ -41,12 +38,10 @@ Shindo.tests('AWS::SQS | queue requests', ['aws']) do }) tests("#get_queue_attributes('#{@queue_url}', 'All')").formats(get_queue_attributes_format) do - pending if Fog.mocking? Fog::AWS[:sqs].get_queue_attributes(@queue_url, 'All').body end tests("#delete_queue('#{@queue_url}')").formats(AWS::SQS::Formats::BASIC) do - pending if Fog.mocking? Fog::AWS[:sqs].delete_queue(@queue_url).body end