snmp 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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