bane 0.1.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/HISTORY.md +49 -0
- data/LICENSE +1 -1
- data/README.md +41 -31
- data/TODO +15 -10
- data/bin/bane +8 -11
- data/lib/bane/arguments_parser.rb +75 -0
- data/lib/bane/behavior_maker.rb +41 -0
- data/lib/bane/behaviors/responders/close_after_pause.rb +23 -0
- data/lib/bane/behaviors/responders/close_immediately.rb +16 -0
- data/lib/bane/behaviors/responders/deluge_response.rb +29 -0
- data/lib/bane/behaviors/responders/echo_response.rb +18 -0
- data/lib/bane/behaviors/responders/exported.rb +11 -0
- data/lib/bane/behaviors/responders/fixed_response.rb +27 -0
- data/lib/bane/behaviors/responders/for_each_line.rb +20 -0
- data/lib/bane/behaviors/responders/http_refuse_all_credentials.rb +33 -0
- data/lib/bane/behaviors/responders/never_respond.rb +29 -0
- data/lib/bane/behaviors/responders/newline_response.rb +20 -0
- data/lib/bane/behaviors/responders/random_response.rb +26 -0
- data/lib/bane/behaviors/responders/slow_response.rb +34 -0
- data/lib/bane/behaviors/servers/exported.rb +20 -0
- data/lib/bane/behaviors/servers/responder_server.rb +52 -0
- data/lib/bane/behaviors/servers/timeout_in_listen_queue.rb +53 -0
- data/lib/bane/command_line_configuration.rb +41 -0
- data/lib/bane/extensions.rb +9 -0
- data/lib/bane/launcher.rb +9 -8
- data/lib/bane/naive_http_response.rb +2 -0
- data/lib/bane/version.rb +5 -0
- data/lib/bane.rb +21 -6
- metadata +104 -102
- data/Rakefile +0 -60
- data/examples/simple_port_and_class_as_constant.rb +0 -9
- data/examples/simple_port_and_class_as_string.rb +0 -7
- data/examples/specify_behavior_options.rb +0 -16
- data/examples/specify_ports.rb +0 -15
- data/lib/bane/behaviors.rb +0 -151
- data/lib/bane/compatibility.rb +0 -36
- data/lib/bane/configuration.rb +0 -50
- data/lib/bane/configuration_parser.rb +0 -74
- data/lib/bane/delegating_gserver.rb +0 -42
- data/lib/bane/service_registry.rb +0 -17
- data/test/bane/behaviors_test.rb +0 -137
- data/test/bane/configuration_parser_test.rb +0 -124
- data/test/bane/configuration_test.rb +0 -52
- data/test/bane/delegating_gserver_test.rb +0 -56
- data/test/bane/integration_test.rb +0 -67
- data/test/bane/launcher_test.rb +0 -16
- data/test/bane/naive_http_response_test.rb +0 -69
- data/test/bane/service_registry_test.rb +0 -20
- data/test/test_helper.rb +0 -9
data/lib/bane/behaviors.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
module Bane
|
2
|
-
|
3
|
-
module Behaviors
|
4
|
-
|
5
|
-
class BasicBehavior
|
6
|
-
def self.inherited(clazz)
|
7
|
-
ServiceRegistry.register(clazz)
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.simple_name
|
11
|
-
self.name.split("::").last
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# This module can be used to wrap another behavior with
|
16
|
-
# a "while(io.gets)" loop, which reads a line from the input and
|
17
|
-
# then performs the given behavior.
|
18
|
-
module ForEachLine
|
19
|
-
def serve(io, options)
|
20
|
-
while (io.gets)
|
21
|
-
super(io, options)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Closes the connection immediately after a connection is made.
|
27
|
-
class CloseImmediately < BasicBehavior
|
28
|
-
def serve(io, options)
|
29
|
-
# do nothing
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Accepts a connection, pauses a fixed duration, then closes the connection.
|
34
|
-
#
|
35
|
-
# Options:
|
36
|
-
# - duration: The number of seconds to wait before disconnect. Default: 30
|
37
|
-
class CloseAfterPause < BasicBehavior
|
38
|
-
def serve(io, options)
|
39
|
-
options = {:duration => 30}.merge(options)
|
40
|
-
|
41
|
-
sleep(options[:duration])
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Sends a static response.
|
46
|
-
#
|
47
|
-
# Options:
|
48
|
-
# - message: The response message to send. Default: "Hello, world!"
|
49
|
-
class FixedResponse < BasicBehavior
|
50
|
-
def serve(io, options)
|
51
|
-
options = {:message => "Hello, world!"}.merge(options)
|
52
|
-
|
53
|
-
io.write options[:message]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
class FixedResponseForEachLine < FixedResponse
|
58
|
-
include ForEachLine
|
59
|
-
end
|
60
|
-
|
61
|
-
# Sends a random response.
|
62
|
-
class RandomResponse < BasicBehavior
|
63
|
-
def serve(io, options)
|
64
|
-
io.write random_string
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
def random_string
|
69
|
-
(1..rand(26)+1).map { |i| ('a'..'z').to_a[rand(26)] }.join
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
class RandomResponseForEachLine < RandomResponse
|
75
|
-
include ForEachLine
|
76
|
-
end
|
77
|
-
|
78
|
-
# Sends a fixed response chacter-by-character, pausing in between each character.
|
79
|
-
#
|
80
|
-
# Options:
|
81
|
-
# - message: The response to send. Default: "Hello, world!"
|
82
|
-
# - pause_duration: The number of seconds to pause between each character. Default: 10 seconds
|
83
|
-
class SlowResponse < BasicBehavior
|
84
|
-
def serve(io, options)
|
85
|
-
options = {:message => "Hello, world!", :pause_duration => 10}.merge(options)
|
86
|
-
message = options[:message]
|
87
|
-
pause_duration = options[:pause_duration]
|
88
|
-
|
89
|
-
message.each_char do |char|
|
90
|
-
io.write char
|
91
|
-
sleep pause_duration
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
class SlowResponseForEachLine < SlowResponse
|
97
|
-
include ForEachLine
|
98
|
-
end
|
99
|
-
|
100
|
-
# Accepts a connection and never sends a byte of data. The connection is
|
101
|
-
# left open indefinitely.
|
102
|
-
class NeverRespond < BasicBehavior
|
103
|
-
def serve(io, options)
|
104
|
-
loop { sleep 1 }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Sends a large response. Response consists of a repeated 'x' character.
|
109
|
-
#
|
110
|
-
# Options
|
111
|
-
# - length: The size in bytes of the response to send. Default: 1,000,000 bytes
|
112
|
-
class DelugeResponse < BasicBehavior
|
113
|
-
def serve(io, options)
|
114
|
-
options = {:length => 1_000_000}.merge(options)
|
115
|
-
length = options[:length]
|
116
|
-
|
117
|
-
length.times { io.write('x') }
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
class DelugeResponseForEachLine < DelugeResponse
|
122
|
-
include ForEachLine
|
123
|
-
end
|
124
|
-
|
125
|
-
# Sends an HTTP 401 response (Unauthorized) for every request. This
|
126
|
-
# attempts to mimic an HTTP server by reading a line (the request)
|
127
|
-
# and then sending the response. This behavior responds to all
|
128
|
-
# incoming request URLs on the running port.
|
129
|
-
class HttpRefuseAllCredentials < BasicBehavior
|
130
|
-
UNAUTHORIZED_RESPONSE_BODY = <<EOF
|
131
|
-
<!DOCTYPE html>
|
132
|
-
<html>
|
133
|
-
<head>
|
134
|
-
<title>Bane Server</title>
|
135
|
-
</head>
|
136
|
-
<body>
|
137
|
-
<h1>Unauthorized</h1>
|
138
|
-
</body>
|
139
|
-
</html>
|
140
|
-
EOF
|
141
|
-
|
142
|
-
def serve(io, options)
|
143
|
-
io.gets # Read the request before responding
|
144
|
-
response = NaiveHttpResponse.new(401, "Unauthorized", "text/html", UNAUTHORIZED_RESPONSE_BODY)
|
145
|
-
io.write(response.to_s)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
data/lib/bane/compatibility.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
class String
|
2
|
-
unless "".respond_to?(:each_char)
|
3
|
-
# copied from jcode in Ruby 1.8.6
|
4
|
-
def each_char
|
5
|
-
if block_given?
|
6
|
-
scan(/./m) do |x|
|
7
|
-
yield x
|
8
|
-
end
|
9
|
-
else
|
10
|
-
scan(/./m)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
unless "".respond_to?(:lines)
|
16
|
-
require "enumerator"
|
17
|
-
|
18
|
-
alias_method :lines, :to_a
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Copied from ActiveSupport
|
23
|
-
unless :to_proc.respond_to?(:to_proc)
|
24
|
-
class Symbol
|
25
|
-
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
|
26
|
-
#
|
27
|
-
# # The same as people.collect { |p| p.name }
|
28
|
-
# people.collect(&:name)
|
29
|
-
#
|
30
|
-
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
|
31
|
-
# people.select(&:manager?).collect(&:salary)
|
32
|
-
def to_proc
|
33
|
-
Proc.new { |*args| args.shift.__send__(self, *args) }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/bane/configuration.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Bane
|
2
|
-
|
3
|
-
class Configuration
|
4
|
-
|
5
|
-
def initialize(configurations)
|
6
|
-
@configurations = configurations
|
7
|
-
end
|
8
|
-
|
9
|
-
def start(logger)
|
10
|
-
@configurations.map do |config|
|
11
|
-
config.start(logger)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class ConfigurationRecord
|
16
|
-
|
17
|
-
def initialize(port, behavior, options = {})
|
18
|
-
@port = port
|
19
|
-
@behavior = behavior
|
20
|
-
@options = options
|
21
|
-
end
|
22
|
-
|
23
|
-
def start(logger)
|
24
|
-
new_server = DelegatingGServer.new(@port, @behavior.new, @options, logger)
|
25
|
-
new_server.start
|
26
|
-
new_server
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
class ConfigurationError < RuntimeError; end
|
33
|
-
|
34
|
-
class UnknownBehaviorError < RuntimeError
|
35
|
-
def initialize(name)
|
36
|
-
super "Unknown behavior: #{name}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
# Helper method to easily create configuration.
|
43
|
-
#
|
44
|
-
# This should likely take the constructor block from the Configuration class
|
45
|
-
# and then we can simplify this class so it's not so big.
|
46
|
-
module Kernel
|
47
|
-
def Configuration(*args)
|
48
|
-
Bane::Configuration.new(Bane::ConfigurationParser.new(*args).configurations)
|
49
|
-
end
|
50
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
module Bane
|
2
|
-
|
3
|
-
class ConfigurationParser
|
4
|
-
|
5
|
-
attr_reader :configurations
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(*args)
|
9
|
-
@configurations = []
|
10
|
-
|
11
|
-
@configurations = case args[0]
|
12
|
-
when String, Integer
|
13
|
-
map_integer_and_behavior_arguments(*args)
|
14
|
-
when Hash
|
15
|
-
map_hash_arguments(args[0])
|
16
|
-
else
|
17
|
-
raise ConfigurationError, "Unknown configuration arguments #{args.inspect}"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def map_integer_and_behavior_arguments(*args)
|
24
|
-
port = Integer(args.shift)
|
25
|
-
|
26
|
-
behavior_classes = args
|
27
|
-
behavior_classes = ServiceRegistry.all_servers if behavior_classes.empty?
|
28
|
-
|
29
|
-
setup_linear_ports(port, behavior_classes)
|
30
|
-
end
|
31
|
-
|
32
|
-
def setup_linear_ports(port, behavior_classes)
|
33
|
-
behavior_classes.each_with_index do |behavior, index|
|
34
|
-
@configurations << Bane::Configuration::ConfigurationRecord.new(port + index, find(behavior))
|
35
|
-
end
|
36
|
-
@configurations
|
37
|
-
end
|
38
|
-
|
39
|
-
def find(behavior)
|
40
|
-
case behavior
|
41
|
-
when String
|
42
|
-
raise UnknownBehaviorError.new(behavior) unless Behaviors.const_defined?(behavior.to_sym)
|
43
|
-
Behaviors.const_get(behavior)
|
44
|
-
when Module
|
45
|
-
behavior
|
46
|
-
else
|
47
|
-
raise UnknownBehaviorError.new(behavior)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def map_hash_arguments(options)
|
52
|
-
options.each_pair do |key, value|
|
53
|
-
@configurations << extract_configuration_from(key, value)
|
54
|
-
end
|
55
|
-
@configurations
|
56
|
-
end
|
57
|
-
|
58
|
-
def extract_configuration_from(port, value)
|
59
|
-
case value
|
60
|
-
when Module
|
61
|
-
behavior = value
|
62
|
-
Bane::Configuration::ConfigurationRecord.new(port, behavior)
|
63
|
-
when Hash
|
64
|
-
behavior = value.delete(:behavior)
|
65
|
-
options = value
|
66
|
-
Bane::Configuration::ConfigurationRecord.new(port, behavior, options)
|
67
|
-
else
|
68
|
-
raise ConfigurationError, "Unknown configuration option: #{value.inspect}"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'gserver'
|
2
|
-
|
3
|
-
module Bane
|
4
|
-
class DelegatingGServer < GServer
|
5
|
-
def initialize(port, behavior, options = {}, logger = $stderr)
|
6
|
-
super(port)
|
7
|
-
@behavior = behavior
|
8
|
-
@options = options
|
9
|
-
self.audit = true
|
10
|
-
self.stdlog = logger
|
11
|
-
end
|
12
|
-
|
13
|
-
def serve(io)
|
14
|
-
@behavior.serve(io, @options)
|
15
|
-
end
|
16
|
-
|
17
|
-
protected
|
18
|
-
|
19
|
-
alias_method :original_log, :log
|
20
|
-
|
21
|
-
def log(message)
|
22
|
-
original_log("#{@behavior.class.simple_name} #{@host}:#{@port} #{message}")
|
23
|
-
end
|
24
|
-
|
25
|
-
def connecting(client)
|
26
|
-
addr = client.peeraddr
|
27
|
-
log("client:#{addr[1]} #{addr[2]}<#{addr[3]}> connect")
|
28
|
-
end
|
29
|
-
|
30
|
-
def disconnecting(client_port)
|
31
|
-
log("client:#{client_port} disconnect")
|
32
|
-
end
|
33
|
-
|
34
|
-
def starting()
|
35
|
-
log("start")
|
36
|
-
end
|
37
|
-
|
38
|
-
def stopping()
|
39
|
-
log("stop")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Bane
|
2
|
-
|
3
|
-
module ServiceRegistry
|
4
|
-
def self.all_servers
|
5
|
-
@servers ||= []
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.register(server)
|
9
|
-
all_servers << server unless all_servers.include?(server)
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.unregister(server)
|
13
|
-
all_servers.delete server
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
data/test/bane/behaviors_test.rb
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
-
require 'timeout'
|
3
|
-
require 'mocha'
|
4
|
-
|
5
|
-
class BehaviorsTest < Test::Unit::TestCase
|
6
|
-
|
7
|
-
include Bane::Behaviors
|
8
|
-
|
9
|
-
class FakeConnection < StringIO
|
10
|
-
def will_send(query)
|
11
|
-
@query = query
|
12
|
-
end
|
13
|
-
|
14
|
-
def gets
|
15
|
-
@query
|
16
|
-
@read_query = true
|
17
|
-
end
|
18
|
-
|
19
|
-
def read_query?
|
20
|
-
@read_query
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def setup
|
25
|
-
@fake_connection = FakeConnection.new
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_fixed_response_sends_the_specified_message
|
29
|
-
query_server(create(FixedResponse), :message => "Test Message")
|
30
|
-
|
31
|
-
assert_equal "Test Message", response
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_deluge_response_sends_one_million_bytes_by_default
|
35
|
-
query_server(create DelugeResponse)
|
36
|
-
|
37
|
-
assert_response_length 1_000_000
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_deluge_response_accepts_length_parameter
|
41
|
-
query_server(create(DelugeResponse), :length => 1)
|
42
|
-
|
43
|
-
assert_response_length 1
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_close_immediately_sends_no_response
|
47
|
-
query_server(create CloseImmediately)
|
48
|
-
|
49
|
-
assert_empty_response()
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_never_respond_never_sends_a_response
|
53
|
-
server = create NeverRespond
|
54
|
-
|
55
|
-
assert_raise Timeout::Error do
|
56
|
-
Timeout::timeout(3) { query_server(server) }
|
57
|
-
end
|
58
|
-
assert_empty_response
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_close_after_pause_sleeps_30_seconds_by_default_and_sends_nothing
|
62
|
-
server = create CloseAfterPause
|
63
|
-
server.expects(:sleep).with(30)
|
64
|
-
|
65
|
-
query_server(server)
|
66
|
-
|
67
|
-
assert_empty_response
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_close_after_pause_accepts_duration_parameter
|
71
|
-
server = create CloseAfterPause
|
72
|
-
|
73
|
-
within(2) { query_server(server, :duration => 1) }
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_slow_response_sends_a_message_slowly
|
77
|
-
server = create SlowResponse
|
78
|
-
message = "Hi!"
|
79
|
-
delay = 0.5
|
80
|
-
max_delay = (message.length + 1) * delay
|
81
|
-
|
82
|
-
within(max_delay) { query_server(server, :pause_duration => delay, :message => message)}
|
83
|
-
|
84
|
-
assert_equal message, response
|
85
|
-
end
|
86
|
-
|
87
|
-
def test_random_response_sends_a_nonempty_response
|
88
|
-
query_server(create RandomResponse)
|
89
|
-
|
90
|
-
assert (!response.empty?), "Should have served a nonempty response"
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_refuse_all_http_credentials_sends_401_response_code
|
94
|
-
@fake_connection.will_send("GET /some/irrelevant/path HTTP/1.1")
|
95
|
-
|
96
|
-
server = create(HttpRefuseAllCredentials)
|
97
|
-
query_server(server)
|
98
|
-
|
99
|
-
assert @fake_connection.read_query?, "Should have read the HTTP query before sending response"
|
100
|
-
assert_match /HTTP\/1.1 401 Unauthorized/, response, 'Should have responded with the 401 response code'
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_simple_name_strips_away_the_namespace
|
104
|
-
assert_equal "SlowResponse", Bane::Behaviors::SlowResponse.simple_name
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
def create(server_class)
|
110
|
-
server_class.new()
|
111
|
-
end
|
112
|
-
|
113
|
-
def query_server(server, options = {})
|
114
|
-
server.serve(@fake_connection, options)
|
115
|
-
end
|
116
|
-
|
117
|
-
def response
|
118
|
-
@fake_connection.string
|
119
|
-
end
|
120
|
-
|
121
|
-
def assert_empty_response
|
122
|
-
assert_equal 0, response.length, "Should have sent nothing"
|
123
|
-
end
|
124
|
-
|
125
|
-
def assert_response_length(expected_length)
|
126
|
-
assert_equal expected_length, response.length, "Response was the wrong length"
|
127
|
-
end
|
128
|
-
|
129
|
-
def within(duration)
|
130
|
-
begin
|
131
|
-
Timeout::timeout(duration) { yield }
|
132
|
-
rescue Timeout::Error
|
133
|
-
flunk "Test took too long - should have completed within #{duration} seconds."
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
end
|
@@ -1,124 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
-
require 'mocha'
|
3
|
-
|
4
|
-
class ConfigurationParserTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
include Bane
|
7
|
-
|
8
|
-
IRRELEVANT_BEHAVIOR = Module.new
|
9
|
-
|
10
|
-
def test_should_map_single_port_and_server_name
|
11
|
-
parser = ConfigurationParser.new(3000, "CloseAfterPause")
|
12
|
-
assert_matches_configuration([
|
13
|
-
{:port => 3000, :behavior => Behaviors::CloseAfterPause}
|
14
|
-
], parser)
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_should_map_multiple_servers_given_one_starting_port
|
18
|
-
parser = ConfigurationParser.new(3000, "CloseImmediately", "CloseAfterPause")
|
19
|
-
assert_matches_configuration([
|
20
|
-
{:port => 3000, :behavior => Behaviors::CloseImmediately},
|
21
|
-
{:port => 3001, :behavior => Behaviors::CloseAfterPause}
|
22
|
-
], parser)
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_should_map_string_port
|
26
|
-
parser = Bane::ConfigurationParser.new("3000", IRRELEVANT_BEHAVIOR)
|
27
|
-
actual = parser.configurations[0]
|
28
|
-
assert_equal 3000, actual.instance_variable_get(:@port), "Should have mapped port given a String"
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_should_raise_if_unknown_server_name
|
32
|
-
assert_raises Bane::UnknownBehaviorError do
|
33
|
-
Bane::ConfigurationParser.new(IRRELEVANT_PORT, "ABehaviorThatDoesNotExist")
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_should_map_server_when_given_class
|
38
|
-
parser = ConfigurationParser.new(IRRELEVANT_PORT, Behaviors::CloseAfterPause)
|
39
|
-
actual = parser.configurations[0]
|
40
|
-
assert_equal Behaviors::CloseAfterPause, actual.instance_variable_get(:@behavior), "Wrong behavior"
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_should_ask_service_registry_for_all_behaviors_if_none_specified
|
44
|
-
fake_behavior = unique_behavior
|
45
|
-
another_fake_behavior = unique_behavior
|
46
|
-
|
47
|
-
ServiceRegistry.expects(:all_servers).returns([fake_behavior, another_fake_behavior])
|
48
|
-
parser = ConfigurationParser.new(4000)
|
49
|
-
assert_matches_configuration([
|
50
|
-
{:port => 4000, :behavior => fake_behavior},
|
51
|
-
{:port => 4001, :behavior => another_fake_behavior}
|
52
|
-
], parser)
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_should_raise_exception_if_no_arguments
|
56
|
-
assert_raises ConfigurationError do
|
57
|
-
ConfigurationParser.new
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_should_raise_exception_if_nil_port_with_behaviors
|
62
|
-
assert_raises ConfigurationError do
|
63
|
-
ConfigurationParser.new(nil, IRRELEVANT_BEHAVIOR)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def test_should_map_single_hash_entry_as_port_and_behavior
|
68
|
-
parser = ConfigurationParser.new(
|
69
|
-
10256 => Behaviors::CloseAfterPause
|
70
|
-
)
|
71
|
-
|
72
|
-
assert_matches_configuration([
|
73
|
-
{:port => 10256, :behavior => Behaviors::CloseAfterPause}
|
74
|
-
], parser)
|
75
|
-
end
|
76
|
-
|
77
|
-
def test_should_map_multiple_hash_entries_as_port_and_behavior
|
78
|
-
parser = ConfigurationParser.new(
|
79
|
-
10256 => Behaviors::CloseAfterPause,
|
80
|
-
6450 => Behaviors::CloseImmediately
|
81
|
-
)
|
82
|
-
|
83
|
-
assert_matches_configuration([
|
84
|
-
{:port => 10256, :behavior => Behaviors::CloseAfterPause},
|
85
|
-
{:port => 6450, :behavior => Behaviors::CloseImmediately}
|
86
|
-
], parser)
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_should_map_hash_with_options
|
90
|
-
parser = ConfigurationParser.new(
|
91
|
-
10256 => {:behavior => Behaviors::CloseAfterPause, :duration => 3},
|
92
|
-
11239 => Behaviors::CloseImmediately
|
93
|
-
)
|
94
|
-
|
95
|
-
assert_matches_configuration([
|
96
|
-
{:port => 10256, :behavior => Behaviors::CloseAfterPause},
|
97
|
-
{:port => 11239, :behavior => Behaviors::CloseImmediately}
|
98
|
-
], parser)
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
def assert_matches_configuration(expected_config, actual_config)
|
104
|
-
actual_elements = actual_config.configurations
|
105
|
-
assert_equal expected_config.size, actual_elements.size, "Did not create correct number of configurations. Actual: #{actual_elements}, expected #{expected_config}"
|
106
|
-
|
107
|
-
expected_config.each do |expected|
|
108
|
-
# We make no guarantee on the order of the configurations
|
109
|
-
assert_includes_configuration(actual_elements, expected)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def assert_includes_configuration(actual_elements, expected)
|
114
|
-
expected_port = expected[:port]
|
115
|
-
matching_config = actual_elements.detect { |actual| actual.instance_variable_get(:@port) == expected_port }
|
116
|
-
assert_not_nil matching_config, "Should have found a configuration with port #{expected_port}"
|
117
|
-
assert_equal expected[:behavior], matching_config.instance_variable_get(:@behavior), "Wrong behavior for port #{expected_port}"
|
118
|
-
end
|
119
|
-
|
120
|
-
def unique_behavior
|
121
|
-
Module.new
|
122
|
-
end
|
123
|
-
|
124
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
-
require 'mocha'
|
3
|
-
|
4
|
-
module Bane
|
5
|
-
module Behaviors
|
6
|
-
class FakeTestServer < BasicBehavior
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
class ConfigurationTest < Test::Unit::TestCase
|
12
|
-
|
13
|
-
include Bane
|
14
|
-
|
15
|
-
def test_starts_server_on_specified_port
|
16
|
-
target_port = 4000
|
17
|
-
DelegatingGServer.expects(:new).with(equals(target_port), anything(), anything(), anything()).returns(fake_server)
|
18
|
-
|
19
|
-
start_configuration(target_port, Behaviors::FakeTestServer)
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_starts_server_with_specified_behavior
|
23
|
-
behavior_instance = stub('constructed behavior instance')
|
24
|
-
Behaviors::FakeTestServer.expects(:new).returns(behavior_instance)
|
25
|
-
DelegatingGServer.expects(:new).with(anything(), equals(behavior_instance), anything(), anything()).returns(fake_server)
|
26
|
-
|
27
|
-
start_configuration(IRRELEVANT_PORT, Behaviors::FakeTestServer)
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_constructs_server_with_specified_options
|
31
|
-
options = { :an_option => :a_value, :another_option => :another_value }
|
32
|
-
DelegatingGServer.expects(:new).with(anything(), anything, has_entries(options), anything()).returns(fake_server)
|
33
|
-
|
34
|
-
start_configuration(IRRELEVANT_PORT, Behaviors::FakeTestServer, options)
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def start_configuration(target_port, behavior, options = {})
|
40
|
-
configuration = configuration_with(target_port, behavior, options)
|
41
|
-
configuration.start(StringIO.new)
|
42
|
-
end
|
43
|
-
|
44
|
-
def configuration_with(port, behavior, options)
|
45
|
-
Configuration.new([Configuration::ConfigurationRecord.new(port, behavior, options)])
|
46
|
-
end
|
47
|
-
|
48
|
-
def fake_server
|
49
|
-
stub_everything('fake_server')
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|