snmp4em 0.2.1 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,60 +1,32 @@
1
1
  module SNMP4EM
2
2
 
3
- # Returned from SNMP4EM::SNMPv1.getnext(). This implements EM::Deferrable, so you can hang a callback()
4
- # or errback() to retrieve the results.
3
+ # This implements EM::Deferrable, so you can hang a callback() or errback() to retrieve the results.
5
4
 
6
5
  class SnmpGetNextRequest < SnmpRequest
7
- attr_reader :snmp_id
6
+ attr_accessor :snmp_id
8
7
 
9
8
  # For an SNMP-GETNEXT request, @pending_oids will be a ruby array of SNMP::ObjectNames that need to be fetched. As
10
9
  # responses come back from the agent, this array will be pruned of any error-producing OIDs. Once no errors
11
10
  # are returned, the @responses hash will be populated and returned. The values of the hash will consist of a
12
11
  # two-element array, in the form of [OID, VALUE], showing the next oid & value.
13
-
14
- def initialize(sender, oids, args = {}) #:nodoc:
15
- @sender = sender
16
-
17
- @timeout_timer = nil
18
- @timeout_retries = @sender.retries
19
- @error_retries = oids.size
20
-
21
- @return_raw = args[:return_raw] || false
22
-
23
- @responses = Hash.new
24
- @pending_oids = SNMP::VarBindList.new(oids).collect{|r| r.name}
25
-
26
- init_callbacks
27
- send
28
- end
29
12
 
30
13
  def handle_response(response) #:nodoc:
31
- if (response.error_status == :noError)
14
+ if response.error_status == :noError
32
15
  # No errors, populate the @responses object so it can be returned
33
16
  response.each_varbind do |vb|
34
17
  request_oid = @pending_oids.shift
35
- @responses[request_oid.to_s] = [vb.name, vb.value]
18
+ value = @return_raw || !vb.value.respond_to?(:rubify) ? vb.value : vb.value.rubify
19
+ @responses[request_oid.to_s] = [vb.name.to_s, value]
36
20
  end
37
-
38
21
  else
39
22
  # Got an error, remove that oid from @pending_oids so we can try again
40
23
  error_oid = @pending_oids.delete_at(response.error_index - 1)
41
24
  @responses[error_oid.to_s] = SNMP::ResponseError.new(response.error_status)
42
25
  end
43
-
44
- if (@pending_oids.empty? || @error_retries.zero?)
45
- until @pending_oids.empty?
46
- error_oid = @pending_oids.shift
47
- @responses[error_oid.to_s] = SNMP::ResponseError.new(:genErr)
48
- end
49
26
 
50
- @responses.each_pair do |oid, value|
51
- if value.is_a? Array
52
- @responses[oid][1] = value[1].rubify if (!@return_raw && value[1].respond_to?(:rubify))
53
- else
54
- @responses[oid] = value.rubify if (!@return_raw && value.respond_to?(:rubify))
55
- end
56
- end
57
-
27
+ if @error_retries < 0
28
+ fail "exhausted all retries"
29
+ elsif @pending_oids.empty?
58
30
  # Send the @responses back to the requester, we're done!
59
31
  succeed @responses
60
32
  else
@@ -66,13 +38,13 @@ module SNMP4EM
66
38
  private
67
39
 
68
40
  def send #:nodoc:
69
- # Send the contents of @pending_oids
41
+ Manager.track_request(self)
70
42
 
71
- @snmp_id = generate_snmp_id
43
+ # Send the contents of @pending_oids
72
44
 
73
45
  vb_list = SNMP::VarBindList.new(@pending_oids)
74
46
  request = SNMP::GetNextRequest.new(@snmp_id, vb_list)
75
- message = SNMP::Message.new(:SNMPv1, @sender.community_ro, request)
47
+ message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
76
48
 
77
49
  super(message)
78
50
  end
@@ -4,7 +4,7 @@ module SNMP4EM
4
4
  # or errback() to retrieve the results.
5
5
 
6
6
  class SnmpSetRequest < SnmpRequest
7
- attr_reader :snmp_id
7
+ attr_accessor :snmp_id
8
8
 
9
9
  # For an SNMP-SET request, @pending_varbinds will by an SNMP::VarBindList, initially populated from the
10
10
  # provided oids hash. Variables can be passed as specific types from the SNMP library (i.e. SNMP::IpAddress)
@@ -13,22 +13,26 @@ module SNMP4EM
13
13
  # are produced, the @responses object is populated and returned.
14
14
 
15
15
  def initialize(sender, oids, args = {}) #:nodoc:
16
+ _oids = [*oids]
17
+
16
18
  @sender = sender
17
19
 
18
20
  @timeout_timer = nil
19
21
  @timeout_retries = @sender.retries
20
- @error_retries = oids.size
22
+ @error_retries = _oids.size
21
23
 
22
24
  @return_raw = args[:return_raw] || false
23
25
 
24
26
  @responses = Hash.new
25
27
  @pending_varbinds = SNMP::VarBindList.new()
26
28
 
27
- oids.each_pair do |oid,value|
29
+ _oids.each do |oid,value|
28
30
  if value.is_a? Integer
29
31
  snmp_value = SNMP::Integer.new(value)
30
32
  elsif value.is_a? String
31
33
  snmp_value = SNMP::OctetString.new(value)
34
+ else
35
+ snmp_value = value
32
36
  end
33
37
 
34
38
  @pending_varbinds << SNMP::VarBind.new(oid,snmp_value)
@@ -76,13 +80,13 @@ module SNMP4EM
76
80
  private
77
81
 
78
82
  def send
83
+ Manager.track_request(self)
84
+
79
85
  # Send the contents of @pending_varbinds
80
-
81
- @snmp_id = generate_snmp_id
82
86
 
83
87
  vb_list = SNMP::VarBindList.new(@pending_varbinds)
84
88
  request = SNMP::SetRequest.new(@snmp_id, vb_list)
85
- message = SNMP::Message.new(:SNMPv1, @sender.community_rw, request)
89
+ message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
86
90
 
87
91
  super(message)
88
92
  end
@@ -1,74 +1,47 @@
1
1
  module SNMP4EM
2
2
 
3
- # Returned from SNMP4EM::SNMPv1.walk(). This implements EM::Deferrable, so you can hang a callback()
4
- # or errback() to retrieve the results.
3
+ # This implements EM::Deferrable, so you can hang a callback() or errback() to retrieve the results.
5
4
 
6
5
  class SnmpWalkRequest < SnmpRequest
7
- attr_reader :snmp_id
6
+ attr_accessor :snmp_id
8
7
 
9
- # For an SNMP-WALK request, @pending_oids will be a ruby array of SNMP::ObjectNames that need to be walked.
10
- # Note that this library supports walking multiple OIDs in parallel. Once any error-producing OIDs are removed,
11
- # a series of SNMP-GETNEXT requests are sent. Each response OID is checked to see if it begins with the walk OID.
12
- # If so, the incoming OID/value pair is appended to the @response hash, and will be used in subsequent GETNEXT
13
- # requests. Once an OID is returned that does not begin with the walk OID, that walk OID is removed from the
14
- # @pending_oids array.
15
-
16
- def initialize(sender, oids, args = {}) #:nodoc:
17
- @sender = sender
18
-
19
- @timeout_timer = nil
20
- @timeout_retries = @sender.retries
21
- @error_retries = oids.size
22
-
23
- @return_raw = args[:return_raw] || false
24
- @max_results = args[:max_results] || nil
25
-
26
- @responses = Hash.new
27
- @pending_oids = SNMP::VarBindList.new(oids).collect{|r| r.name}
28
-
29
- init_callbacks
30
- send
31
- end
32
-
8
+ # SNMP-WALK is faked using GETNEXT queries until the returned OID isn't a subtree of the walk OID.
9
+ #
10
+ # @next_oids is a hash that maps the base walk OID to the next OID to be queried.
11
+ #
12
+ # @query_indexes simply tracks the order in which the next_oids were packaged up, in order to
13
+ # determine which query left the subtree
14
+ #
15
+ # Note that this library supports walking multiple base OIDs in parallel, and that the walk fails
16
+ # atomically with a list of OIDS that failed to gather.
17
+ #
33
18
  def handle_response(response) #:nodoc:
34
- oids_to_delete = []
19
+ if response.error_status == :noError
35
20
 
36
- if (response.error_status == :noError)
37
21
  response.varbind_list.each_index do |i|
38
- walk_oid = @pending_oids[i]
39
22
  response_vb = response.varbind_list[i]
40
-
41
- # Initialize the responses array if necessary
42
- @responses[walk_oid.to_s] ||= Array.new
43
-
44
- # If the incoming response-oid begins with the walk-oid, then append the pairing
45
- # to the @response array. Otherwise, add it to the list of oids ready to delete
46
- if (response_vb.name[0,walk_oid.length] == walk_oid)
47
- @responses[walk_oid.to_s] << [response_vb.name, response_vb.value]
23
+ response_oid = response_vb.name
24
+ response_walk_oid = response_oid.dup; response_walk_oid.pop
25
+
26
+ if response_walk_oid.subtree_of?(@query_indexes[i])
27
+ value = @return_raw || !response_vb.value.respond_to?(:rubify) ? response_vb.value : response_vb.value.rubify
28
+ @responses[response_walk_oid.to_s][response_oid.dup.pop] = value
29
+ @next_oids[response_walk_oid] = response_oid
48
30
  else
49
- # If we were to delete thid oid from @pending_oids now, it would mess up the
50
- # @pending_oids[i] call above.
51
- oids_to_delete << walk_oid
31
+ @next_oids.delete(@query_indexes[i])
52
32
  end
53
33
  end
54
34
 
55
35
  @max_results -= 1 unless @max_results.nil?
56
-
57
36
  else
58
- error_oid = @pending_oids[response.error_index - 1]
59
- oids_to_delete << error_oid
60
-
61
- @responses[error_oid.to_s] = SNMP::ResponseError.new(response.error_status)
37
+ @errors ||= []
38
+ error_oid = response.varbind_list[response.error_index].name
39
+ @errors << SNMP::ResponseError.new("Couldn't gather: #{error_oid} -> #{response.error_status}")
40
+ fail @errors if @error_retries < 1
62
41
  @error_retries -= 1
63
42
  end
64
-
65
- oids_to_delete.each{|oid| @pending_oids.delete oid}
66
-
67
- if (@pending_oids.empty? || (@error_retries < 0) || (@max_results.to_i < 0))
68
- @responses.each_pair do |oid, value|
69
- @responses[oid] = value.rubify if (!@return_raw && value.respond_to?(:rubify))
70
- end
71
-
43
+
44
+ if @next_oids.empty? || @max_results.to_i < 0
72
45
  # Send the @responses back to the requester, we're done!
73
46
  succeed @responses
74
47
  else
@@ -79,24 +52,35 @@ module SNMP4EM
79
52
  private
80
53
 
81
54
  def send
82
- @snmp_id = generate_snmp_id
55
+ Manager.track_request(self)
83
56
 
84
- # This oids array will consist of all the oids that need to be getnext'd
85
- oids = Array.new
86
-
87
- @pending_oids.each do |oid|
88
- # If there's already a response for this walk-oid, then use the last returned oid, otherwise
89
- # start with the walk-oid.
90
- if @responses.has_key?(oid.to_s)
91
- oids << @responses[oid.to_s].last.first
92
- else
93
- oids << oid
57
+ #
58
+ # @next_oids maps the walk oid to its next getnext oid
59
+ #
60
+ unless @next_oids
61
+ @responses = {}
62
+ @next_oids = {}
63
+ @pending_oids.each do |walk_oid|
64
+ @next_oids[walk_oid] = walk_oid
65
+ @responses[walk_oid.to_s] = {}
94
66
  end
95
67
  end
68
+
69
+ #
70
+ # @query_indexes maps the index of the requested oid to the walk oid
71
+ #
72
+ i = 0
73
+ @query_indexes = {}
74
+ query_oids = \
75
+ @next_oids.collect do |walk_oid, next_oid|
76
+ @query_indexes[i] = walk_oid
77
+ i += 1
78
+ next_oid
79
+ end
96
80
 
97
- vb_list = SNMP::VarBindList.new(oids)
81
+ vb_list = SNMP::VarBindList.new(query_oids)
98
82
  request = SNMP::GetNextRequest.new(@snmp_id, vb_list)
99
- message = SNMP::Message.new(:SNMPv1, @sender.community_ro, request)
83
+ message = SNMP::Message.new(@sender.version, @sender.community_ro, request)
100
84
 
101
85
  super(message)
102
86
  end
@@ -1,24 +1,35 @@
1
1
  module SNMP4EM
2
2
  class SnmpRequest #:nodoc:
3
3
  include EM::Deferrable
4
-
5
- def generate_snmp_id
6
- begin
7
- snmp_id = rand(1073741823) # Largest Fixnum
8
- end until (SnmpConnection.pending_requests.select{|r| r.snmp_id == snmp_id}.empty?)
9
4
 
10
- return snmp_id
11
- end
5
+ attr_accessor :timeout_timer
6
+
7
+ def initialize(sender, oids, args = {}) #:nodoc:
8
+ _oids = [*oids]
9
+
10
+ @sender = sender
11
+
12
+ @timeout_timer = nil
13
+ @timeout_retries = @sender.retries
14
+ @error_retries = _oids.size
15
+
16
+ @return_raw = args[:return_raw] || false
17
+
18
+ @responses = {}
19
+ @pending_oids = _oids.collect { |oid_str| SNMP::ObjectId.new(oid_str) }
12
20
 
21
+ init_callbacks
22
+ send
23
+ end
24
+
13
25
  def init_callbacks
14
26
  self.callback do
15
- SnmpConnection.pending_requests.delete_if {|r| r.snmp_id == @snmp_id}
16
- @timeout_timer.cancel
27
+ Manager.pending_requests.delete(@snmp_id)
17
28
  end
18
29
 
19
30
  self.errback do
20
- SnmpConnection.pending_requests.delete_if {|r| r.snmp_id == @snmp_id}
21
31
  @timeout_timer.cancel
32
+ Manager.pending_requests.delete(@snmp_id)
22
33
  end
23
34
  end
24
35
 
@@ -28,13 +39,13 @@ module SNMP4EM
28
39
  @timeout_timer.cancel if @timeout_timer.is_a?(EM::Timer)
29
40
 
30
41
  @timeout_timer = EM::Timer.new(@sender.timeout) do
31
- if (@timeout_retries > 0)
42
+ if @timeout_retries > 0
32
43
  send
33
44
  @timeout_retries -= 1
34
45
  else
35
- fail("timeout")
46
+ fail "exhausted all timeout retries"
36
47
  end
37
48
  end
38
49
  end
39
50
  end
40
- end
51
+ end
@@ -0,0 +1,25 @@
1
+ # The SNMP4EM library
2
+
3
+ module SNMP4EM
4
+ module SNMPv2cRequests
5
+ # Sends an SNMPv2 GET-BULK request to fetch multiple OID-value pairings simultaneously. This produces similar results to an SNMP-WALK using a single
6
+ # request/response transaction (SNMP-WALK is actually an inefficient series of GET-NEXTs). Multiple OIDs can be passed into the _oids_ array. Two
7
+ # additional parameters control how this list is processed. Setting the parameter _nonrepeaters_ to value _N_ indicates that the first _N_ OIDs will
8
+ # fetch a single value. This is identical to running a single GET-NEXT for the OID. Any remaining OIDs will fetch multiple values. The number of values
9
+ # fetched is controlled by the parameter _maxrepetitions_. The function returns a SnmpGetBulkRequest object, which implements EM::Deferrable. From there,
10
+ # implement a callback/errback to fetch the result. On success, the result will be a hash, mapping requested OID prefixes to the returned value.
11
+ # Successful fetches will be mapped to an array of two-element arrays, each of which consists of [_oid_ , _value_]. Unsuccessful fetches will be mapped to a
12
+ # symbol representing the error.
13
+
14
+ # For more information, see http://tools.ietf.org/html/rfc1905#section-4.2.3
15
+
16
+ # Optional arguments can be passed into _args_, including:
17
+ # * _return_raw_ - Return objects and errors as their raw SNMP types, such as SNMP::Integer instead of native Ruby integers, SNMP::OctetString instead of native Ruby strings, etc. (default: false)
18
+ # * _nonrepeaters_ - Number of OIDs passed to which exactly one result will be returned (default is 0)
19
+ # * _maxrepetitions_ - Number of OID-value pairs to be returned for each OID (default is 10)
20
+
21
+ def getbulk(oids, args = {})
22
+ SnmpGetBulkRequest.new(self, oids, args.merge(:version => @version))
23
+ end
24
+ end
25
+ end
data/lib/snmp4em.rb CHANGED
@@ -1,15 +1,19 @@
1
- $:.unshift File.expand_path(File.dirname(File.expand_path(__FILE__)))
1
+ $:.unshift File.dirname(File.expand_path(__FILE__))
2
+
3
+ gem "eventmachine", ">= 0.12.10"
4
+ gem "snmp", ">= 1.0.2"
2
5
 
3
6
  require 'eventmachine'
4
7
  require 'snmp'
5
- require 'snmp4em/common'
8
+
9
+ require 'snmp4em/extensions'
6
10
  require 'snmp4em/handler'
7
- require 'snmp4em/snmp_connection'
8
- require 'snmp4em/snmp_v1'
9
- require 'snmp4em/snmp_v2'
11
+ require 'snmp4em/common_requests'
12
+ require 'snmp4em/manager'
13
+ require 'snmp4em/snmp_v2c_requests'
10
14
  require 'snmp4em/snmp_request'
11
15
  require 'snmp4em/requests/snmp_get_request'
12
16
  require 'snmp4em/requests/snmp_getbulk_request'
13
17
  require 'snmp4em/requests/snmp_getnext_request'
14
18
  require 'snmp4em/requests/snmp_set_request'
15
- require 'snmp4em/requests/snmp_walk_request'
19
+ require 'snmp4em/requests/snmp_walk_request'
data/snmp4em.gemspec CHANGED
@@ -1,30 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = %q{snmp4em}
5
- s.version = "0.2.1"
4
+ s.name = "snmp4em"
5
+ s.version = "0.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Norman Elton"]
9
- s.date = %q{2010-05-17}
10
- s.description = %q{A high-performance SNMP engine built on EventMachine and Ruby-SNMP, supporting SNMPv1 and SNMPv2 operations}
11
- s.email = %q{normelton@gmail.com}
12
- s.extra_rdoc_files = ["README"]
13
- s.files = ["lib/snmp4em.rb", "lib/snmp4em/common.rb", "lib/snmp4em/handler.rb", "lib/snmp4em/requests/snmp_get_request.rb", "lib/snmp4em/requests/snmp_getbulk_request.rb", "lib/snmp4em/requests/snmp_getnext_request.rb", "lib/snmp4em/requests/snmp_set_request.rb", "lib/snmp4em/requests/snmp_walk_request.rb", "lib/snmp4em/snmp_request.rb", "lib/snmp4em/snmp_connection.rb", "lib/snmp4em/snmp_v1.rb", "lib/snmp4em/snmp_v2.rb", "snmp4em.gemspec", "Manifest"]
14
- s.homepage = %q{http://github.com/normelton/snmp4em}
15
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Snmp4em", "--main", "README"]
9
+ s.date = "2012-02-23"
10
+ s.description = "A high-performance SNMP engine built on EventMachine and Ruby-SNMP"
11
+ s.email = "normelton@gmail.com"
12
+ s.extra_rdoc_files = ["README.rdoc"]
13
+ s.files = ["Gemfile", "README.rdoc", "Rakefile", "lib/snmp4em.rb", "lib/snmp4em/common_requests.rb", "lib/snmp4em/extensions.rb", "lib/snmp4em/extensions/snmp/integer.rb", "lib/snmp4em/extensions/snmp/ip_address.rb", "lib/snmp4em/extensions/snmp/null.rb", "lib/snmp4em/extensions/snmp/object_id.rb", "lib/snmp4em/extensions/snmp/octet_string.rb", "lib/snmp4em/extensions/snmp/response_error.rb", "lib/snmp4em/handler.rb", "lib/snmp4em/manager.rb", "lib/snmp4em/requests/snmp_get_request.rb", "lib/snmp4em/requests/snmp_getbulk_request.rb", "lib/snmp4em/requests/snmp_getnext_request.rb", "lib/snmp4em/requests/snmp_set_request.rb", "lib/snmp4em/requests/snmp_walk_request.rb", "lib/snmp4em/snmp_request.rb", "lib/snmp4em/snmp_v2c_requests.rb", "snmp4em.gemspec", "spec/models/test_message.rb", "spec/models/test_request.rb", "spec/models/test_response.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/handler_spec.rb", "spec/unit/manager_spec.rb", "Manifest"]
14
+ s.homepage = "http://github.com/normelton/snmp4em"
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Snmp4em", "--main", "README.rdoc"]
16
16
  s.require_paths = ["lib"]
17
- s.rubyforge_project = %q{snmp4em}
18
- s.rubygems_version = %q{1.3.6}
19
- s.summary = %q{A high-performance SNMP engine built on EventMachine and Ruby-SNMP}
20
-
21
- if s.respond_to? :specification_version then
22
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
- s.specification_version = 3
24
-
25
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
- else
27
- end
28
- else
29
- end
17
+ s.rubyforge_project = "snmp4em"
18
+ s.rubygems_version = "1.8.16"
19
+ s.summary = "A high-performance SNMP engine built on EventMachine and Ruby-SNMP"
20
+ s.add_runtime_dependency 'snmp', '>= 1.0.2'
21
+ s.add_runtime_dependency 'eventmachine', '>= 1.0.0'
22
+
30
23
  end
@@ -0,0 +1,7 @@
1
+ module SNMP4EM
2
+ class TestMessage
3
+
4
+ attr_accessor :pdu
5
+
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module SNMP4EM
2
+ class TestRequest
3
+
4
+ attr_accessor :snmp_id
5
+
6
+ def handle_response(response)
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module SNMP4EM
2
+ class TestResponse
3
+
4
+ attr_accessor :request_id
5
+
6
+ end
7
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format nested
3
+ --drb
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+
4
+ MODELS = File.join(File.dirname(__FILE__), "models")
5
+ $LOAD_PATH.unshift(MODELS)
6
+ Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
7
+
8
+ require 'rubygems'
9
+ require "spec"
10
+ require "snmp4em"
11
+
12
+ def em
13
+ EM.run {
14
+ yield
15
+ EM.stop
16
+ }
17
+ end
18
+
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe SNMP4EM::Handler do
4
+
5
+ before do
6
+ SNMP4EM::Manager.class_eval do
7
+ @pending_requests = {}
8
+ end
9
+ end
10
+
11
+ describe "#receive_data" do
12
+
13
+ it "should match responses to requests" do
14
+ em do
15
+ response = SNMP4EM::TestResponse.new
16
+ response.request_id = 1
17
+
18
+ message = SNMP4EM::TestMessage.new
19
+ message.pdu = response
20
+ SNMP::Message.should_receive(:decode).and_return(message)
21
+
22
+ request = SNMP4EM::TestRequest.new
23
+ SNMP4EM::Manager.should_receive(:rand).and_return(1)
24
+ SNMP4EM::Manager.track_request(request)
25
+
26
+ request.should_receive(:handle_response).with(response)
27
+ SNMP4EM::Handler.new(nil).receive_data(nil)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe SNMP4EM::Manager do
4
+
5
+ before do
6
+ SNMP4EM::Manager.class_eval do
7
+ @pending_requests = {}
8
+ end
9
+ end
10
+
11
+ describe "#track_request" do
12
+
13
+ it "should assign a random and unique id to each request" do
14
+ em do
15
+ request = SNMP4EM::TestRequest.new
16
+ other_request = SNMP4EM::TestRequest.new
17
+
18
+ SNMP4EM::Manager.should_receive(:rand).and_return(1, 1, 2)
19
+ SNMP4EM::Manager.track_request(request)
20
+ SNMP4EM::Manager.track_request(other_request)
21
+
22
+ request.snmp_id.should == 1
23
+ other_request.snmp_id.should == 2
24
+ end
25
+ end
26
+
27
+ it "should prune requests when their request id changes" do
28
+ em do
29
+ request = SNMP4EM::TestRequest.new
30
+
31
+ SNMP4EM::Manager.should_receive(:rand).and_return(1, 2)
32
+ SNMP4EM::Manager.track_request(request)
33
+ request.snmp_id.should == 1
34
+ SNMP4EM::Manager.pending_requests.size.should == 1
35
+
36
+ SNMP4EM::Manager.track_request(request)
37
+ request.snmp_id.should == 2
38
+ SNMP4EM::Manager.pending_requests.size.should == 1
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ describe "#initialize" do
45
+
46
+ it "should default to v2c" do
47
+ em do
48
+ SNMP4EM::Manager.new.version.should == :SNMPv2c
49
+ end
50
+ end
51
+
52
+ it "should create the class' UDP socket" do
53
+ em do
54
+ SNMP4EM::Manager.new
55
+ SNMP4EM::Manager.socket.should be_a EventMachine::Connection
56
+ end
57
+ end
58
+
59
+
60
+ context "when using v2c" do
61
+
62
+ it "should acquire the #getbulk method" do
63
+ em do
64
+ SNMP4EM::Manager.new.methods.should include :getbulk
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ context "when using v1" do
71
+
72
+ it "should not acquire the #getbulk method" do
73
+ em do
74
+ SNMP4EM::Manager.new(:version => :SNMPv1).methods.should_not include :getbulk
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end