LanGrove 0.0.1
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.
- data/.rspec +1 -0
- data/.rvmrc +62 -0
- data/.watchr +19 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +61 -0
- data/Rakefile +17 -0
- data/bin/datagram_example +4 -0
- data/config/boot.rb +64 -0
- data/config/daemons.yml.tmpl +78 -0
- data/config/environment.rb +28 -0
- data/config/environments/development.rb +0 -0
- data/config/environments/production.rb +0 -0
- data/config/environments/test.rb +0 -0
- data/lib/adaptor/base.rb +1 -0
- data/lib/adaptor/datagram.rb +20 -0
- data/lib/adaptor/socket_handler.rb +27 -0
- data/lib/adaptor_base.rb +39 -0
- data/lib/client/base.rb +1 -0
- data/lib/client/puppet_state.rb +74 -0
- data/lib/client/radio_state.rb +81 -0
- data/lib/client_base.rb +24 -0
- data/lib/daemon/base.rb +1 -0
- data/lib/daemon/datagram_example.rb +12 -0
- data/lib/daemon_base.rb +168 -0
- data/lib/ext/config_item.rb +35 -0
- data/lib/ext/config_loader.rb +16 -0
- data/lib/ext/persistable.rb +103 -0
- data/lib/ext/string.rb +35 -0
- data/lib/handler/base.rb +1 -0
- data/lib/handler/socket_to_file.rb +30 -0
- data/lib/handler_base.rb +125 -0
- data/lib/jobs/Rakefile +0 -0
- data/lib/jobs/jobs.rb +1 -0
- data/lib/jobs/updated_puppet_state.rb +17 -0
- data/lib/protocol_base.rb +5 -0
- data/libexec/daemon.rb +57 -0
- data/spec/adaptor/datagram_spec.rb +6 -0
- data/spec/adaptor/socket_handler_spec.rb +5 -0
- data/spec/adaptor_base_spec.rb +45 -0
- data/spec/client_base_spec.rb +5 -0
- data/spec/daemon_base_spec.rb +97 -0
- data/spec/ext/config_item_spec.rb +77 -0
- data/spec/ext/config_loader_spec.rb +5 -0
- data/spec/ext/persistable_spec.rb +118 -0
- data/spec/ext/string_spec.rb +16 -0
- data/spec/functional/datagram_spec.rb +122 -0
- data/spec/handler_base_spec.rb +71 -0
- data/spec/protocol_base_spec.rb +6 -0
- data/spec/todo_spec.rb +13 -0
- data/tmp/TMP +0 -0
- metadata +97 -0
data/lib/daemon_base.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
require 'ext/string'
|
4
|
+
|
5
|
+
class DaemonConfigException < Exception; end
|
6
|
+
|
7
|
+
module Daemon class Base
|
8
|
+
|
9
|
+
def listen
|
10
|
+
|
11
|
+
#
|
12
|
+
# Handler, the CollectionOfClients,
|
13
|
+
# is passed through the adaptor to
|
14
|
+
# be assigned to the attaching sockets.
|
15
|
+
#
|
16
|
+
|
17
|
+
@adaptor.listen( @handler )
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def stop_daemon
|
22
|
+
|
23
|
+
#
|
24
|
+
# Handle stopping daemon
|
25
|
+
#
|
26
|
+
@logger.info "#{self} received stop_daemon"
|
27
|
+
@handler.stop_daemon
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def reload_daemon
|
32
|
+
|
33
|
+
#
|
34
|
+
# TODO: Handle reloading daemon properly
|
35
|
+
#
|
36
|
+
# [ !!complexities abound around reloading config!! ]
|
37
|
+
#
|
38
|
+
|
39
|
+
@logger.info "#{self} received reload_daemon"
|
40
|
+
@handler.reload_daemon
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def schedule
|
45
|
+
|
46
|
+
EM::add_periodic_timer( @my_config['periodic'] ) do
|
47
|
+
|
48
|
+
@logger.info "#{self} Scheduling periodic ...TODO..."
|
49
|
+
|
50
|
+
#
|
51
|
+
# TODO: This can be a lot more usefull than
|
52
|
+
# then one ticker to one function call
|
53
|
+
#
|
54
|
+
|
55
|
+
@handler.periodic
|
56
|
+
|
57
|
+
end if @my_config.has_key? 'periodic'
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def run
|
62
|
+
|
63
|
+
EventMachine::run do
|
64
|
+
|
65
|
+
#
|
66
|
+
# https://github.com/eventmachine/eventmachine/wiki/Protocol-Implementations
|
67
|
+
#
|
68
|
+
|
69
|
+
schedule
|
70
|
+
|
71
|
+
listen if @server
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
def initialize( config_hash, daemon_name, logger )
|
78
|
+
|
79
|
+
@config = config_hash
|
80
|
+
@daemon_name = daemon_name
|
81
|
+
@logger = logger
|
82
|
+
@server = true
|
83
|
+
|
84
|
+
#
|
85
|
+
# A network connection.
|
86
|
+
#
|
87
|
+
@adaptor = nil
|
88
|
+
|
89
|
+
#
|
90
|
+
# A handler to direct the traffic.
|
91
|
+
#
|
92
|
+
@handler = nil
|
93
|
+
|
94
|
+
|
95
|
+
begin
|
96
|
+
|
97
|
+
@logger.info "Starting daemon: #{@daemon_name}"
|
98
|
+
|
99
|
+
rescue
|
100
|
+
|
101
|
+
#
|
102
|
+
# you shall not pass
|
103
|
+
#
|
104
|
+
raise DaemonConfigException.new( "Requires a logger" )
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
begin
|
109
|
+
|
110
|
+
@my_config = config_hash['daemons'][daemon_name]
|
111
|
+
|
112
|
+
@server = @my_config['listen'] if @my_config.has_key? 'listen'
|
113
|
+
|
114
|
+
adaptor = @my_config['adaptor']['connection']
|
115
|
+
|
116
|
+
handler = @my_config['handler']['collection']
|
117
|
+
|
118
|
+
rescue
|
119
|
+
|
120
|
+
error = "Missing config item for daemon: #{daemon_name}"
|
121
|
+
|
122
|
+
@logger.error "EXIT: #{error}"
|
123
|
+
|
124
|
+
raise DaemonConfigException.new(
|
125
|
+
|
126
|
+
"Missing config item for daemon: #{daemon_name}"
|
127
|
+
|
128
|
+
)
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# initialize the connection adaptor specified in config
|
134
|
+
#
|
135
|
+
# daemons:
|
136
|
+
# name_of_daemon:
|
137
|
+
# adaptor:
|
138
|
+
# connection: TcpServer <----------
|
139
|
+
# handler:
|
140
|
+
# collection: CollectionOfClients
|
141
|
+
#
|
142
|
+
|
143
|
+
@logger.info "Initialize connection: Adaptor::#{adaptor}.new( @my_config['adaptor'], logger )"
|
144
|
+
eval "require 'adaptor/#{adaptor.underscore}'"
|
145
|
+
@adaptor = Adaptor.const_get(adaptor).new( @my_config['adaptor'], logger )
|
146
|
+
|
147
|
+
|
148
|
+
#
|
149
|
+
# bind to the handler collection specified in config
|
150
|
+
#
|
151
|
+
# daemons:
|
152
|
+
# name_of_daemon:
|
153
|
+
# adaptor:
|
154
|
+
# connection: TcpServer
|
155
|
+
# handler:
|
156
|
+
# collection: CollectionOfClients <----------
|
157
|
+
#
|
158
|
+
# CollectionOfClients ---> is the handler passed into listen()
|
159
|
+
#
|
160
|
+
|
161
|
+
@logger.info "Initialize collection: #{handler}.new( config_hash, daemon_name, logger )"
|
162
|
+
eval "require 'handler/#{handler.underscore}'"
|
163
|
+
@handler = Handler.const_get(handler).new( config_hash, daemon_name, logger )
|
164
|
+
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end; end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class ConfigException < Exception
|
2
|
+
|
3
|
+
end
|
4
|
+
|
5
|
+
class ConfigItem
|
6
|
+
|
7
|
+
def self.get(config_hash, key_array, mandatory = true)
|
8
|
+
|
9
|
+
# raise ConfigException.new("match")
|
10
|
+
|
11
|
+
hash = config_hash
|
12
|
+
|
13
|
+
key_array.each do |key|
|
14
|
+
|
15
|
+
if mandatory != false then
|
16
|
+
# raises a config exception if the item isnt present
|
17
|
+
raise ConfigException.new("Missing config item '#{key}'") unless hash.has_key?(key)
|
18
|
+
|
19
|
+
# raises a config exception if the nested item isnt present NEITHER NOT
|
20
|
+
# raise ConfigException.new("Missing config item '#{key}'") if hash[key].empty?
|
21
|
+
|
22
|
+
hash = hash[key]
|
23
|
+
|
24
|
+
# raises a config exception if the key isnt present BLANK NEITHER
|
25
|
+
raise ConfigException.new("Missing config item '#{key}'") if hash == ""
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
return hash
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'resque'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
# require 'updated_puppet_state'
|
5
|
+
|
6
|
+
class Persistable
|
7
|
+
|
8
|
+
def initialize( notifies = [] )
|
9
|
+
|
10
|
+
@notifies = notifies
|
11
|
+
|
12
|
+
@notifies.each do |worker|
|
13
|
+
|
14
|
+
Object.const_set(
|
15
|
+
|
16
|
+
worker.camelize, Class.new
|
17
|
+
|
18
|
+
) ### ??unless defined already??
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_hash( hash_instance, from_file )
|
25
|
+
#
|
26
|
+
# <hash_instance> as String (name of) variable storing the Hash
|
27
|
+
#
|
28
|
+
|
29
|
+
@logger.debug "loading from: #{from_file}" if @logger
|
30
|
+
|
31
|
+
#
|
32
|
+
# get the instance variable (late bind)
|
33
|
+
#
|
34
|
+
hash = self.instance_variable_get( hash_instance.to_sym )
|
35
|
+
hash ||= {}
|
36
|
+
|
37
|
+
begin
|
38
|
+
|
39
|
+
#
|
40
|
+
# load file contents, merge into hash and
|
41
|
+
# store it at the instance variable
|
42
|
+
#
|
43
|
+
persisted = YAML.load_file( from_file )
|
44
|
+
hash.merge!( persisted ) if persisted.is_a?( Hash )
|
45
|
+
self.instance_variable_set( hash_instance.to_sym, hash )
|
46
|
+
|
47
|
+
#
|
48
|
+
# set flag to 'already in storage'
|
49
|
+
#
|
50
|
+
@stored = true
|
51
|
+
|
52
|
+
rescue Exception => e
|
53
|
+
@logger.error "FAILED loading from #{from_file} #{e}" if @logger
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def store_hash( hash_instance, to_file )
|
60
|
+
#
|
61
|
+
# <hash_instance> as String (name of) variable storing the Hash
|
62
|
+
#
|
63
|
+
|
64
|
+
if @stored != nil && @stored
|
65
|
+
|
66
|
+
@logger.debug "storing to: #{to_file} skipped - no change"
|
67
|
+
return
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
@logger.debug "storing to: #{to_file}"
|
72
|
+
|
73
|
+
#
|
74
|
+
# get the instance variable (late bind)
|
75
|
+
#
|
76
|
+
hash = self.instance_variable_get( hash_instance.to_sym )
|
77
|
+
|
78
|
+
begin
|
79
|
+
|
80
|
+
File.open(to_file, 'w') do |f|
|
81
|
+
|
82
|
+
YAML::dump( hash, f )
|
83
|
+
@stored = true
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
#@notifies.each do |worker|
|
88
|
+
#
|
89
|
+
# Resque.enqueue(
|
90
|
+
#
|
91
|
+
# Object.const_get( worker.camelize ), to_file
|
92
|
+
#
|
93
|
+
# )
|
94
|
+
#
|
95
|
+
#end
|
96
|
+
|
97
|
+
rescue Exception => e
|
98
|
+
@logger.error "FAILED storing to: #{to_file} #{e}" if @logger
|
99
|
+
@stored = false
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/ext/string.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# extend ruby String class
|
2
|
+
|
3
|
+
class String
|
4
|
+
#
|
5
|
+
# from the rails inflector
|
6
|
+
# (de-camelize)
|
7
|
+
#
|
8
|
+
# ie. CamelThing becomes camel_thing
|
9
|
+
#
|
10
|
+
def underscore
|
11
|
+
gsub(/::/, '/').
|
12
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
13
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
14
|
+
tr("-", "_").
|
15
|
+
downcase
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# unless already defined
|
20
|
+
#
|
21
|
+
end unless String.method_defined?(:underscore)
|
22
|
+
|
23
|
+
class String
|
24
|
+
#
|
25
|
+
# from the rails inflector
|
26
|
+
# (camelize)
|
27
|
+
#
|
28
|
+
# ie. CamelThing becomes camel_thing
|
29
|
+
#
|
30
|
+
def camelize(first_letter_in_uppercase = :upper)
|
31
|
+
s = gsub(/\/(.?)/){|x| "::#{x[-1..-1].upcase unless x == '/'}"}.gsub(/(^|_)(.)/){|x| x[-1..-1].upcase}
|
32
|
+
s[0...1] = s[0...1].downcase unless first_letter_in_uppercase == :upper
|
33
|
+
s
|
34
|
+
end
|
35
|
+
end unless String.method_defined?(:camelize)
|
data/lib/handler/base.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'handler_base'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# Mainly to facilitate functional tests
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'handler/base'
|
6
|
+
|
7
|
+
module Handler
|
8
|
+
|
9
|
+
class SocketToFile < Base
|
10
|
+
|
11
|
+
def message( data )
|
12
|
+
|
13
|
+
@logger.debug( "Received: #{data}" )
|
14
|
+
|
15
|
+
filename = data.split('|')[0]
|
16
|
+
filecontents = data.split('|',2)[1]
|
17
|
+
|
18
|
+
File.open( filename, 'w' ) do |f|
|
19
|
+
|
20
|
+
f.write( filecontents )
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
@logger.debug "Wrote file: #{filename}"
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/lib/handler_base.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'protocol/base'
|
2
|
+
require 'ext/string'
|
3
|
+
|
4
|
+
module Handler class Base
|
5
|
+
|
6
|
+
#
|
7
|
+
# One handler exists in the daemon with
|
8
|
+
# the primary purpose of housing through
|
9
|
+
# an addressable Hash the set of connected
|
10
|
+
# clients,
|
11
|
+
#
|
12
|
+
# In this:
|
13
|
+
#
|
14
|
+
attr_writer :clients
|
15
|
+
|
16
|
+
|
17
|
+
def daemon_start
|
18
|
+
|
19
|
+
#
|
20
|
+
# OVERRIDE
|
21
|
+
#
|
22
|
+
# To prepare the Handler in any necessary
|
23
|
+
# ways before the thread is handed over to
|
24
|
+
# the socket listener, (or thing),
|
25
|
+
#
|
26
|
+
# The daemon has just started.
|
27
|
+
#
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def daemon_stop
|
32
|
+
|
33
|
+
#
|
34
|
+
# OVERRIDE
|
35
|
+
#
|
36
|
+
# To perfom any necessties before process
|
37
|
+
# termination,
|
38
|
+
#
|
39
|
+
# The daemon has received a signal to stop.
|
40
|
+
#
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def periodic
|
45
|
+
|
46
|
+
#
|
47
|
+
# TODO: There shall not only be one
|
48
|
+
#
|
49
|
+
# Changes are pending.
|
50
|
+
#
|
51
|
+
# OVERRIDE
|
52
|
+
#
|
53
|
+
# To perform activities at the interval
|
54
|
+
# defined in the config.
|
55
|
+
#
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize( config_hash, daemon_name, logger )
|
60
|
+
|
61
|
+
@config = config_hash
|
62
|
+
@my_config = @config['daemons'][daemon_name]['handler']
|
63
|
+
@daemon_name = daemon_name
|
64
|
+
@logger = logger
|
65
|
+
|
66
|
+
protocol = 'Base'
|
67
|
+
|
68
|
+
if @my_config.has_key? 'protocol' then
|
69
|
+
|
70
|
+
protocol = @my_config['protocol']
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# SIGNIFICANT DECISION
|
76
|
+
#
|
77
|
+
# - (currently) - There is one >>Instance<< of the protocol
|
78
|
+
#
|
79
|
+
# - It is an object ( has .new )
|
80
|
+
#
|
81
|
+
# - All attached socket traffic is directed through it for de/encode
|
82
|
+
# -
|
83
|
+
# - ?.. ie. multiple TcpClients all routing through the same object..?
|
84
|
+
# -
|
85
|
+
# - THIS MAY NEED TO CHANGE (thinks & thinks & thinks)
|
86
|
+
#
|
87
|
+
# - (Thinks) - It may move to the Client::Base so that each attached
|
88
|
+
# client is paired with its own instance of the protocol.
|
89
|
+
#
|
90
|
+
# - For now it wil be instanciated here and binded to each client at
|
91
|
+
# connect - to be shared for the decoding. That should be fine for
|
92
|
+
# as long as the protocol itself stores no state and is simply a
|
93
|
+
# code path (Still, thinks & ...
|
94
|
+
#
|
95
|
+
|
96
|
+
#
|
97
|
+
# initialize the protocol specified in config
|
98
|
+
#
|
99
|
+
# daemons:
|
100
|
+
#
|
101
|
+
# viking-invasion-early-warning-net_CoreHub_co_uk-D4RK1:
|
102
|
+
#
|
103
|
+
# adaptor:
|
104
|
+
# connection: TriFocalOcularRotisserie
|
105
|
+
# lightsource:
|
106
|
+
# type: Fire
|
107
|
+
# fuel: Peat
|
108
|
+
#
|
109
|
+
# handler:
|
110
|
+
# collection: ScottishCoastalVillages
|
111
|
+
# protocol: MedievalLanternMorse <----------
|
112
|
+
#
|
113
|
+
# Note: This is the application layer protocol
|
114
|
+
# and is therefore entirely agnostic of
|
115
|
+
# transport and disassociated from the
|
116
|
+
# adapter in use.
|
117
|
+
#
|
118
|
+
|
119
|
+
@logger.info "Initialize protocol: Protocol::#{protocol}.new( logger )"
|
120
|
+
eval "require 'protocol/#{protocol.underscore}'"
|
121
|
+
@protocol = Protocol.const_get(protocol).new( logger )
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end; end
|
data/lib/jobs/Rakefile
ADDED
File without changes
|
data/lib/jobs/jobs.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'jobs/updated_puppet_state'
|
data/libexec/daemon.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'ext/string'
|
2
|
+
require 'ext/config_loader'
|
3
|
+
|
4
|
+
CLASS_NAME = DAEMON_NAME.camelize
|
5
|
+
CONFIG_FILE = "#{DAEMON_ROOT}/config/daemons.yml"
|
6
|
+
CONFIG_HASH = ConfigLoader.yaml( CONFIG_FILE )
|
7
|
+
|
8
|
+
daemon = nil
|
9
|
+
|
10
|
+
DaemonKit::Application.running! do |config|
|
11
|
+
|
12
|
+
DaemonKit.logger.info "Spawing #{DAEMON_NAME} at pidfile #{config.pid_file}"
|
13
|
+
|
14
|
+
#
|
15
|
+
# setup signal traps
|
16
|
+
#
|
17
|
+
config.trap( 'TERM', Proc.new {
|
18
|
+
|
19
|
+
#
|
20
|
+
# Handle stop signal from os
|
21
|
+
#
|
22
|
+
daemon.stop_daemon
|
23
|
+
|
24
|
+
} )
|
25
|
+
|
26
|
+
config.trap( 'INT', Proc.new {
|
27
|
+
|
28
|
+
#
|
29
|
+
# Handle ^C from user (eg. developer) running un-daemonized
|
30
|
+
#
|
31
|
+
daemon.stop_daemon
|
32
|
+
|
33
|
+
} )
|
34
|
+
|
35
|
+
#
|
36
|
+
# Have not yet '''suitably''' succeeded in getting a sigHUP
|
37
|
+
# into a daemon with the monit/daemonkit combo yet....
|
38
|
+
#
|
39
|
+
# grumbles...
|
40
|
+
#
|
41
|
+
config.trap( 'HUP', Proc.new {
|
42
|
+
|
43
|
+
#
|
44
|
+
# Handle reload
|
45
|
+
#
|
46
|
+
daemon.reload_daemon
|
47
|
+
|
48
|
+
} )
|
49
|
+
|
50
|
+
#
|
51
|
+
# Latebind the daemon class
|
52
|
+
#
|
53
|
+
require "daemon/#{DAEMON_NAME}"
|
54
|
+
daemon = Object.const_get( CLASS_NAME ).new( CONFIG_HASH, DAEMON_NAME, DaemonKit.logger )
|
55
|
+
daemon.run
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'adaptor/base'
|
2
|
+
|
3
|
+
require 'ext/fake_logger'
|
4
|
+
|
5
|
+
describe Adaptor::Base do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
|
9
|
+
@logger = FakeLogger.new
|
10
|
+
|
11
|
+
@extendhandler = 'ExtendedHandler'
|
12
|
+
|
13
|
+
@config = {
|
14
|
+
|
15
|
+
'iface' => '111.111.111.111',
|
16
|
+
|
17
|
+
'port' => 11111,
|
18
|
+
|
19
|
+
'connector' => @extendhandler
|
20
|
+
|
21
|
+
}
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
pending 'may need to override default connection handler' do
|
26
|
+
|
27
|
+
Adaptor.const_set( @extendhandler, Class.new )
|
28
|
+
|
29
|
+
subject = Adaptor::Base.new( @config, @logger )
|
30
|
+
connector = subject.instance_variable_get( :@handler )
|
31
|
+
|
32
|
+
connector.should be_a( Adaptor.const_get( @extendhandler ) )
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'assigns defaults' do
|
37
|
+
|
38
|
+
subject = Adaptor::Base.new( {}, @logger )
|
39
|
+
connector = subject.instance_variable_get( :@connector )
|
40
|
+
|
41
|
+
connector.should == Adaptor::SocketHandler
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|