fake_sns 0.0.1
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 +2 -0
- data/.simplecov +4 -0
- data/.travis.yml +5 -0
- data/Gemfile +2 -0
- data/README.md +167 -0
- data/Rakefile +24 -0
- data/bin/fake_sns +79 -0
- data/config.ru +3 -0
- data/fake_sns.gemspec +34 -0
- data/lib/fake_sns/action.rb +24 -0
- data/lib/fake_sns/actions/create_topic.rb +41 -0
- data/lib/fake_sns/actions/delete_topic.rb +13 -0
- data/lib/fake_sns/actions/get_topic_attributes.rb +32 -0
- data/lib/fake_sns/actions/list_subscriptions.rb +24 -0
- data/lib/fake_sns/actions/list_subscriptions_by_topic.rb +23 -0
- data/lib/fake_sns/actions/list_topics.rb +13 -0
- data/lib/fake_sns/actions/publish.rb +37 -0
- data/lib/fake_sns/actions/set_topic_attributes.rb +19 -0
- data/lib/fake_sns/actions/subscribe.rb +43 -0
- data/lib/fake_sns/database.rb +76 -0
- data/lib/fake_sns/deliver_message.rb +100 -0
- data/lib/fake_sns/error.rb +34 -0
- data/lib/fake_sns/error_response.rb +46 -0
- data/lib/fake_sns/message.rb +28 -0
- data/lib/fake_sns/message_collection.rb +40 -0
- data/lib/fake_sns/response.rb +16 -0
- data/lib/fake_sns/server.rb +76 -0
- data/lib/fake_sns/show_output.rb +20 -0
- data/lib/fake_sns/storage.rb +75 -0
- data/lib/fake_sns/subscription.rb +17 -0
- data/lib/fake_sns/subscription_collection.rb +34 -0
- data/lib/fake_sns/test_integration.rb +110 -0
- data/lib/fake_sns/topic.rb +13 -0
- data/lib/fake_sns/topic_collection.rb +41 -0
- data/lib/fake_sns/version.rb +3 -0
- data/lib/fake_sns/views/create_topic.xml.erb +8 -0
- data/lib/fake_sns/views/delete_topic.xml.erb +5 -0
- data/lib/fake_sns/views/error.xml.erb +8 -0
- data/lib/fake_sns/views/get_topic_attributes.xml.erb +15 -0
- data/lib/fake_sns/views/list_subscriptions.xml.erb +18 -0
- data/lib/fake_sns/views/list_subscriptions_by_topic.xml.erb +18 -0
- data/lib/fake_sns/views/list_topics.xml.erb +14 -0
- data/lib/fake_sns/views/publish.xml.erb +8 -0
- data/lib/fake_sns/views/set_topic_attributes.xml.erb +5 -0
- data/lib/fake_sns/views/subscribe.xml.erb +8 -0
- data/lib/fake_sns.rb +51 -0
- data/spec/fake_sns/drain_spec.rb +91 -0
- data/spec/fake_sns/publish_spec.rb +28 -0
- data/spec/fake_sns/replace_spec.rb +14 -0
- data/spec/fake_sns/subscribing_spec.rb +42 -0
- data/spec/fake_sns/topics_spec.rb +44 -0
- data/spec/spec_helper.rb +54 -0
- metadata +271 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
require "etc"
|
2
|
+
require "aws-sdk"
|
3
|
+
|
4
|
+
module FakeSNS
|
5
|
+
class Database
|
6
|
+
|
7
|
+
attr_reader :database_filename
|
8
|
+
|
9
|
+
def initialize(database_filename)
|
10
|
+
@database_filename = database_filename || File.join(Dir.home, ".fake_sns.yml")
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform(action, params)
|
14
|
+
action_instance = action_provider(action).new(self, params)
|
15
|
+
action_instance.call
|
16
|
+
Response.new(action_instance)
|
17
|
+
end
|
18
|
+
|
19
|
+
def topics
|
20
|
+
@topics ||= TopicCollection.new(store)
|
21
|
+
end
|
22
|
+
|
23
|
+
def subscriptions
|
24
|
+
@subscriptions ||= SubscriptionCollection.new(store)
|
25
|
+
end
|
26
|
+
|
27
|
+
def messages
|
28
|
+
@messages ||= MessageCollection.new(store)
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset
|
32
|
+
topics.reset
|
33
|
+
subscriptions.reset
|
34
|
+
messages.reset
|
35
|
+
end
|
36
|
+
|
37
|
+
def transaction
|
38
|
+
store.transaction do
|
39
|
+
yield
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def replace(data)
|
44
|
+
store.replace(data)
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_yaml
|
48
|
+
store.to_yaml
|
49
|
+
end
|
50
|
+
|
51
|
+
def each_deliverable_message
|
52
|
+
topics.each do |topic|
|
53
|
+
subscriptions.each do |subscription|
|
54
|
+
messages.each do |message|
|
55
|
+
if message.topic_arn == topic.arn
|
56
|
+
yield subscription, message
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def store
|
66
|
+
@store ||= Storage.for(database_filename)
|
67
|
+
end
|
68
|
+
|
69
|
+
def action_provider(action)
|
70
|
+
Actions.const_get(action)
|
71
|
+
rescue NameError
|
72
|
+
raise InvalidAction, "not implemented: #{action}"
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "faraday"
|
3
|
+
|
4
|
+
module FakeSNS
|
5
|
+
class DeliverMessage
|
6
|
+
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def self.call(options)
|
10
|
+
new(options).call
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :subscription, :message, :config, :request
|
14
|
+
|
15
|
+
def_delegators :subscription, :protocol, :endpoint, :arn
|
16
|
+
|
17
|
+
def initialize(options)
|
18
|
+
@subscription = options.fetch(:subscription)
|
19
|
+
@message = options.fetch(:message)
|
20
|
+
@request = options.fetch(:request)
|
21
|
+
@config = options.fetch(:config)
|
22
|
+
end
|
23
|
+
|
24
|
+
def call
|
25
|
+
method_name = protocol.gsub("-", "_")
|
26
|
+
if protected_methods.map(&:to_s).include?(method_name)
|
27
|
+
send(method_name)
|
28
|
+
else
|
29
|
+
raise InvalidParameterValue, "Protocol #{protocol} not supported"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def sqs
|
36
|
+
queue_name = endpoint.split(":").last
|
37
|
+
sqs = AWS::SQS.new(config["aws_config"] || {})
|
38
|
+
queue = sqs.queues.named(queue_name)
|
39
|
+
queue.send_message(message_contents)
|
40
|
+
end
|
41
|
+
|
42
|
+
def http
|
43
|
+
http_or_https
|
44
|
+
end
|
45
|
+
|
46
|
+
def https
|
47
|
+
http_or_https
|
48
|
+
end
|
49
|
+
|
50
|
+
def email
|
51
|
+
pending
|
52
|
+
end
|
53
|
+
|
54
|
+
def email_json
|
55
|
+
pending
|
56
|
+
end
|
57
|
+
|
58
|
+
def sms
|
59
|
+
pending
|
60
|
+
end
|
61
|
+
|
62
|
+
def application
|
63
|
+
pending
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def message_contents
|
69
|
+
message.message_for_protocol protocol
|
70
|
+
end
|
71
|
+
|
72
|
+
def pending
|
73
|
+
puts "Not sending to subscription #{arn}, because protocol #{protocol} has no fake implementation. Message: #{message.id} - #{message_contents.inspect}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def http_or_https
|
77
|
+
Faraday.new.post(endpoint) do |f|
|
78
|
+
f.body = {
|
79
|
+
"Type" => "Notification",
|
80
|
+
"MessageId" => message.id,
|
81
|
+
"TopicArn" => message.topic_arn,
|
82
|
+
"Subject" => message.subject,
|
83
|
+
"Message" => message_contents,
|
84
|
+
"Timestamp" => message.received_at.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
85
|
+
"SignatureVersion" => "1",
|
86
|
+
"Signature" => "Fake",
|
87
|
+
"SigningCertURL" => "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem",
|
88
|
+
"UnsubscribeURL" => "", # TODO url to unsubscribe URL on this server
|
89
|
+
}.to_json
|
90
|
+
f.headers = {
|
91
|
+
"x-amz-sns-message-type" => "Notification",
|
92
|
+
"x-amz-sns-message-id" => message.id,
|
93
|
+
"x-amz-sns-topic-arn" => message.topic_arn,
|
94
|
+
"x-amz-sns-subscription-arn" => arn,
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.error_type(status)
|
7
|
+
Class.new(Error) do
|
8
|
+
define_method :status do
|
9
|
+
status
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Common Errors, according to AWS docs
|
15
|
+
IncompleteSignature = error_type 400
|
16
|
+
InternalFailure = error_type 500
|
17
|
+
InvalidAction = error_type 400
|
18
|
+
InvalidClientTokenId = error_type 403
|
19
|
+
InvalidParameterCombination = error_type 400
|
20
|
+
InvalidParameterValue = error_type 400
|
21
|
+
InvalidQueryParameter = error_type 400
|
22
|
+
MalformedQueryString = error_type 400
|
23
|
+
MissingAction = error_type 400
|
24
|
+
MissingAuthenticationToken = error_type 403
|
25
|
+
MissingParameter = error_type 400
|
26
|
+
OptInRequired = error_type 403
|
27
|
+
RequestExpired = error_type 400
|
28
|
+
ServiceUnavailable = error_type 403
|
29
|
+
Throttling = error_type 400
|
30
|
+
|
31
|
+
# Other errors
|
32
|
+
NotFound = error_type 404
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
class ErrorResponse
|
3
|
+
|
4
|
+
DEFAULT_CODE = "InternalFailure"
|
5
|
+
DEFAULT_STATUS = 500
|
6
|
+
|
7
|
+
attr_reader :error, :parameters
|
8
|
+
|
9
|
+
def initialize(error, parameters)
|
10
|
+
@error = error
|
11
|
+
@parameters = parameters
|
12
|
+
end
|
13
|
+
|
14
|
+
def status
|
15
|
+
if error.respond_to?(:status)
|
16
|
+
error.status
|
17
|
+
else
|
18
|
+
DEFAULT_STATUS
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO figure out what this value does
|
23
|
+
def type
|
24
|
+
"Sender"
|
25
|
+
end
|
26
|
+
|
27
|
+
def code
|
28
|
+
if error.respond_to?(:code)
|
29
|
+
error.code
|
30
|
+
elsif error.is_a?(FakeSNS::Error)
|
31
|
+
error.class.to_s.split("::").last
|
32
|
+
else
|
33
|
+
DEFAULT_CODE
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def message
|
38
|
+
error.message
|
39
|
+
end
|
40
|
+
|
41
|
+
def request_id
|
42
|
+
@request_id ||= SecureRandom.uuid
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module FakeSNS
|
4
|
+
class Message
|
5
|
+
|
6
|
+
include Virtus.model
|
7
|
+
|
8
|
+
json = Class.new(Virtus::Attribute) do
|
9
|
+
def coerce(value)
|
10
|
+
value.is_a?(::Hash) ? value : JSON.parse(value)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
attribute :id, String
|
15
|
+
attribute :subject, String
|
16
|
+
attribute :endpoint, String
|
17
|
+
attribute :topic_arn, String
|
18
|
+
attribute :structure, String
|
19
|
+
attribute :target_arn, String
|
20
|
+
attribute :received_at, DateTime
|
21
|
+
attribute :message, json
|
22
|
+
|
23
|
+
def message_for_protocol(type)
|
24
|
+
message.fetch(type.to_s) { message.fetch("default") }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
class MessageCollection
|
3
|
+
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(store)
|
7
|
+
@store = store
|
8
|
+
@store["messages"] ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def collection
|
12
|
+
@store["messages"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset
|
16
|
+
@store["messages"] = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def each(*args, &block)
|
20
|
+
collection.map { |item| Message.new(item) }.each(*args, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch(arn, &default)
|
24
|
+
default ||= -> { raise InvalidParameterValue, "Unknown message #{arn}" }
|
25
|
+
found = collection.find do |message|
|
26
|
+
message["arn"] == arn
|
27
|
+
end
|
28
|
+
found || default.call
|
29
|
+
end
|
30
|
+
|
31
|
+
def create(attributes)
|
32
|
+
collection << attributes
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete(arn)
|
36
|
+
collection.delete(fetch(arn))
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
require "delegate"
|
3
|
+
|
4
|
+
module FakeSNS
|
5
|
+
class Response < SimpleDelegator
|
6
|
+
|
7
|
+
def request_id
|
8
|
+
@request_id ||= SecureRandom.uuid
|
9
|
+
end
|
10
|
+
|
11
|
+
def template
|
12
|
+
__getobj__.class.name.to_s.split("::").last.gsub(/[A-Z]/){|m| "_#{m[0].downcase}"}.sub(/_/, '')
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "fake_sns"
|
2
|
+
require "sinatra/base"
|
3
|
+
|
4
|
+
module FakeSNS
|
5
|
+
class Server < Sinatra::Base
|
6
|
+
|
7
|
+
before do
|
8
|
+
content_type :xml
|
9
|
+
end
|
10
|
+
|
11
|
+
def database
|
12
|
+
$database ||= FakeSNS::Database.new(settings.database)
|
13
|
+
end
|
14
|
+
|
15
|
+
def action
|
16
|
+
params.fetch("Action") { raise MissingAction }
|
17
|
+
end
|
18
|
+
|
19
|
+
get "/" do
|
20
|
+
database.transaction do
|
21
|
+
database.to_yaml
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
post "/" do
|
26
|
+
database.transaction do
|
27
|
+
begin
|
28
|
+
response = database.perform(action, params)
|
29
|
+
status 200
|
30
|
+
erb :"#{response.template}.xml", scope: response
|
31
|
+
rescue Exception => error
|
32
|
+
p error
|
33
|
+
puts(*error.backtrace)
|
34
|
+
error_response = ErrorResponse.new(error, params)
|
35
|
+
status error_response.status
|
36
|
+
erb :"error.xml", scope: error_response
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
delete "/" do
|
42
|
+
database.transaction do
|
43
|
+
database.reset
|
44
|
+
200
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
put "/" do
|
49
|
+
database.replace(request.body.read)
|
50
|
+
200
|
51
|
+
end
|
52
|
+
|
53
|
+
post "/drain" do
|
54
|
+
database.transaction do
|
55
|
+
config = JSON.parse(request.body.read)
|
56
|
+
database.each_deliverable_message do |subscription, message|
|
57
|
+
DeliverMessage.call(subscription: subscription, message: message, request: request, config: config)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
200
|
61
|
+
end
|
62
|
+
|
63
|
+
post "/drain/:message_id" do |message_id|
|
64
|
+
config = JSON.parse(request.body.read)
|
65
|
+
database.transaction do
|
66
|
+
database.each_deliverable_message do |subscription, message|
|
67
|
+
if message.id == message_id
|
68
|
+
DeliverMessage.call(subscription: subscription, message: message, request: request, config: config)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
200
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rack/request'
|
2
|
+
|
3
|
+
module FakeSNS
|
4
|
+
class ShowOutput
|
5
|
+
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
request = Rack::Request.new(env)
|
12
|
+
puts request.params.to_yaml
|
13
|
+
result = @app.call(env)
|
14
|
+
puts
|
15
|
+
puts(*result.last)
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "yaml/store"
|
2
|
+
|
3
|
+
module FakeSNS
|
4
|
+
|
5
|
+
class Storage
|
6
|
+
|
7
|
+
def self.for(database_filename)
|
8
|
+
if database_filename == ":memory:"
|
9
|
+
MemoryStorage.new(database_filename)
|
10
|
+
else
|
11
|
+
FileStorage.new(database_filename)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(database_filename)
|
16
|
+
@database_filename = database_filename
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
storage[key]
|
21
|
+
end
|
22
|
+
|
23
|
+
def []=(key, value)
|
24
|
+
storage[key] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class MemoryStorage < Storage
|
30
|
+
|
31
|
+
def to_yaml
|
32
|
+
storage.to_yaml
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def storage
|
37
|
+
@storage ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def transaction
|
41
|
+
yield
|
42
|
+
end
|
43
|
+
|
44
|
+
def replace(data)
|
45
|
+
@storage = YAML.load(data)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
class FileStorage < Storage
|
51
|
+
|
52
|
+
def to_yaml
|
53
|
+
storage["x"]
|
54
|
+
storage.instance_variable_get(:@table).to_yaml
|
55
|
+
end
|
56
|
+
|
57
|
+
def storage
|
58
|
+
@storage ||= YAML::Store.new(@database_filename)
|
59
|
+
end
|
60
|
+
|
61
|
+
def transaction
|
62
|
+
storage.transaction do
|
63
|
+
yield
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def replace(data)
|
68
|
+
File.open(@database_filename, "w:utf-8") do |f|
|
69
|
+
f.write(data)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
class Subscription
|
3
|
+
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
attribute :arn, String
|
7
|
+
attribute :protocol, String
|
8
|
+
attribute :endpoint, String
|
9
|
+
attribute :topic_arn, String
|
10
|
+
attribute :owner, String
|
11
|
+
|
12
|
+
def sqs?
|
13
|
+
protocol == "sqs"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module FakeSNS
|
2
|
+
class SubscriptionCollection
|
3
|
+
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_reader :collection
|
7
|
+
|
8
|
+
def initialize(store)
|
9
|
+
@store = store
|
10
|
+
@store["subscriptions"] ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def collection
|
14
|
+
@store["subscriptions"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset
|
18
|
+
@store["subscriptions"] = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def each(*args, &block)
|
22
|
+
collection.map { |item| Subscription.new(item) }.each(*args, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(attributes)
|
26
|
+
collection << attributes
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(arn)
|
30
|
+
collection.delete(fetch(arn))
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require "faraday"
|
2
|
+
|
3
|
+
module FakeSNS
|
4
|
+
class TestIntegration
|
5
|
+
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def host
|
13
|
+
option :sns_endpoint
|
14
|
+
end
|
15
|
+
|
16
|
+
def port
|
17
|
+
option :sns_port
|
18
|
+
end
|
19
|
+
|
20
|
+
def start
|
21
|
+
start! unless up?
|
22
|
+
reset
|
23
|
+
end
|
24
|
+
|
25
|
+
def start!
|
26
|
+
@pid = Process.spawn(binfile, "-p", port.to_s, "--database", database, :out => out, :err => out)
|
27
|
+
wait_until_up
|
28
|
+
end
|
29
|
+
|
30
|
+
def stop
|
31
|
+
if @pid
|
32
|
+
Process.kill("INT", @pid)
|
33
|
+
Process.waitpid(@pid)
|
34
|
+
@pid = nil
|
35
|
+
else
|
36
|
+
$stderr.puts "FakeSNS is not running"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset
|
41
|
+
connection.delete("/")
|
42
|
+
end
|
43
|
+
|
44
|
+
def url
|
45
|
+
"http://#{host}:#{port}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def up?
|
49
|
+
@pid && connection.get("/").success?
|
50
|
+
rescue Errno::ECONNREFUSED, Faraday::Error::ConnectionFailed
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
def data
|
55
|
+
YAML.load(connection.get("/").body)
|
56
|
+
end
|
57
|
+
|
58
|
+
def drain(message_id = nil, options = {})
|
59
|
+
path = message_id ? "/drain/#{message_id}" : "/drain"
|
60
|
+
default = { aws_config: AWS.config.send(:supplied) }
|
61
|
+
body = default.merge(options).to_json
|
62
|
+
result = connection.post(path, body)
|
63
|
+
if result.success?
|
64
|
+
true
|
65
|
+
else
|
66
|
+
raise "Unable to drain messages: #{result.body}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def connection
|
71
|
+
@connection ||= Faraday.new(url)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def database
|
77
|
+
options.fetch(:database) { ":memory:" }
|
78
|
+
end
|
79
|
+
|
80
|
+
def option(key)
|
81
|
+
options.fetch(key) { AWS.config.public_send(key) }
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def wait_until_up(deadline = Time.now + 2)
|
86
|
+
fail "FakeSNS didn't start in time" if Time.now > deadline
|
87
|
+
unless up?
|
88
|
+
sleep 0.1
|
89
|
+
wait_until_up(deadline)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def binfile
|
94
|
+
File.expand_path("../../../bin/fake_sns", __FILE__)
|
95
|
+
end
|
96
|
+
|
97
|
+
def out
|
98
|
+
if debug?
|
99
|
+
:out
|
100
|
+
else
|
101
|
+
"/dev/null"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def debug?
|
106
|
+
ENV["DEBUG"].to_s == "true"
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|