fake_servicebus 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.md +20 -0
  7. data/README.md +41 -0
  8. data/Rakefile +31 -0
  9. data/bin/fake_servicebus +65 -0
  10. data/fake_servicebus.gemspec +33 -0
  11. data/lib/fake_servicebus.rb +90 -0
  12. data/lib/fake_servicebus/actions/create_queue.rb +64 -0
  13. data/lib/fake_servicebus/actions/delete_message.rb +19 -0
  14. data/lib/fake_servicebus/actions/delete_queue.rb +18 -0
  15. data/lib/fake_servicebus/actions/get_queue.rb +20 -0
  16. data/lib/fake_servicebus/actions/list_queues.rb +28 -0
  17. data/lib/fake_servicebus/actions/receive_message.rb +44 -0
  18. data/lib/fake_servicebus/actions/renew_lock_message.rb +19 -0
  19. data/lib/fake_servicebus/actions/send_message.rb +22 -0
  20. data/lib/fake_servicebus/actions/unlock_message.rb +19 -0
  21. data/lib/fake_servicebus/api.rb +71 -0
  22. data/lib/fake_servicebus/catch_errors.rb +19 -0
  23. data/lib/fake_servicebus/collection_view.rb +20 -0
  24. data/lib/fake_servicebus/daemonize.rb +30 -0
  25. data/lib/fake_servicebus/databases/file.rb +129 -0
  26. data/lib/fake_servicebus/databases/memory.rb +30 -0
  27. data/lib/fake_servicebus/error_response.rb +55 -0
  28. data/lib/fake_servicebus/error_responses.yml +32 -0
  29. data/lib/fake_servicebus/message.rb +59 -0
  30. data/lib/fake_servicebus/queue.rb +201 -0
  31. data/lib/fake_servicebus/queue_factory.rb +16 -0
  32. data/lib/fake_servicebus/queues.rb +72 -0
  33. data/lib/fake_servicebus/responder.rb +41 -0
  34. data/lib/fake_servicebus/server.rb +19 -0
  35. data/lib/fake_servicebus/show_output.rb +21 -0
  36. data/lib/fake_servicebus/test_integration.rb +122 -0
  37. data/lib/fake_servicebus/version.rb +3 -0
  38. data/lib/fake_servicebus/web_interface.rb +74 -0
  39. data/spec/acceptance/message_actions_spec.rb +452 -0
  40. data/spec/acceptance/queue_actions_spec.rb +82 -0
  41. data/spec/integration_spec_helper.rb +23 -0
  42. data/spec/spec_helper.rb +3 -0
  43. data/spec/unit/api_spec.rb +76 -0
  44. data/spec/unit/catch_errors_spec.rb +43 -0
  45. data/spec/unit/collection_view_spec.rb +41 -0
  46. data/spec/unit/error_response_spec.rb +65 -0
  47. data/spec/unit/message_spec.rb +76 -0
  48. data/spec/unit/queue_factory_spec.rb +13 -0
  49. data/spec/unit/queue_spec.rb +204 -0
  50. data/spec/unit/queues_spec.rb +102 -0
  51. data/spec/unit/responder_spec.rb +44 -0
  52. data/spec/unit/show_output_spec.rb +22 -0
  53. data/spec/unit/web_interface_spec.rb +15 -0
  54. metadata +266 -0
@@ -0,0 +1,82 @@
1
+ require "integration_spec_helper"
2
+
3
+ RSpec.describe "Actions for Queues", :sqs do
4
+
5
+ let(:sqs) { Aws::SQS::Client.new }
6
+ before do
7
+ sqs.config.endpoint = $fake_sqs.uri
8
+ end
9
+
10
+ specify "CreateQueue" do
11
+ response = sqs.create_queue(queue_name: "test-create-queue")
12
+ expect(response.queue_url).to eq "http://0.0.0.0:4568/test-create-queue"
13
+ response2 = sqs.get_queue_attributes(queue_url: response.queue_url)
14
+ expect(response2.attributes.fetch("QueueArn")).to match %r"arn:aws:sqs:us-east-1:.+:test-create-queue"
15
+ end
16
+
17
+ specify "GetQueueUrl" do
18
+ sqs.create_queue(queue_name: "test-get-queue-url")
19
+ response = sqs.get_queue_url(queue_name: "test-get-queue-url")
20
+ expect(response.queue_url).to eq "http://0.0.0.0:4568/test-get-queue-url"
21
+ end
22
+
23
+ specify "ListQueues" do
24
+ sqs.create_queue(queue_name: "test-list-1")
25
+ sqs.create_queue(queue_name: "test-list-2")
26
+ expect(sqs.list_queues.queue_urls).to eq [
27
+ "http://0.0.0.0:4568/test-list-1",
28
+ "http://0.0.0.0:4568/test-list-2"
29
+ ]
30
+ end
31
+
32
+ specify "ListQueues with prefix" do
33
+ sqs.create_queue(queue_name: "test-list-1")
34
+ sqs.create_queue(queue_name: "test-list-2")
35
+ sqs.create_queue(queue_name: "other-list-3")
36
+ expect(sqs.list_queues(queue_name_prefix: "test").queue_urls).to eq [
37
+ "http://0.0.0.0:4568/test-list-1",
38
+ "http://0.0.0.0:4568/test-list-2",
39
+ ]
40
+ end
41
+
42
+ specify "ListDeadLetterSourceQueues" do
43
+ dlq_queue_url = sqs.create_queue(queue_name: "source-list-DLQ").queue_url
44
+ dlq_arn = sqs.get_queue_attributes(queue_url: dlq_queue_url).attributes.fetch("QueueArn")
45
+ source_queue_urls = []
46
+ 2.times do |time|
47
+ queue_url = sqs.create_queue(queue_name: "source-list-#{time}").queue_url
48
+ sqs.set_queue_attributes(queue_url: queue_url,
49
+ attributes: {
50
+ "RedrivePolicy" => "{\"deadLetterTargetArn\":\"#{dlq_arn}\",\"maxReceiveCount\":10}"
51
+ }
52
+ )
53
+ source_queue_urls << queue_url
54
+ end
55
+ expect(sqs.list_dead_letter_source_queues(queue_url: dlq_queue_url).queue_urls).to eq source_queue_urls
56
+ end
57
+
58
+ specify "DeleteQueue" do
59
+ url = sqs.create_queue(queue_name: "test-delete").queue_url
60
+ expect(sqs.list_queues.queue_urls.size).to eq 1
61
+ sqs.delete_queue(queue_url: url)
62
+ expect(sqs.list_queues.queue_urls.size).to eq 0
63
+ end
64
+
65
+ specify "SetQueueAttributes / GetQueueAttributes" do
66
+ queue_url = sqs.create_queue(queue_name: "my-queue").queue_url
67
+
68
+
69
+ sqs.set_queue_attributes(
70
+ queue_url: queue_url,
71
+ attributes: {
72
+ "DelaySeconds" => "900"
73
+ }
74
+ )
75
+
76
+ response = sqs.get_queue_attributes(
77
+ queue_url: queue_url,
78
+ )
79
+ expect(response.attributes.fetch("DelaySeconds")).to eq "900"
80
+ end
81
+
82
+ end
@@ -0,0 +1,23 @@
1
+ require "aws-sdk"
2
+ require "fake_sqs/test_integration"
3
+
4
+ Aws.config.update(
5
+ region: "us-east-1",
6
+ credentials: Aws::Credentials.new("fake", "fake"),
7
+ )
8
+
9
+ db = ENV["SQS_DATABASE"] || ":memory:"
10
+ puts "\n\e[34mRunning specs with database \e[33m#{db}\e[0m"
11
+
12
+ $fake_sqs = FakeSQS::TestIntegration.new(
13
+ database: db,
14
+ sqs_endpoint: "0.0.0.0",
15
+ sqs_port: 4568,
16
+ start_timeout: 2,
17
+ )
18
+
19
+ RSpec.configure do |config|
20
+ config.before(:each, :sqs) { $fake_sqs.start }
21
+ config.before(:each, :sqs) { $fake_sqs.reset }
22
+ config.after(:suite) { $fake_sqs.stop }
23
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.disable_monkey_patching!
3
+ end
@@ -0,0 +1,76 @@
1
+ require 'fake_sqs/api'
2
+
3
+ class FakeSQS::Actions::ImmediateAction
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ end
8
+
9
+ def call(params)
10
+ { :options => @options, :params => params }
11
+ end
12
+
13
+ end
14
+
15
+ class FakeSQS::Actions::PollingAction
16
+
17
+ def initialize(options)
18
+ @options = options
19
+ @call_count = 0
20
+ end
21
+
22
+ def call(params)
23
+ @call_count += 1
24
+ end
25
+
26
+ def satisfied?
27
+ @call_count >= 3
28
+ end
29
+ end
30
+
31
+ RSpec.describe FakeSQS::API do
32
+
33
+ it "delegates actions to classes" do
34
+ queues = double :queues
35
+ allow(queues).to receive(:transaction).and_yield
36
+ api = FakeSQS::API.new(:queues => queues)
37
+
38
+ response = api.call("ImmediateAction", {}, {:foo => "bar"})
39
+
40
+ expect(response[:options]).to eq :queues => queues, :request => {}
41
+ expect(response[:params]).to eq :foo => "bar"
42
+ end
43
+
44
+ it "attempts a polling action until it's satisfied" do
45
+ queues = double :queues
46
+ allow(queues).to receive(:transaction).and_yield
47
+ api = FakeSQS::API.new(:queues => queues)
48
+
49
+ call_count = api.call("PollingAction", {}, {})
50
+ expect(call_count).to eq 3
51
+ end
52
+
53
+ it "raises InvalidAction for unknown actions" do
54
+ api = FakeSQS::API.new(:queues => [])
55
+
56
+ expect {
57
+ api.call("SomethingDifferentAndUnknown", {:foo => "bar"})
58
+ }.to raise_error(FakeSQS::InvalidAction)
59
+
60
+ end
61
+
62
+ it "resets queues" do
63
+ queues = double :queues
64
+ api = FakeSQS::API.new(:queues => queues)
65
+ expect(queues).to receive(:reset)
66
+ api.reset
67
+ end
68
+
69
+ it "expires messages in queues" do
70
+ queues = double :queues
71
+ api = FakeSQS::API.new(:queues => queues)
72
+ expect(queues).to receive(:expire)
73
+ api.expire
74
+ end
75
+
76
+ end
@@ -0,0 +1,43 @@
1
+ require 'fake_sqs/catch_errors'
2
+
3
+ RSpec.describe FakeSQS::CatchErrors do
4
+
5
+ let(:app) { double :app }
6
+ let(:error_response) { double :error_response, :status => 500, :body => "X" }
7
+ let(:response) { double :response, :new => error_response }
8
+ subject(:catch_errors) { FakeSQS::CatchErrors.new(app, response: response) }
9
+
10
+ context "when the app behaves normally" do
11
+
12
+ let(:normal_response) { double :normal_response }
13
+ before { allow(app).to receive(:call).and_return(normal_response) }
14
+
15
+ it "doesn't modify normal responses" do
16
+ expect(catch_errors.call({})).to eq normal_response
17
+ end
18
+
19
+ end
20
+
21
+ context "when the app raises an exception" do
22
+
23
+ let(:error) { RuntimeError.new("it went wrong") }
24
+ before { allow(app).to receive(:call).and_raise(error) }
25
+
26
+ it "cathes and processes errors" do
27
+ expect(response).to receive(:new).with(error)
28
+ catch_errors.call({})
29
+ end
30
+
31
+ it "sets the status determined by the error response" do
32
+ allow(error_response).to receive(:status).and_return(123)
33
+ expect(catch_errors.call({}).fetch(0)).to eq 123
34
+ end
35
+
36
+ it "set the body determined by the error response" do
37
+ allow(error_response).to receive(:body).and_return("foobar")
38
+ expect(catch_errors.call({}).fetch(2)).to eq ["foobar"]
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,41 @@
1
+ require 'fake_sqs/collection_view'
2
+
3
+ RSpec.describe FakeSQS::CollectionView do
4
+
5
+ def wrap(collection)
6
+ FakeSQS::CollectionView.new(collection)
7
+ end
8
+
9
+ it 'should correctly wrap an array' do
10
+ array = %w{one two three four}
11
+ view = wrap(array)
12
+ expect(view[0]).to eq 'one'
13
+ expect(view[1]).to eq 'two'
14
+ expect(view[2]).to eq 'three'
15
+ expect(view[3]).to eq 'four'
16
+ end
17
+
18
+ it 'should correctly wrap a hash' do
19
+ hash = { :one => 1, :two => 2, :three => 3 }
20
+ view = wrap(hash)
21
+ expect(view[:one]).to eq 1
22
+ expect(view[:two]).to eq 2
23
+ expect(view[:three]).to eq 3
24
+ end
25
+
26
+ it 'should respond to empty correctly' do
27
+ expect(wrap([])).to be_empty
28
+ expect(wrap({'one' => 1})).to_not be_empty
29
+ end
30
+
31
+ it 'should be enumerable' do
32
+ result = wrap([1, 2, 3]).map { |i| i * i }
33
+ expect(result).to eq [1, 4, 9]
34
+ end
35
+
36
+ it 'should respond to size/length' do
37
+ expect(wrap([1, 2, 3]).size).to eq 3
38
+ expect(wrap([]).size).to eq 0
39
+ end
40
+
41
+ end
@@ -0,0 +1,65 @@
1
+ require 'fake_sqs/error_response'
2
+ require 'active_support/core_ext/hash'
3
+ require 'verbose_hash_fetch'
4
+
5
+ RSpec.describe FakeSQS::ErrorResponse do
6
+
7
+ module FakeSQS
8
+ MissingCredentials = Class.new(RuntimeError)
9
+ end
10
+ ErrorUnknownToSQS = Class.new(RuntimeError)
11
+
12
+ describe "#status" do
13
+
14
+ it "picks the right error status" do
15
+ error = FakeSQS::MissingCredentials.new("message")
16
+ response = FakeSQS::ErrorResponse.new(error)
17
+ expect(response.status).to eq 401
18
+ end
19
+
20
+ it "uses 400 as default status" do
21
+ error = ErrorUnknownToSQS.new("message")
22
+ response = FakeSQS::ErrorResponse.new(error)
23
+ expect(response.status).to eq 500
24
+ end
25
+
26
+ end
27
+
28
+ describe "#body" do
29
+
30
+ let(:error) { FakeSQS::MissingCredentials.new("the message") }
31
+ let(:response) { FakeSQS::ErrorResponse.new(error) }
32
+ let(:data) { Hash.from_xml(response.body) }
33
+
34
+ it "uses the error class name as error code" do
35
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Code")).to eq "MissingCredentials"
36
+ end
37
+
38
+ it "uses InternalError as code for unknown errors" do
39
+ error = ErrorUnknownToSQS.new("the message")
40
+ response = FakeSQS::ErrorResponse.new(error)
41
+ data = Hash.from_xml(response.body)
42
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Code")).to eq "InternalError"
43
+ end
44
+
45
+ it "uses the to_s of the error as message" do
46
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Message")).to eq "the message"
47
+ end
48
+
49
+ it "has a request id" do
50
+ expect(data.fetch("ErrorResponse").fetch("RequestId").size).to eq 36
51
+ end
52
+
53
+ it "uses Sender as type for 4xx responses" do
54
+ allow(response).to receive(:status).and_return(400)
55
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Type")).to eq "Sender"
56
+ end
57
+
58
+ it "uses Receiver as type for 5xx responses" do
59
+ allow(response).to receive(:status).and_return(500)
60
+ expect(data.fetch("ErrorResponse").fetch("Error").fetch("Type")).to eq "Receiver"
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,76 @@
1
+ require 'fake_sqs/message'
2
+
3
+ RSpec.describe FakeSQS::Message do
4
+
5
+ describe "#body" do
6
+
7
+ it "is extracted from the MessageBody" do
8
+ message = create_message("MessageBody" => "abc")
9
+ expect(message.body).to eq "abc"
10
+ end
11
+
12
+ end
13
+
14
+ describe "#md5" do
15
+
16
+ it "is calculated from body" do
17
+ message = create_message("MessageBody" => "abc")
18
+ expect(message.md5).to eq "900150983cd24fb0d6963f7d28e17f72"
19
+ end
20
+
21
+ end
22
+
23
+ describe "#id" do
24
+
25
+ it "is generated" do
26
+ message = create_message
27
+ expect(message.id.size).to eq 36
28
+ end
29
+
30
+ end
31
+
32
+ describe "#delay_seconds" do
33
+
34
+ it "is generated" do
35
+ message = create_message({"DelaySeconds" => 10})
36
+ expect(message.delay_seconds).to eq 10
37
+ end
38
+
39
+ end
40
+
41
+ describe 'visibility_timeout' do
42
+
43
+ let :message do
44
+ create_message
45
+ end
46
+
47
+ it 'should default to nil' do
48
+ expect(message.visibility_timeout).to eq nil
49
+ end
50
+
51
+ it 'should be expired when it is nil' do
52
+ expect(message).to be_expired
53
+ end
54
+
55
+ it 'should be expired if set to a previous time' do
56
+ message.visibility_timeout = Time.now - 1
57
+ expect(message).to be_expired
58
+ end
59
+
60
+ it 'should not be expired at a future date' do
61
+ message.visibility_timeout = Time.now + 1
62
+ expect(message).not_to be_expired
63
+ end
64
+
65
+ it 'should not be expired when set to expire at a future date' do
66
+ message.expire_at(5)
67
+ expect(message.visibility_timeout).to be >=(Time.now + 4)
68
+ end
69
+
70
+ end
71
+
72
+ def create_message(options = {})
73
+ FakeSQS::Message.new({"MessageBody" => "test"}.merge(options))
74
+ end
75
+
76
+ end
@@ -0,0 +1,13 @@
1
+ require 'fake_sqs/queue_factory'
2
+
3
+ RSpec.describe FakeSQS::QueueFactory do
4
+
5
+ it "builds queues with a message factory" do
6
+ message_factory = double :message_factory
7
+ queue = double :queue
8
+ queue_factory = FakeSQS::QueueFactory.new(message_factory: message_factory, queue: queue)
9
+ expect(queue).to receive(:new).with(message_factory: message_factory, name: "Foo")
10
+ queue_factory.new(name: "Foo")
11
+ end
12
+
13
+ end
@@ -0,0 +1,204 @@
1
+ require 'fake_sqs/queue'
2
+ require 'fake_sqs/message'
3
+
4
+ RSpec.describe FakeSQS::Queue do
5
+
6
+ class MessageFactory
7
+ def new(options = {})
8
+ FakeSQS::Message.new({'MessageBody' => 'sample-body'}.merge(options))
9
+ end
10
+ end
11
+
12
+ let(:message_factory) { MessageFactory.new }
13
+ subject(:queue) { FakeSQS::Queue.new(:message_factory => message_factory, "QueueName" => "test-queue") }
14
+
15
+ describe "#send_message" do
16
+
17
+ it "adds a message" do
18
+ expect(queue.messages.size).to eq 0
19
+ send_message
20
+ expect(queue.messages.size).to eq 1
21
+ end
22
+
23
+ it "returns the message" do
24
+ message = double.as_null_object
25
+ allow(message_factory).to receive(:new).and_return(message)
26
+ expect(send_message).to eq message
27
+ end
28
+
29
+ it "uses the message factory" do
30
+ options = { "MessageBody" => "abc" }
31
+ expect(message_factory).to receive(:new).with(options)
32
+ send_message(options)
33
+ end
34
+
35
+ it "should set the message's SentTimestamp attribute" do
36
+ expect(send_message.attributes["SentTimestamp"]).to eq (Time.now.to_i * 1000)
37
+ end
38
+
39
+ it "should set the SenderId of the sender" do
40
+ sender_id = send_message.attributes["SenderId"]
41
+ expect(sender_id).to be_a String
42
+ expect(sender_id.length).to eq 21
43
+ end
44
+ end
45
+
46
+ describe "#receive_message" do
47
+
48
+ it "gets the message" do
49
+ sent = send_message
50
+ received = receive_message
51
+ expect(received.values.first).to eq sent
52
+ end
53
+
54
+ it "gets the message with 'DelaySeconds' option" do
55
+ delay_seconds = 3
56
+ sent = send_message({ "DelaySeconds" => delay_seconds })
57
+ received = receive_message
58
+ expect(received.values.first).to be_nil
59
+
60
+ allow(Time).to receive(:now).and_return(Time.now + delay_seconds)
61
+ received = receive_message
62
+ expect(received.values.first).to eq sent
63
+ end
64
+
65
+ it "gets you a random message" do
66
+ indexes = { :first => 0, :second => 0 }
67
+ sample_group = 1_000
68
+ half_sample_group = sample_group / 2
69
+ ten_percent = half_sample_group / 0.1
70
+
71
+ sample_group.times do
72
+ sent_first = send_message
73
+ _ = send_message
74
+ message = receive_message.values.first
75
+ if message == sent_first
76
+ indexes[:first] += 1
77
+ else
78
+ indexes[:second] += 1
79
+ end
80
+ reset_queue
81
+ end
82
+
83
+ expect(indexes[:first] + indexes[:second]).to eq sample_group
84
+
85
+ expect(indexes[:first]).to be_within(ten_percent).of(half_sample_group)
86
+ expect(indexes[:second]).to be_within(ten_percent).of(half_sample_group)
87
+ end
88
+
89
+ it "cannot get received messages" do
90
+ sample_group = 1_000
91
+
92
+ sample_group.times do
93
+ sent_first = send_message
94
+ sent_second = send_message
95
+ received_first = receive_message.values.first
96
+
97
+ if received_first == sent_first
98
+ expect(receive_message.values.first).to eq sent_second
99
+ else
100
+ expect(receive_message.values.first).to eq sent_first
101
+ end
102
+ reset_queue
103
+ end
104
+ end
105
+
106
+ it "keeps track of sent messages" do
107
+
108
+ send_message
109
+
110
+ expect(queue.messages_in_flight.size).to eq 0
111
+ expect(queue.attributes["ApproximateNumberOfMessagesNotVisible"]).to eq 0
112
+ expect(queue.attributes["ApproximateNumberOfMessages"]).to eq 1
113
+
114
+ receive_message
115
+
116
+ expect(queue.messages_in_flight.size).to eq 1
117
+ expect(queue.attributes["ApproximateNumberOfMessagesNotVisible"]).to eq 1
118
+ expect(queue.attributes["ApproximateNumberOfMessages"]).to eq 0
119
+ end
120
+
121
+ it "gets multiple message" do
122
+ sent_first = send_message
123
+ sent_second = send_message
124
+ messages = receive_message("MaxNumberOfMessages" => "2")
125
+ expect(messages.size).to eq 2
126
+ expect(messages.values).to match_array [ sent_first, sent_second ]
127
+ end
128
+
129
+ it "won't accept more than 10 message" do
130
+ expect {
131
+ receive_message("MaxNumberOfMessages" => "11")
132
+ }.to raise_error(FakeSQS::ReadCountOutOfRange, "11")
133
+ end
134
+
135
+ it "won't error on empty queues" do
136
+ expect(receive_message).to eq({})
137
+ end
138
+
139
+ it "should increment the ApproximateReceiveCount" do
140
+ sent_message = send_message
141
+ expect(sent_message.attributes["ApproximateReceiveCount"]).to eq 0
142
+ queue.change_message_visibility(receive_message.keys.first, 0)
143
+ expect(sent_message.attributes["ApproximateReceiveCount"]).to eq 1
144
+ receive_message
145
+ expect(sent_message.attributes["ApproximateReceiveCount"]).to eq 2
146
+ end
147
+
148
+ it "should set the ApproximateFirstReceiveTimestamp only when the message is first received" do
149
+ sent_message = send_message
150
+ expect(sent_message.attributes["ApproximateFirstReceiveTimestamp"]).to eq nil
151
+ receive_time = (Time.now.to_i * 1000)
152
+ queue.change_message_visibility(receive_message.keys.first, 0)
153
+ expect(sent_message.attributes["ApproximateFirstReceiveTimestamp"]).to eq receive_time
154
+ sleep 1
155
+ receive_message
156
+ expect(sent_message.attributes["ApproximateFirstReceiveTimestamp"]).to eq receive_time
157
+ end
158
+ end
159
+
160
+ describe "#delete_message" do
161
+
162
+ it "deletes by the receipt" do
163
+ send_message
164
+ receipt = receive_message.keys.first
165
+
166
+ expect(queue.messages_in_flight.size).to eq 1
167
+ queue.delete_message(receipt)
168
+ expect(queue.messages_in_flight.size).to eq 0
169
+ expect(queue.messages.size).to eq 0
170
+ end
171
+
172
+ it "won't raise if the receipt is unknown" do
173
+ queue.delete_message("abc")
174
+ end
175
+
176
+ end
177
+
178
+ describe "#add_queue_attributes" do
179
+
180
+ it "adds to it's queue attributes" do
181
+ queue.add_queue_attributes("foo" => "bar")
182
+ expect(queue.attributes).to eq(
183
+ "foo" => "bar",
184
+ "QueueArn" => queue.arn,
185
+ "ApproximateNumberOfMessages" => 0,
186
+ "ApproximateNumberOfMessagesNotVisible" => 0
187
+ )
188
+ end
189
+
190
+ end
191
+
192
+ def send_message(options = {})
193
+ queue.send_message(options)
194
+ end
195
+
196
+ def receive_message(options = {})
197
+ queue.receive_message(options)
198
+ end
199
+
200
+ def reset_queue
201
+ queue.reset
202
+ end
203
+
204
+ end