fake_servicebus 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +4 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.md +20 -0
- data/README.md +41 -0
- data/Rakefile +31 -0
- data/bin/fake_servicebus +65 -0
- data/fake_servicebus.gemspec +33 -0
- data/lib/fake_servicebus.rb +90 -0
- data/lib/fake_servicebus/actions/create_queue.rb +64 -0
- data/lib/fake_servicebus/actions/delete_message.rb +19 -0
- data/lib/fake_servicebus/actions/delete_queue.rb +18 -0
- data/lib/fake_servicebus/actions/get_queue.rb +20 -0
- data/lib/fake_servicebus/actions/list_queues.rb +28 -0
- data/lib/fake_servicebus/actions/receive_message.rb +44 -0
- data/lib/fake_servicebus/actions/renew_lock_message.rb +19 -0
- data/lib/fake_servicebus/actions/send_message.rb +22 -0
- data/lib/fake_servicebus/actions/unlock_message.rb +19 -0
- data/lib/fake_servicebus/api.rb +71 -0
- data/lib/fake_servicebus/catch_errors.rb +19 -0
- data/lib/fake_servicebus/collection_view.rb +20 -0
- data/lib/fake_servicebus/daemonize.rb +30 -0
- data/lib/fake_servicebus/databases/file.rb +129 -0
- data/lib/fake_servicebus/databases/memory.rb +30 -0
- data/lib/fake_servicebus/error_response.rb +55 -0
- data/lib/fake_servicebus/error_responses.yml +32 -0
- data/lib/fake_servicebus/message.rb +59 -0
- data/lib/fake_servicebus/queue.rb +201 -0
- data/lib/fake_servicebus/queue_factory.rb +16 -0
- data/lib/fake_servicebus/queues.rb +72 -0
- data/lib/fake_servicebus/responder.rb +41 -0
- data/lib/fake_servicebus/server.rb +19 -0
- data/lib/fake_servicebus/show_output.rb +21 -0
- data/lib/fake_servicebus/test_integration.rb +122 -0
- data/lib/fake_servicebus/version.rb +3 -0
- data/lib/fake_servicebus/web_interface.rb +74 -0
- data/spec/acceptance/message_actions_spec.rb +452 -0
- data/spec/acceptance/queue_actions_spec.rb +82 -0
- data/spec/integration_spec_helper.rb +23 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/api_spec.rb +76 -0
- data/spec/unit/catch_errors_spec.rb +43 -0
- data/spec/unit/collection_view_spec.rb +41 -0
- data/spec/unit/error_response_spec.rb +65 -0
- data/spec/unit/message_spec.rb +76 -0
- data/spec/unit/queue_factory_spec.rb +13 -0
- data/spec/unit/queue_spec.rb +204 -0
- data/spec/unit/queues_spec.rb +102 -0
- data/spec/unit/responder_spec.rb +44 -0
- data/spec/unit/show_output_spec.rb +22 -0
- data/spec/unit/web_interface_spec.rb +15 -0
- 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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|