bane 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +16 -6
  3. data/Rakefile +1 -1
  4. data/TODO +5 -8
  5. data/bin/bane +4 -12
  6. data/examples/multiple_behaviors.rb +7 -6
  7. data/examples/readme_example.rb +2 -1
  8. data/examples/single_behavior.rb +2 -1
  9. data/lib/bane.rb +18 -5
  10. data/lib/bane/arguments_parser.rb +73 -0
  11. data/lib/bane/behavior_maker.rb +39 -0
  12. data/lib/bane/behaviors/responders/close_after_pause.rb +21 -0
  13. data/lib/bane/behaviors/responders/close_immediately.rb +14 -0
  14. data/lib/bane/behaviors/responders/deluge_response.rb +27 -0
  15. data/lib/bane/behaviors/responders/echo_response.rb +16 -0
  16. data/lib/bane/behaviors/responders/exported.rb +9 -0
  17. data/lib/bane/behaviors/responders/fixed_response.rb +25 -0
  18. data/lib/bane/behaviors/responders/for_each_line.rb +18 -0
  19. data/lib/bane/behaviors/responders/http_refuse_all_credentials.rb +31 -0
  20. data/lib/bane/behaviors/responders/never_respond.rb +27 -0
  21. data/lib/bane/behaviors/responders/newline_response.rb +18 -0
  22. data/lib/bane/behaviors/responders/random_response.rb +24 -0
  23. data/lib/bane/behaviors/responders/slow_response.rb +32 -0
  24. data/lib/bane/behaviors/servers/exported.rb +18 -0
  25. data/lib/bane/behaviors/servers/responder_server.rb +50 -0
  26. data/lib/bane/behaviors/servers/timeout_in_listen_queue.rb +51 -0
  27. data/lib/bane/command_line_configuration.rb +22 -79
  28. data/lib/bane/extensions.rb +7 -0
  29. data/test/bane/acceptance_test.rb +65 -0
  30. data/test/bane/arguments_parser_test.rb +76 -0
  31. data/test/bane/bane_test.rb +12 -0
  32. data/test/bane/behaviors/responders/close_after_pause_test.rb +30 -0
  33. data/test/bane/behaviors/responders/close_immediately_test.rb +14 -0
  34. data/test/bane/behaviors/responders/deluge_response_test.rb +20 -0
  35. data/test/bane/behaviors/responders/echo_response_test.rb +16 -0
  36. data/test/bane/behaviors/responders/fixed_response_test.rb +14 -0
  37. data/test/bane/behaviors/responders/for_each_line_test.rb +29 -0
  38. data/test/bane/behaviors/responders/http_refuse_all_credentials_test.rb +18 -0
  39. data/test/bane/behaviors/responders/never_respond_test.rb +31 -0
  40. data/test/bane/behaviors/responders/newline_response_test.rb +14 -0
  41. data/test/bane/behaviors/responders/random_response_test.rb +15 -0
  42. data/test/bane/behaviors/responders/slow_response_test.rb +21 -0
  43. data/test/bane/behaviors/servers/responder_server_test.rb +77 -0
  44. data/test/bane/behaviors/servers/timeout_in_listen_queue_test.rb +23 -0
  45. data/test/bane/command_line_configuration_test.rb +54 -72
  46. data/test/bane/extensions_test.rb +17 -0
  47. data/test/bane/fake_connection_test.rb +1 -1
  48. data/test/bane/launchable_role_tests.rb +20 -0
  49. data/test/bane/naive_http_response_test.rb +1 -1
  50. data/test/test_helper.rb +42 -1
  51. metadata +143 -99
  52. data/lib/bane/behavior_server.rb +0 -47
  53. data/lib/bane/behaviors.rb +0 -171
  54. data/lib/bane/compatibility.rb +0 -36
  55. data/lib/bane/configuration_parser.rb +0 -89
  56. data/lib/bane/service_registry.rb +0 -21
  57. data/test/bane/behavior_server_test.rb +0 -59
  58. data/test/bane/behaviors_test.rb +0 -135
  59. data/test/bane/configuration_parser_test.rb +0 -111
  60. data/test/bane/integration_test.rb +0 -92
  61. data/test/bane/service_registry_test.rb +0 -20
@@ -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
@@ -1,89 +0,0 @@
1
- module Bane
2
-
3
- class ConfigurationParser
4
-
5
- attr_reader :configurations
6
-
7
- def initialize(*args)
8
- warn_about_deprecation()
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
- def warn_about_deprecation
22
- warn "Kernel#Configuration() and ConfigurationParser are deprecated. Please directly construct an array of BehaviorServers to pass to Launcher."
23
- end
24
-
25
- private
26
-
27
- def map_integer_and_behavior_arguments(*args)
28
- port = Integer(args.shift)
29
-
30
- behavior_classes = args
31
- behavior_classes = ServiceRegistry.all_servers if behavior_classes.empty?
32
-
33
- setup_linear_ports(port, behavior_classes)
34
- end
35
-
36
- def setup_linear_ports(port, behavior_classes)
37
- behavior_classes.each_with_index do |behavior, index|
38
- @configurations << create_server(port + index, find(behavior))
39
- end
40
- @configurations
41
- end
42
-
43
- def find(behavior)
44
- case behavior
45
- when String
46
- raise UnknownBehaviorError.new(behavior) unless Behaviors.const_defined?(behavior.to_sym)
47
- Behaviors.const_get(behavior)
48
- when Module
49
- behavior
50
- else
51
- raise UnknownBehaviorError.new(behavior)
52
- end
53
- end
54
-
55
- def map_hash_arguments(options)
56
- options.each_pair do |key, value|
57
- @configurations << extract_configuration_from(key, value)
58
- end
59
- @configurations
60
- end
61
-
62
- def extract_configuration_from(port, value)
63
- case value
64
- when Module
65
- behavior = value
66
- create_server(port, behavior)
67
- when Hash
68
- behavior = value.delete(:behavior)
69
- options = value
70
- create_server(port, behavior, options)
71
- else
72
- raise ConfigurationError, "Unknown configuration option: #{value.inspect}"
73
- end
74
- end
75
-
76
- def create_server(port, behavior, options = {})
77
- BehaviorServer.new(port, behavior.new(options), BehaviorServer::DEFAULT_HOST)
78
- end
79
-
80
- end
81
-
82
- end
83
-
84
- # Helper method to easily create configuration.
85
- module Kernel
86
- def Configuration(*args)
87
- Bane::ConfigurationParser.new(*args).configurations
88
- end
89
- end
@@ -1,21 +0,0 @@
1
- module Bane
2
-
3
- module ServiceRegistry
4
- def self.all_servers
5
- @servers ||= []
6
- end
7
-
8
- def self.all_server_names
9
- all_servers.map(&:simple_name).sort
10
- end
11
-
12
- def self.register(server)
13
- all_servers << server unless all_servers.include?(server)
14
- end
15
-
16
- def self.unregister(server)
17
- all_servers.delete server
18
- end
19
- end
20
-
21
- end
@@ -1,59 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
2
- require 'mocha'
3
-
4
- class BehaviorServerTest < Test::Unit::TestCase
5
- include Bane
6
-
7
- IRRELEVANT_IO_STREAM = nil
8
- IRRELEVANT_OPTIONS = {}
9
- IRRELEVANT_HOST = "1.1.1.1"
10
- IRRELEVANT_BEHAVIOR = nil
11
-
12
- def test_initializes_server_on_specified_port
13
- server = BehaviorServer.new(6000, IRRELEVANT_BEHAVIOR)
14
- assert_equal 6000, server.port
15
- end
16
-
17
- def test_initializes_server_on_specified_hostname
18
- server = BehaviorServer.new(IRRELEVANT_PORT, IRRELEVANT_BEHAVIOR, "hostname")
19
- assert_equal "hostname", server.host
20
- end
21
-
22
- def test_delegates_serve_call_to_behavior
23
- io = mock()
24
- behavior = mock()
25
- server = BehaviorServer.new(IRRELEVANT_PORT, behavior)
26
-
27
- behavior.expects(:serve).with(io)
28
-
29
- server.serve(io)
30
- end
31
-
32
- def test_connection_log_messages_use_short_behavior_name_to_shorten_log_messages
33
- [:connecting, :disconnecting].each do |method|
34
- assert_log_message_uses_short_behavior_name_for(method) do |server|
35
- server.send(method, stub_everything(:peeraddr => [127, 0, 0, 1]))
36
- end
37
- end
38
- end
39
-
40
- def test_start_stop_log_messages_use_short_behavior_name_to_shorten_log_messages
41
- [:starting, :stopping].each do |method|
42
- assert_log_message_uses_short_behavior_name_for(method) do |server|
43
- server.send(method)
44
- end
45
- end
46
- end
47
-
48
- def assert_log_message_uses_short_behavior_name_for(method)
49
- logger = StringIO.new
50
- server = BehaviorServer.new(IRRELEVANT_PORT, Bane::Behaviors::CloseImmediately.new)
51
- server.stdlog = logger
52
-
53
- yield server
54
-
55
- assert_match /CloseImmediately/, logger.string, "Log for #{method} should contain class short name"
56
- assert_no_match /Behaviors::CloseImmediately/, logger.string, "Log for #{method} should not contain expanded module name"
57
- end
58
-
59
- end
@@ -1,135 +0,0 @@
1
- require File.expand_path(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
- def setup
10
- @fake_connection = FakeConnection.new
11
- end
12
-
13
- def test_fixed_response_sends_the_specified_message
14
- query_server(FixedResponse.new(:message => "Test Message"))
15
-
16
- assert_equal "Test Message", response
17
- end
18
-
19
- def test_newline_response_sends_only_a_newline_character
20
- query_server(NewlineResponse.new)
21
-
22
- assert_equal "\n", response
23
- end
24
-
25
- def test_deluge_response_sends_one_million_bytes_by_default
26
- query_server(DelugeResponse.new)
27
-
28
- assert_response_length 1_000_000
29
- end
30
-
31
- def test_deluge_response_accepts_length_parameter
32
- query_server(DelugeResponse.new(:length => 1))
33
-
34
- assert_response_length 1
35
- end
36
-
37
- def test_close_immediately_sends_no_response
38
- query_server(CloseImmediately.new)
39
-
40
- assert_empty_response()
41
- end
42
-
43
- def test_never_respond_never_sends_a_response
44
- server = NeverRespond.new
45
-
46
- assert_raise Timeout::Error do
47
- Timeout::timeout(1) { query_server(server) }
48
- end
49
- assert_empty_response
50
- end
51
-
52
- def test_close_after_pause_sleeps_30_seconds_by_default
53
- server = CloseAfterPause.new
54
- server.expects(:sleep).with(30)
55
-
56
- query_server(server)
57
- end
58
-
59
-
60
- def test_close_after_pause_accepts_duration_parameter
61
- server = CloseAfterPause.new(:duration => 1)
62
- server.expects(:sleep).with(1)
63
-
64
- query_server(server)
65
- end
66
-
67
- def test_close_after_pause_sends_nothing
68
- server = CloseAfterPause.new
69
- server.stubs(:sleep)
70
-
71
- query_server(server)
72
- end
73
-
74
- def test_slow_response_sends_a_message_slowly
75
- message = "Hi!"
76
- delay = 0.5
77
-
78
- server = SlowResponse.new(:pause_duration => delay, :message => message)
79
- server.expects(:sleep).with(delay).at_least(message.length)
80
-
81
- query_server(server)
82
-
83
- assert_equal message, response
84
- end
85
-
86
- def test_random_response_sends_a_nonempty_response
87
- query_server(RandomResponse.new)
88
-
89
- assert (!response.empty?), "Should have served a nonempty response"
90
- end
91
-
92
- def test_refuse_all_http_credentials_sends_401_response_code
93
- @fake_connection.will_send("GET /some/irrelevant/path HTTP/1.1")
94
-
95
- server = HttpRefuseAllCredentials.new
96
- query_server(server)
97
-
98
- assert @fake_connection.read_all_queries?, "Should have read the HTTP query before sending response"
99
- assert_match /HTTP\/1.1 401 Unauthorized/, response, 'Should have responded with the 401 response code'
100
- end
101
-
102
- def test_simple_name_strips_away_the_namespace
103
- assert_equal "SlowResponse", Bane::Behaviors::SlowResponse.simple_name
104
- end
105
-
106
- def test_for_each_line_reads_a_line_before_responding
107
- server = Bane::Behaviors::FixedResponseForEachLine.new({:message => "Dynamic"})
108
-
109
- @fake_connection.will_send "irrelevant\n"
110
-
111
- query_server(server)
112
- assert_equal "Dynamic", response
113
-
114
- assert @fake_connection.read_all_queries?
115
- end
116
-
117
- private
118
-
119
- def query_server(server)
120
- server.serve(@fake_connection)
121
- end
122
-
123
- def response
124
- @fake_connection.string
125
- end
126
-
127
- def assert_empty_response
128
- assert_equal 0, response.length, "Should have sent nothing"
129
- end
130
-
131
- def assert_response_length(expected_length)
132
- assert_equal expected_length, response.length, "Response was the wrong length"
133
- end
134
-
135
- end
@@ -1,111 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
2
- require 'mocha'
3
-
4
- class ConfigurationParserTest < Test::Unit::TestCase
5
-
6
- include Bane
7
-
8
- IRRELEVANT_BEHAVIOR = Bane::Behaviors::CloseImmediately
9
-
10
- def setup
11
- ConfigurationParser.any_instance.stubs(:warn_about_deprecation)
12
- end
13
-
14
- def test_should_map_single_port_and_server_name
15
- expect_server_created_with :port => 3000, :behavior => Behaviors::CloseAfterPause
16
-
17
- ConfigurationParser.new(3000, "CloseAfterPause")
18
- end
19
-
20
- def test_should_map_multiple_servers_given_one_starting_port
21
- expect_server_created_with :port => 3000, :behavior => Behaviors::CloseImmediately
22
- expect_server_created_with :port => 3001, :behavior => Behaviors::CloseAfterPause
23
-
24
- ConfigurationParser.new(3000, "CloseImmediately", "CloseAfterPause")
25
- end
26
-
27
- def test_should_map_string_port
28
- expect_server_created_with :port => 3000, :behavior => IRRELEVANT_BEHAVIOR
29
-
30
- Bane::ConfigurationParser.new("3000", IRRELEVANT_BEHAVIOR)
31
- end
32
-
33
- def test_should_raise_if_unknown_server_name
34
- assert_raises Bane::UnknownBehaviorError do
35
- Bane::ConfigurationParser.new(IRRELEVANT_PORT, "ABehaviorThatDoesNotExist")
36
- end
37
- end
38
-
39
- def test_should_map_server_when_given_class
40
- expect_server_created_with :port => anything(), :behavior => Behaviors::CloseAfterPause
41
-
42
- ConfigurationParser.new(IRRELEVANT_PORT, Behaviors::CloseAfterPause)
43
- end
44
-
45
- def test_should_ask_service_registry_for_all_behaviors_if_none_specified
46
- fake_behavior = unique_behavior
47
- another_fake_behavior = unique_behavior
48
-
49
- expect_server_created_with :port => anything(), :behavior => fake_behavior
50
- expect_server_created_with :port => anything(), :behavior => another_fake_behavior
51
-
52
- ServiceRegistry.expects(:all_servers).returns([fake_behavior, another_fake_behavior])
53
- ConfigurationParser.new(4000)
54
- end
55
-
56
- def test_should_raise_exception_if_no_arguments
57
- assert_raises ConfigurationError do
58
- ConfigurationParser.new
59
- end
60
- end
61
-
62
- def test_should_raise_exception_if_nil_port_with_behaviors
63
- assert_raises ConfigurationError do
64
- ConfigurationParser.new(nil, IRRELEVANT_BEHAVIOR)
65
- end
66
- end
67
-
68
- def test_should_map_single_hash_entry_as_port_and_behavior
69
- expect_server_created_with :port => 10256, :behavior => Behaviors::CloseAfterPause
70
-
71
- ConfigurationParser.new(
72
- 10256 => Behaviors::CloseAfterPause
73
- )
74
- end
75
-
76
- def test_should_map_multiple_hash_entries_as_port_and_behavior
77
- expect_server_created_with :port => 10256, :behavior => Behaviors::CloseAfterPause
78
- expect_server_created_with :port => 6450, :behavior => Behaviors::CloseImmediately
79
-
80
- ConfigurationParser.new(
81
- 10256 => Behaviors::CloseAfterPause,
82
- 6450 => Behaviors::CloseImmediately
83
- )
84
- end
85
-
86
- def test_should_map_hash_with_options
87
- expect_server_created_with :port => 10256, :behavior => Behaviors::CloseAfterPause, :options => { :duration => 3 }
88
- expect_server_created_with :port => 11239, :behavior => Behaviors::CloseImmediately
89
-
90
- ConfigurationParser.new(
91
- 10256 => {:behavior => Behaviors::CloseAfterPause, :duration => 3},
92
- 11239 => Behaviors::CloseImmediately
93
- )
94
- end
95
-
96
- private
97
-
98
- def expect_server_created_with(arguments)
99
- arguments = { :options => anything() }.merge(arguments)
100
- a_behavior_instance = "an instance of #{arguments[:behavior]}.to_s"
101
- behavior = arguments[:behavior]
102
- behavior.expects(:new).with(arguments[:options]).returns(a_behavior_instance)
103
- BehaviorServer.expects(:new).with(arguments[:port], a_behavior_instance, BehaviorServer::DEFAULT_HOST)
104
- end
105
-
106
-
107
- def unique_behavior
108
- Class.new
109
- end
110
-
111
- end