def test_walk_multiple_return_binds(self): """ A "WALK" response should only return one varbind. """ data = readbytes('get_sysoid_01_error.hex') with patch('puresnmp.api.raw.send') as mck: mck.return_value = data with six.assertRaisesRegex(self, SnmpError, 'varbind'): next(walk('::1', 'private', '1.2.3'))
def test_walk(self): response_1 = readbytes('walk_response_1.hex') response_2 = readbytes('walk_response_2.hex') response_3 = readbytes('walk_response_3.hex') expected = [ VarBind(ObjectIdentifier.from_string('1.3.6.1.2.1.2.2.1.5.1'), Gauge(10000000)), VarBind(ObjectIdentifier.from_string('1.3.6.1.2.1.2.2.1.5.13'), Gauge(4294967295)) ] with patch('puresnmp.api.raw.send') as mck: mck.side_effect = [response_1, response_2, response_3] result = list(walk('::1', 'public', '1.3.6.1.2.1.2.2.1.5')) self.assertEqual(result, expected)
def test_walk_endless_loop(self): ''' In rare cases, some devices fall into an endless loop by returning the requested OID on a "getnext" call during a "walk" operation. A SNMP client behaving according to the SNMP spec will fall into an endless loop. This test fakes such a case and revents the loop. ''' response_binds = [ VarBind(ObjectIdentifier(1, 2, 3), Integer(123)), VarBind(ObjectIdentifier(1, 2, 4), Integer(124)), VarBind(ObjectIdentifier(1, 2, 5), Integer(125)), VarBind(ObjectIdentifier(1, 2, 5), Integer(125)), # same OID VarBind(ObjectIdentifier(1, 2, 5), Integer(125)), # same OID VarBind(ObjectIdentifier(1, 2, 5), Integer(125)), # same OID ] response_packets = [ Sequence(Integer(1), OctetString(b'public'), GetResponse(234, [bind])) for bind in response_binds ] response_bytes = [to_bytes(packet) for packet in response_packets] handler = CapturingHandler() logger = getLogger('puresnmp') logger.addHandler(handler) with patch('puresnmp.api.raw.Transport') as mck: mck().send.side_effect = response_bytes mck().get_request_id.return_value = 0 result = list(walk('::1', 'private', '1.2', errors='warn')) logger.removeHandler(handler) # The last OID in the mocked responses is decreasing so we want to read # just up to that point. expected = [ VarBind(ObjectIdentifier(1, 2, 3), Integer(123)), VarBind(ObjectIdentifier(1, 2, 4), Integer(124)), VarBind(ObjectIdentifier(1, 2, 5), Integer(125)), ] self.assertEqual(result, expected) # We also want to make sure that we have a proper warning about this handler.assertContains(WARNING, r'.*1.2.5.*')
def test_walk_increasing_oid_lenient(self): ''' We want to be able to allow faulty SNMP implementations to at least try to fetch the values in a walk which are not increasing. It should read up to the values which are no longer increasing and emit a warning. ''' logger = getLogger('puresnmp') handler = CapturingHandler() logger.addHandler(handler) response_binds = [ VarBind(ObjectIdentifier(1, 2, 3), Integer(123)), VarBind(ObjectIdentifier(1, 2, 4), Integer(124)), VarBind(ObjectIdentifier(1, 2, 5), Integer(125)), VarBind(ObjectIdentifier(1, 2, 1), Integer(121)), # non-increasing ] response_packets = [ Sequence(Integer(1), OctetString(b'public'), GetResponse(234, [bind])) for bind in response_binds ] response_bytes = [to_bytes(packet) for packet in response_packets] with patch('puresnmp.api.raw.Transport') as mck: mck().send.side_effect = response_bytes mck().get_request_id.return_value = 0 result = list(walk('::1', 'private', '1.2', errors='warn')) # The last OID in the mocked responses is decreasing so we want to read # just up to that point. expected = [ VarBind(ObjectIdentifier(1, 2, 3), Integer(123)), VarBind(ObjectIdentifier(1, 2, 4), Integer(124)), VarBind(ObjectIdentifier(1, 2, 5), Integer(125)), ] self.assertEqual(result, expected) # We also want to make sure that we have a proper warning about this handler.assertContains(WARNING, r'.*1.2.1.*1.2.5.*') logger.removeHandler(handler)