def test_get_call_args(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence(Integer(Version.V2C), OctetString('public'), GetNextRequest(0, ObjectIdentifier(1, 2, 3))) with patch('puresnmp.api.raw.send') as mck, \ patch('puresnmp.api.raw.get_request_id') as mck2: mck2.return_value = 0 mck.return_value = data getnext('::1', 'public', '1.2.3') mck.assert_called_with('::1', 161, to_bytes(packet), timeout=2)
def test_get_call_args_issue_22(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence(Integer(Version.V2C), OctetString('public'), BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3))) with patch('puresnmp.api.raw.Transport') as mck: mck().send.return_value = data mck().get_request_id.return_value = 0 with six.assertRaisesRegex(self, TypeError, 'OIDS.*list'): # we need to wrap this in a list to consume the generator. list(bulkwalk('::1', 'public', '1.2.3', bulk_size=2))
async def test_get_call_args(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence(Integer(Version.V2C), OctetString('public'), GetNextRequest(0, ObjectIdentifier(1, 2, 3))) with patch('puresnmp.aio.api.raw.Transport') as mck: mck().send = AsyncMock() mck().get_request_id.return_value = 0 mck().send.return_value = data await getnext('::1', 'public', '1.2.3') mck.assert_called_with(timeout=6) mck().send.assert_called_with('::1', 161, to_bytes(packet))
def test_get_call_args(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence(Integer(Version.V2C), OctetString('public'), BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3))) with patch('puresnmp.api.raw.send') as mck, \ patch('puresnmp.api.raw.get_request_id') as mck2: mck2.return_value = 0 mck.return_value = data # we need to wrap this in a list to consume the generator. list(bulkwalk('::1', 'public', ['1.2.3'], bulk_size=2)) mck.assert_called_with('::1', 161, to_bytes(packet), timeout=2)
def test_get_call_args(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence( Integer(Version.V2C), OctetString('public'), BulkGetRequest(0, 1, 2, ObjectIdentifier(1, 2, 3), ObjectIdentifier(1, 2, 4))) with patch('puresnmp.api.raw.Transport') as mck: mck().send.return_value = data mck().get_request_id.return_value = 0 bulkget('::1', 'public', ['1.2.3'], ['1.2.4'], max_list_size=2) mck.assert_called_with(timeout=6) mck().send.assert_called_with('::1', 161, to_bytes(packet))
def test_get_call_args(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence( Integer(Version.V2C), OctetString('public'), BulkGetRequest(0, 1, 2, ObjectIdentifier(1, 2, 3), ObjectIdentifier(1, 2, 4))) with patch('puresnmp.send') as mck, \ patch('puresnmp.get_request_id') as mck2: mck2.return_value = 0 mck.return_value = data bulkget('::1', 'public', ['1.2.3'], ['1.2.4'], max_list_size=2) mck.assert_called_with('::1', 161, bytes(packet))
def test_multiwalk_non_containment(self): ''' Running a multiwalk should raise an exception if the agent returns OIDs which are not properly increasing. ''' from puresnmp.pdu import GetResponse OID = ObjectIdentifier.from_string # First case: Returned OIDs are the same response = Sequence( Integer(1), OctetString(b'public'), GetResponse(123, [ VarBind(oid=OID('1.2.3'), value=Integer(30)), VarBind(oid=OID('2.3.4'), value=Integer(40)), ])) with patch('puresnmp.api.raw.Transport') as mck: mck().send.side_effect = [to_bytes(response)] mck().get_request_id.return_value = 0 with self.assertRaises(FaultySNMPImplementation): list(multiwalk('::1', 'public', [ '1.2.3', '2.3.4', ])) # Second case: Returned OIDs are smaller response = Sequence( Integer(1), OctetString(b'public'), GetResponse(123, [ VarBind(oid=OID('1.2.2'), value=Integer(30)), VarBind(oid=OID('2.3.3'), value=Integer(40)), ])) with patch('puresnmp.api.raw.Transport') as mck: mck().send.side_effect = [to_bytes(response)] mck().get_request_id.return_value = 0 with self.assertRaises(FaultySNMPImplementation): list(multiwalk('::1', 'public', [ '1.2.3', '2.3.4', ]))
async def test_get_call_args_issue_22(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence(Integer(Version.V2C), OctetString('public'), BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3))) with patch('puresnmp.aio.api.raw.send', new_callable=AsyncMock) as mck, \ patch('puresnmp.aio.api.raw.get_request_id') as mck2: mck2.return_value = 0 mck.return_value = data with pytest.raises(TypeError, match=r'OIDS.*list'): # we need to wrap this in a list to consume the generator. async for x in bulkwalk('::1', 'public', '1.2.3', bulk_size=2): pass
def test_get_call_args(self): """ Test the call arguments of "get" """ data = readbytes('dummy.hex') # any dump would do packet = Sequence(Integer(Version.V2C), OctetString('public'), GetRequest(0, ObjectIdentifier(1, 2, 3))) with patch('puresnmp.send') as mck, \ patch('puresnmp.get_request_id') as mck2: mck2.return_value = 0 mck.return_value = data get('::1', 'public', '1.2.3') mck.assert_called_with('::1', 161, bytes(packet))
async def test_get_call_args(self): data = readbytes('dummy.hex') # any dump would do packet = Sequence(Integer(Version.V2C), OctetString('public'), BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3))) with patch('puresnmp.aio.api.raw.Transport') as mck: mck().send = AsyncMock() mck().get_request_id.return_value = 0 mck().send.return_value = data # we need to wrap this in a list to consume the generator. async for x in bulkwalk('::1', 'public', ['1.2.3'], bulk_size=2): pass mck.assert_called_with(timeout=6) mck().send.assert_called_with('::1', 161, to_bytes(packet))
def test_getnext_increasing_oid_strict(self): ''' When running "getnext" we expect a different OID than the one we passed in. If not, this can cause endless-loops in the worst case. Faulty SNMP implementations may behave this way! ''' requested_oid = ObjectIdentifier(1, 2, 3, 4) response_object = Sequence( Integer(1), OctetString(b'public'), GetResponse(234, [VarBind(requested_oid, Integer(123))])) response_bytes = to_bytes(response_object) with patch('puresnmp.api.raw.send') as mck: mck.return_value = response_bytes with self.assertRaises(FaultySNMPImplementation): getnext('::1', 'private', '1.2.3.4')
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)