snmp 0.5.1 → 0.6.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.
@@ -2,13 +2,13 @@ require 'test/unit'
2
2
  require 'snmp/manager'
3
3
 
4
4
  class EchoTransport
5
- def initialize(host, port)
5
+ def initialize
6
6
  end
7
7
 
8
8
  def close
9
9
  end
10
10
 
11
- def send(data)
11
+ def send(data, host, port)
12
12
  @data = data
13
13
  end
14
14
 
@@ -111,9 +111,8 @@ class TestManager < Test::Unit::TestCase
111
111
  end
112
112
 
113
113
  def test_request_id
114
- srand(100)
115
114
  id = RequestId.new
116
- assert_equal(186422792, id.next)
115
+ fail if id.next < 0 or id.next >= 2**31
117
116
 
118
117
  id.force_next(1)
119
118
  assert_equal(1, id.next)
@@ -124,6 +123,52 @@ class TestManager < Test::Unit::TestCase
124
123
  assert_raise(RuntimeError) { id.force_next(RequestId::MAX_REQUEST_ID) }
125
124
  assert_raise(RuntimeError) { id.force_next(0) }
126
125
  end
126
+
127
+ def test_trap_v1
128
+ manager = Manager.new(:Transport => EchoTransport, :Version => :SNMPv1)
129
+ sent_data = manager.trap_v1(
130
+ "enterprises.9",
131
+ "10.1.2.3",
132
+ :enterpriseSpecific,
133
+ 42,
134
+ 12345,
135
+ [VarBind.new("1.3.6.1.2.3.4", Integer.new(1))]
136
+ )
137
+ pdu = Message.decode(sent_data).pdu
138
+ assert_equal(ObjectId.new("1.3.6.1.4.1.9"), pdu.enterprise)
139
+ assert_equal(IpAddress.new("10.1.2.3"), pdu.agent_addr)
140
+ assert_equal(:enterpriseSpecific, pdu.generic_trap)
141
+ assert_equal(42, pdu.specific_trap)
142
+ assert_equal(TimeTicks.new(12345), pdu.timestamp)
143
+ assert_equal(1, pdu.vb_list.length)
144
+ end
145
+
146
+ def test_trap_v2
147
+ sent_data = @manager.trap_v2(1234, "1.3.6.1.2.3.4")
148
+ pdu = Message.decode(sent_data).pdu
149
+ assert_equal(1234, pdu.sys_up_time)
150
+ assert_equal("1.3.6.1.2.3.4", pdu.trap_oid.to_s)
151
+ assert_equal(2, pdu.vb_list.length)
152
+
153
+ sent_data = @manager.trap_v2(1234, "1.3.6.1.2.3.4", ["1.2.3", "1.4.5.6"])
154
+ pdu = Message.decode(sent_data).pdu
155
+ assert_equal(1234, pdu.sys_up_time)
156
+ assert_equal("1.3.6.1.2.3.4", pdu.trap_oid.to_s)
157
+ assert_equal(4, pdu.vb_list.length)
158
+ assert_equal("1.4.5.6", pdu.vb_list.last.name.to_s)
159
+ end
160
+
161
+ def test_inform
162
+ response = @manager.inform(1234, "1.3.6.1.2.3.4")
163
+ assert_equal(1234, response.vb_list[0].value)
164
+ assert_equal("1.3.6.1.2.3.4", response.vb_list[1].value.to_s)
165
+ assert(2, response.vb_list.length)
166
+
167
+ response = @manager.inform(1234, "1.3.6.1.2.3.4", ["1.2.3", "1.4.5.6"])
168
+ assert_equal(1234, response.vb_list[0].value)
169
+ assert_equal("1.3.6.1.2.3.4", response.vb_list[1].value.to_s)
170
+ assert(4, response.vb_list.length)
171
+ end
127
172
  end
128
173
 
129
174
  class TrapTestTransport
@@ -0,0 +1,81 @@
1
+ require 'snmp/manager'
2
+
3
+ class TimeoutManager < SNMP::Manager
4
+ attr_accessor :response_count
5
+
6
+ def initialize(config)
7
+ super(config)
8
+ @response_count = 0
9
+ @raise_on_send = false
10
+ @raise_on_get = false
11
+ end
12
+
13
+ def raise_send_error
14
+ @raise_on_send = true
15
+ end
16
+
17
+ def raise_get_error
18
+ @raise_on_get = true
19
+ end
20
+
21
+ def send_request(request, community, host, port)
22
+ raise RuntimeError if @raise_on_send
23
+ end
24
+
25
+ def get_response(request)
26
+ @response_count += 1
27
+ raise RuntimeError if @raise_on_get
28
+ raise Timeout::Error, "testing retry count"
29
+ end
30
+ end
31
+
32
+ class MismatchIdTransport
33
+ def initialize
34
+ @data = []
35
+ end
36
+
37
+ def close
38
+ end
39
+
40
+ def send(data, host, port)
41
+ bad_id_data = data.dup
42
+ bad_msg = Message.decode(data)
43
+ bad_msg.pdu.request_id -= 3 # corrupt request_id
44
+ @data << bad_msg.encode # insert corrupted PDU before real data
45
+ @data << data
46
+ end
47
+
48
+ def recv(max_bytes)
49
+ raise "receive queue is empty" unless @data.first
50
+ SNMP::Message.decode(@data.shift).response.encode[0,max_bytes]
51
+ end
52
+ end
53
+
54
+
55
+ class TestRetry < Test::Unit::TestCase
56
+ def test_retry_count
57
+ assert_response_count(0, 1, SNMP::RequestTimeout)
58
+ assert_response_count(1, 2, SNMP::RequestTimeout)
59
+ assert_response_count(5, 6, SNMP::RequestTimeout)
60
+ end
61
+
62
+ def test_retry_on_error
63
+ assert_response_count(5, 0, RuntimeError) { |m| m.raise_send_error }
64
+ old_verbose = $VERBOSE
65
+ $VERBOSE = nil
66
+ assert_response_count(5, 6, SNMP::RequestTimeout) { |m| m.raise_get_error }
67
+ $VERBOSE = old_verbose
68
+ end
69
+
70
+ def assert_response_count(retry_count, response_count, exception)
71
+ m = TimeoutManager.new( :Retries => retry_count )
72
+ yield m if block_given?
73
+ assert_raise(exception) { m.get("1.2.3.4") }
74
+ assert_equal(response_count, m.response_count)
75
+ end
76
+
77
+ def test_drop_mismatched_id
78
+ m = SNMP::Manager.new(:Transport => MismatchIdTransport)
79
+ m.get("1.2.3.4")
80
+ end
81
+ end
@@ -22,6 +22,12 @@ class TestVarBind < Test::Unit::TestCase
22
22
  assert_equal("0\f\006\010+\006\001\002\001\001\002\000\005\000", remainder)
23
23
  end
24
24
 
25
+ def test_varbind_name_alias_oid
26
+ vb = VarBind.new("1.2.3.4", OctetString.new("blah"))
27
+ assert(ObjectId.new("1.2.3.4"), vb.name)
28
+ assert(ObjectId.new("1.2.3.4"), vb.oid)
29
+ end
30
+
25
31
  def test_varbind_list_create
26
32
  list = VarBindList.new
27
33
  assert_equal(0, list.length)
@@ -99,6 +105,11 @@ class TestVarBind < Test::Unit::TestCase
99
105
  assert_equal(s1, s3)
100
106
  end
101
107
 
108
+ def test_octet_string_to_oid
109
+ s = OctetString.new("test")
110
+ assert_equal(ObjectId.new([116, 101, 115, 116]), s.to_oid)
111
+ end
112
+
102
113
  def test_object_id
103
114
  id = ObjectId.new([1,3,6,1])
104
115
  assert_equal("1.3.6.1", id.to_s)
@@ -154,6 +165,17 @@ class TestVarBind < Test::Unit::TestCase
154
165
  assert(id1.subtree_of?("1.3.3.4"))
155
166
  assert(!id4.subtree_of?("1.3.3.4"))
156
167
  end
168
+
169
+ def test_object_id_index
170
+ id1 = ObjectId.new("1.3.3.4")
171
+ id2 = ObjectId.new("1.3.3.4.1")
172
+ id3 = ObjectId.new("1.3.3.4.1.2")
173
+ assert(ObjectId.new("1"), id2.index(id1))
174
+ assert(ObjectId.new("1.2"), id3.index(id1))
175
+ assert(ObjectId.new("1.2"), id3.index("1.3.3.4"))
176
+ assert_raise(ArgumentError) { id1.index(id3) }
177
+ assert_raise(ArgumentError) { id1.index(id1) }
178
+ end
157
179
 
158
180
  def test_object_name_from_string
159
181
  id = ObjectName.new("1.3.4.5.6")
@@ -196,6 +218,14 @@ class TestVarBind < Test::Unit::TestCase
196
218
  assert(i2 > 54000)
197
219
  end
198
220
 
221
+ def test_integer_to_oid
222
+ assert(ObjectId.new("123"), Integer.new(123).to_oid)
223
+ assert(ObjectId.new("0"), Integer.new(0).to_oid)
224
+
225
+ i = Integer.new(-1)
226
+ assert_raise(RangeError) { i.to_oid }
227
+ end
228
+
199
229
  def test_ip_address_from_string
200
230
  ip = IpAddress.new("10.0.255.1")
201
231
  assert_equal("10.0.255.1", ip.to_s)
@@ -203,6 +233,12 @@ class TestVarBind < Test::Unit::TestCase
203
233
  assert_raise(InvalidIpAddress) { IpAddress.new("1.2.3.-1") }
204
234
  assert_raise(InvalidIpAddress) { IpAddress.new("1.2.3") }
205
235
  end
236
+
237
+ def test_ip_address_from_self
238
+ ip1 = IpAddress.new("1.2.3.4")
239
+ ip2 = IpAddress.new(ip1)
240
+ assert_equal(ip1, ip2)
241
+ end
206
242
 
207
243
  def test_ip_address_create
208
244
  ip = IpAddress.new("\001\002\003\004")
@@ -230,6 +266,11 @@ class TestVarBind < Test::Unit::TestCase
230
266
  assert(!ip1.eql?(12))
231
267
  end
232
268
 
269
+ def test_ip_address_to_oid
270
+ ip = IpAddress.new("1.2.3.4")
271
+ assert_equal(ObjectId.new("1.2.3.4"), ip.to_oid)
272
+ end
273
+
233
274
  def test_counter32_create
234
275
  i = Counter32.new(12345)
235
276
  assert_equal("12345", i.to_s)
@@ -1,104 +1,191 @@
1
1
  require 'snmp'
2
2
  require 'test/unit'
3
+ require 'yaml'
3
4
 
4
5
  include SNMP
5
6
 
6
- class GetNextTransport
7
-
8
- attr_accessor :count
9
-
10
- def initialize(host, port)
7
+ ##
8
+ # Accept get and get-next requests, returning the data from the
9
+ # provided YAML data file. The file contains a list of OID, value, and
10
+ # value type.
11
+ #
12
+ class YamlDataTransport
13
+ def self.load_data(yaml_file)
14
+ values = YAML.load(File.new(yaml_file))
15
+ @@get_map = {}
16
+ @@get_next_map = {}
17
+ values.each_index do |i|
18
+ name, value, klass = values[i]
19
+ if i < values.length - 1
20
+ next_name, next_value, next_klass = values[i + 1]
21
+ else
22
+ next_value = SNMP::EndOfMibView
23
+ next_klass = SNMP::EndOfMibView
24
+ end
25
+ @@get_map[name] = [name, value, klass]
26
+ @@get_next_map[name] = [next_name, next_value, next_klass]
27
+ end
11
28
  end
12
-
13
- def close
29
+
30
+ def initialize
31
+ @responses = []
14
32
  end
15
33
 
16
- def send(data)
17
- @data = data
34
+ def close
18
35
  end
19
36
 
20
- def recv(max_bytes)
21
- response = Message.decode(@data).response
22
- if $transport_pdu_count > 0
23
- response.pdu.each_varbind do |vb|
24
- vb.name << 1
25
- end
26
- $transport_pdu_count -= 1
37
+ def send(data, host, port)
38
+ msg = Message.decode(data)
39
+ req_class = msg.pdu.class
40
+ if req_class == SNMP::GetRequest
41
+ oid_map = @@get_map
42
+ elsif req_class == SNMP::GetNextRequest
43
+ oid_map = @@get_next_map
27
44
  else
28
- response.pdu.each_varbind do |vb|
29
- vb.name = ObjectId.new("1.3.6.9999")
45
+ raise "request not supported: " + req_class
46
+ end
47
+
48
+ resp = msg.response
49
+ resp.pdu.vb_list.each do |vb|
50
+ name, value, klass = oid_map[vb.name.to_s]
51
+ vb.name = ObjectId.new(name)
52
+ if klass == "SNMP::NoSuchObject" or klass == "SNMP::NoSuchInstance"
53
+ vb.value = eval(klass)
54
+ elsif value
55
+ vb.value = eval("#{klass}.new(value)")
56
+ else
57
+ vb.value = SNMP::NoSuchInstance
30
58
  end
31
- end
32
- response.encode[0,max_bytes]
59
+ end
60
+ @responses << resp.encode
61
+ end
62
+
63
+ def recv(max_bytes)
64
+ @responses.shift
33
65
  end
34
66
  end
35
67
 
68
+ class TestTransport < Test::Unit::TestCase
69
+
70
+ def test_get
71
+ YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table6.yaml")
72
+ SNMP::Manager.open(:Transport => YamlDataTransport) do |snmp|
73
+ value = snmp.get_value("ifDescr.1")
74
+ assert_equal("lo0", value)
75
+ end
76
+ end
77
+
78
+ def test_get_next
79
+ YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table6.yaml")
80
+ SNMP::Manager.open(:Transport => YamlDataTransport) do |snmp|
81
+ vb = snmp.get_next("ifDescr.1")
82
+ assert_equal("gif0", vb.vb_list.first.value)
83
+ end
84
+ end
85
+
86
+ end
36
87
 
37
88
  class TestWalk < Test::Unit::TestCase
38
89
 
90
+ ##
91
+ # A single string or single ObjectId can be passed to walk()
92
+ #
39
93
  def test_single_object
40
- $transport_pdu_count = 3
41
94
  list = []
42
- manager.walk("ifTable") do |vb|
95
+ ifTable6_manager.walk("ifDescr") do |vb|
43
96
  assert(vb.kind_of?(VarBind), "Expected a VarBind")
44
97
  list << vb
45
98
  end
46
- assert_equal(3, list.length)
99
+ assert_equal(6, list.length)
47
100
 
48
- $transport_pdu_count = 3
49
101
  list = []
50
- manager.walk(ObjectId.new("1.3.4.5")) do |vb|
102
+ ifTable6_manager.walk(ObjectId.new("1.3.6.1.2.1.2.2.1.2")) do |vb|
51
103
  assert(vb.kind_of?(VarBind), "Expected a VarBind")
52
104
  list << vb
53
105
  end
54
- assert_equal(3, list.length)
106
+ assert_equal(6, list.length)
55
107
  end
56
-
108
+
109
+
110
+ ##
111
+ # If a list of one element is passed to walk() then a list of
112
+ # one element is passed as the block parameter.
113
+ #
57
114
  def test_single_object_list
58
- $transport_pdu_count = 1
59
115
  executed_block = false
60
- manager.walk(["1.3.6.1"]) do |vb_list|
116
+ ifTable6_manager.walk(["1.3.6.1.2.1.2.2.1.2"]) do |vb_list|
61
117
  executed_block = true
62
118
  assert_equal(1, vb_list.length)
63
- assert_equal("1.3.6.1.1", vb_list.first.name.to_s)
119
+ assert_equal("1.3.6.1.2.1.2.2.1.2.1", vb_list.first.name.to_s)
120
+ break
64
121
  end
65
122
  assert(executed_block, "Did not execute block")
66
123
  end
67
-
124
+
125
+ ##
126
+ # If a list of multiple items are passed to walk() then
127
+ # multiple items are passed to the block.
128
+ #
68
129
  def test_object_list
69
- $transport_pdu_count = 3
70
130
  list1 = []
71
131
  list2 = []
72
- manager.walk(["ifIndex", "ifDescr"]) do |vb1, vb2|
132
+ ifTable6_manager.walk(["ifIndex", "ifDescr"]) do |vb1, vb2|
73
133
  list1 << vb1
74
134
  list2 << vb2
75
135
  end
76
- assert_equal(3, list1.length)
77
- assert_equal(3, list2.length)
136
+ assert_equal(6, list1.length)
137
+ assert_equal(6, list2.length)
138
+
139
+ list1 = []
140
+ list2 = []
141
+ ifTable6_manager.walk(["ifIndex", "ifDescr"], 1) do |vb1, vb2|
142
+ list1 << vb1
143
+ list2 << vb2
144
+ end
145
+ assert_equal(6, list1.length)
146
+ assert_equal(6, list2.length)
78
147
  end
79
-
148
+
80
149
  def test_empty
81
- $transport_pdu_count = 0
82
- manager.walk("1.2.3.4") do |vb|
150
+ ifTable6_manager.walk("1.3.6.1.2.1.2.2.1.2.1") do |vb|
83
151
  fail("Expected block to not be executed")
84
152
  end
85
153
  end
86
-
154
+
87
155
  def test_one
88
- $transport_pdu_count = 1
89
156
  list = []
90
- manager.walk(["1.3.6.1", "1.3.6.2"]) do |vb|
91
- assert_equal("1.3.6.1.1", vb[0].name.to_s)
92
- assert_equal("1.3.6.2.1", vb[1].name.to_s)
157
+ ifTable1_manager.walk(["1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"]) do |vb|
158
+ assert_equal("1.3.6.1.2.1.2.2.1.1.1", vb[0].name.to_s)
159
+ assert_equal("1.3.6.1.2.1.2.2.1.2.1", vb[1].name.to_s)
160
+ list << vb
161
+ end
162
+ assert_equal(1, list.length)
163
+ end
164
+
165
+ def test_hole_in_one
166
+ list = []
167
+ ifTable1_manager.walk(["ifIndex", "ifDescr", "ifType"]) do |vb|
168
+ assert_equal("1.3.6.1.2.1.2.2.1.1.1", vb[0].name.to_s)
169
+ assert_equal(1, vb[0].value)
170
+ assert_equal("1.3.6.1.2.1.2.2.1.2.1", vb[1].name.to_s)
171
+ assert_equal("lo0", vb[1].value)
172
+ assert_equal("1.3.6.1.2.1.2.2.1.3.1", vb[2].name.to_s)
173
+ assert_equal(NoSuchInstance, vb[2].value)
93
174
  list << vb
175
+ break
94
176
  end
95
177
  assert_equal(1, list.length)
96
178
  end
97
179
 
98
180
  private
99
181
 
100
- def manager
101
- Manager.new(:Transport => GetNextTransport)
182
+ def ifTable1_manager
183
+ YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table1.yaml")
184
+ Manager.new(:Transport => YamlDataTransport)
185
+ end
186
+
187
+ def ifTable6_manager
188
+ YamlDataTransport.load_data(File.dirname(__FILE__) + "/if_table6.yaml")
189
+ Manager.new(:Transport => YamlDataTransport)
102
190
  end
103
-
104
191
  end