pyrad 2.4__py3-none-any.whl → 2.5.0__py3-none-any.whl

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.
Files changed (51) hide show
  1. docs/Makefile +20 -0
  2. docs/make.bat +36 -0
  3. docs/source/_static/logo.png +0 -0
  4. docs/source/api/client.rst +10 -0
  5. docs/source/api/dictionary.rst +10 -0
  6. docs/source/api/host.rst +7 -0
  7. docs/source/api/packet.rst +48 -0
  8. docs/source/api/proxy.rst +7 -0
  9. docs/source/api/server.rst +13 -0
  10. docs/source/conf.py +158 -0
  11. docs/source/index.rst +75 -0
  12. example/acct.py +41 -0
  13. example/auth.py +37 -0
  14. example/auth_async.py +164 -0
  15. example/client-coa.py +61 -0
  16. example/coa.py +40 -0
  17. example/dictionary +405 -0
  18. example/dictionary.freeradius +91 -0
  19. example/pyrad.log +0 -0
  20. example/server.py +68 -0
  21. example/server_async.py +117 -0
  22. example/status.py +26 -0
  23. pyrad/__init__.py +3 -3
  24. pyrad/client.py +14 -6
  25. pyrad/client_async.py +16 -13
  26. pyrad/dictfile.py +2 -5
  27. pyrad/dictionary.py +6 -7
  28. pyrad/host.py +1 -1
  29. pyrad/packet.py +145 -114
  30. pyrad/proxy.py +2 -2
  31. pyrad/server.py +3 -7
  32. pyrad/server_async.py +3 -4
  33. pyrad/tests/__init__.py +5 -0
  34. pyrad/tests/mock.py +145 -0
  35. pyrad/tests/test_bidict.py +56 -0
  36. pyrad/tests/test_client.py +183 -0
  37. pyrad/tests/test_dictionary.py +357 -0
  38. pyrad/tests/test_host.py +87 -0
  39. pyrad/tests/test_packet.py +679 -0
  40. pyrad/tests/test_proxy.py +96 -0
  41. pyrad/tests/test_server.py +323 -0
  42. pyrad/tests/test_tools.py +126 -0
  43. pyrad/tools.py +254 -158
  44. {pyrad-2.4.dist-info → pyrad-2.5.0.dist-info}/METADATA +44 -20
  45. pyrad-2.5.0.dist-info/RECORD +51 -0
  46. {pyrad-2.4.dist-info → pyrad-2.5.0.dist-info}/WHEEL +1 -1
  47. {pyrad-2.4.dist-info → pyrad-2.5.0.dist-info/licenses}/LICENSE.txt +1 -1
  48. pyrad-2.5.0.dist-info/top_level.txt +3 -0
  49. pyrad-2.4.dist-info/RECORD +0 -19
  50. pyrad-2.4.dist-info/top_level.txt +0 -1
  51. {pyrad-2.4.dist-info → pyrad-2.5.0.dist-info}/zip-safe +0 -0
@@ -0,0 +1,96 @@
1
+ import select
2
+ import socket
3
+ import unittest
4
+ from .mock import MockFd
5
+ from .mock import MockPoll
6
+ from .mock import MockSocket
7
+ from .mock import MockClassMethod
8
+ from .mock import UnmockClassMethods
9
+ from pyrad.proxy import Proxy
10
+ from pyrad.packet import AccessAccept
11
+ from pyrad.packet import AccessRequest
12
+ from pyrad.server import ServerPacketError
13
+ from pyrad.server import Server
14
+
15
+
16
+ class TrivialObject:
17
+ """dummy object"""
18
+
19
+
20
+ class SocketTests(unittest.TestCase):
21
+ def setUp(self):
22
+ self.orgsocket = socket.socket
23
+ socket.socket = MockSocket
24
+ self.proxy = Proxy()
25
+ self.proxy._fdmap = {}
26
+
27
+ def tearDown(self):
28
+ socket.socket = self.orgsocket
29
+
30
+ def testProxyFd(self):
31
+ self.proxy._poll = MockPoll()
32
+ self.proxy._PrepareSockets()
33
+ self.assertTrue(isinstance(self.proxy._proxyfd, MockSocket))
34
+ self.assertEqual(list(self.proxy._fdmap.keys()), [1])
35
+ self.assertEqual(self.proxy._poll.registry,
36
+ {1: select.POLLIN | select.POLLPRI | select.POLLERR})
37
+
38
+
39
+ class ProxyPacketHandlingTests(unittest.TestCase):
40
+ def setUp(self):
41
+ self.proxy = Proxy()
42
+ self.proxy.hosts['host'] = TrivialObject()
43
+ self.proxy.hosts['host'].secret = 'supersecret'
44
+ self.packet = TrivialObject()
45
+ self.packet.code = AccessAccept
46
+ self.packet.source = ('host', 'port')
47
+
48
+ def testHandleProxyPacketUnknownHost(self):
49
+ self.packet.source = ('stranger', 'port')
50
+ try:
51
+ self.proxy._HandleProxyPacket(self.packet)
52
+ except ServerPacketError as e:
53
+ self.assertTrue('unknown host' in str(e))
54
+ else:
55
+ self.fail()
56
+
57
+ def testHandleProxyPacketSetsSecret(self):
58
+ self.proxy._HandleProxyPacket(self.packet)
59
+ self.assertEqual(self.packet.secret, 'supersecret')
60
+
61
+ def testHandleProxyPacketHandlesWrongPacket(self):
62
+ self.packet.code = AccessRequest
63
+ try:
64
+ self.proxy._HandleProxyPacket(self.packet)
65
+ except ServerPacketError as e:
66
+ self.assertTrue('non-response' in str(e))
67
+ else:
68
+ self.fail()
69
+
70
+
71
+ class OtherTests(unittest.TestCase):
72
+ def setUp(self):
73
+ self.proxy = Proxy()
74
+ self.proxy._proxyfd = MockFd()
75
+
76
+ def tearDown(self):
77
+ UnmockClassMethods(Proxy)
78
+ UnmockClassMethods(Server)
79
+
80
+ def testProcessInputNonProxyPort(self):
81
+ fd = MockFd(fd=111)
82
+ MockClassMethod(Server, '_ProcessInput')
83
+ self.proxy._ProcessInput(fd)
84
+ self.assertEqual(self.proxy.called,
85
+ [('_ProcessInput', (fd,), {})])
86
+
87
+ def testProcessInput(self):
88
+ MockClassMethod(Proxy, '_GrabPacket')
89
+ MockClassMethod(Proxy, '_HandleProxyPacket')
90
+ self.proxy._ProcessInput(self.proxy._proxyfd)
91
+ self.assertEqual([x[0] for x in self.proxy.called],
92
+ ['_GrabPacket', '_HandleProxyPacket'])
93
+
94
+
95
+ if not hasattr(select, 'poll'):
96
+ del SocketTests
@@ -0,0 +1,323 @@
1
+ import select
2
+ import socket
3
+ import unittest
4
+ from .mock import MockFinished
5
+ from .mock import MockFd
6
+ from .mock import MockPoll
7
+ from .mock import MockSocket
8
+ from .mock import MockClassMethod
9
+ from .mock import UnmockClassMethods
10
+ from pyrad.packet import PacketError
11
+ from pyrad.server import RemoteHost
12
+ from pyrad.server import Server
13
+ from pyrad.server import ServerPacketError
14
+ from pyrad.packet import AccessRequest
15
+ from pyrad.packet import AccountingRequest
16
+
17
+
18
+ class TrivialObject:
19
+ """dummy objec"""
20
+
21
+
22
+ class RemoteHostTests(unittest.TestCase):
23
+ def testSimpleConstruction(self):
24
+ host = RemoteHost('address', 'secret', 'name', 'authport', 'acctport', 'coaport')
25
+ self.assertEqual(host.address, 'address')
26
+ self.assertEqual(host.secret, 'secret')
27
+ self.assertEqual(host.name, 'name')
28
+ self.assertEqual(host.authport, 'authport')
29
+ self.assertEqual(host.acctport, 'acctport')
30
+ self.assertEqual(host.coaport, 'coaport')
31
+
32
+ def testNamedConstruction(self):
33
+ host = RemoteHost(address='address', secret='secret', name='name',
34
+ authport='authport', acctport='acctport', coaport='coaport')
35
+ self.assertEqual(host.address, 'address')
36
+ self.assertEqual(host.secret, 'secret')
37
+ self.assertEqual(host.name, 'name')
38
+ self.assertEqual(host.authport, 'authport')
39
+ self.assertEqual(host.acctport, 'acctport')
40
+ self.assertEqual(host.coaport, 'coaport')
41
+
42
+
43
+ class ServerConstructiontests(unittest.TestCase):
44
+ def testSimpleConstruction(self):
45
+ server = Server()
46
+ self.assertEqual(server.authfds, [])
47
+ self.assertEqual(server.acctfds, [])
48
+ self.assertEqual(server.authport, 1812)
49
+ self.assertEqual(server.acctport, 1813)
50
+ self.assertEqual(server.coaport, 3799)
51
+ self.assertEqual(server.hosts, {})
52
+
53
+ def testParameterOrder(self):
54
+ server = Server([], 'authport', 'acctport', 'coaport', 'hosts', 'dict')
55
+ self.assertEqual(server.authfds, [])
56
+ self.assertEqual(server.acctfds, [])
57
+ self.assertEqual(server.authport, 'authport')
58
+ self.assertEqual(server.acctport, 'acctport')
59
+ self.assertEqual(server.coaport, 'coaport')
60
+ self.assertEqual(server.dict, 'dict')
61
+
62
+ def testBindDuringConstruction(self):
63
+ def BindToAddress(self, addr):
64
+ self.bound.append(addr)
65
+ bta = Server.BindToAddress
66
+ Server.BindToAddress = BindToAddress
67
+
68
+ Server.bound = []
69
+ server = Server(['one', 'two', 'three'])
70
+ self.assertEqual(server.bound, ['one', 'two', 'three'])
71
+ del Server.bound
72
+
73
+ Server.BindToAddress = bta
74
+
75
+
76
+ class SocketTests(unittest.TestCase):
77
+ def setUp(self):
78
+ self.orgsocket = socket.socket
79
+ socket.socket = MockSocket
80
+ self.server = Server()
81
+
82
+ def tearDown(self):
83
+ socket.socket = self.orgsocket
84
+
85
+ def testBind(self):
86
+ self.server.BindToAddress('192.168.13.13')
87
+ self.assertEqual(len(self.server.authfds), 1)
88
+ self.assertEqual(self.server.authfds[0].address,
89
+ ('192.168.13.13', 1812))
90
+
91
+ self.assertEqual(len(self.server.acctfds), 1)
92
+ self.assertEqual(self.server.acctfds[0].address,
93
+ ('192.168.13.13', 1813))
94
+
95
+ def testBindv6(self):
96
+ self.server.BindToAddress('2001:db8:123::1')
97
+ self.assertEqual(len(self.server.authfds), 1)
98
+ self.assertEqual(self.server.authfds[0].address,
99
+ ('2001:db8:123::1', 1812))
100
+
101
+ self.assertEqual(len(self.server.acctfds), 1)
102
+ self.assertEqual(self.server.acctfds[0].address,
103
+ ('2001:db8:123::1', 1813))
104
+
105
+ def testGrabPacket(self):
106
+ def gen(data):
107
+ res = TrivialObject()
108
+ res.data = data
109
+ return res
110
+
111
+ fd = MockFd()
112
+ fd.source = object()
113
+ pkt = self.server._GrabPacket(gen, fd)
114
+ self.assertTrue(isinstance(pkt, TrivialObject))
115
+ self.assertTrue(pkt.fd is fd)
116
+ self.assertTrue(pkt.source is fd.source)
117
+ self.assertTrue(pkt.data is fd.data)
118
+
119
+ def testPrepareSocketNoFds(self):
120
+ self.server._poll = MockPoll()
121
+ self.server._PrepareSockets()
122
+
123
+ self.assertEqual(self.server._poll.registry, {})
124
+ self.assertEqual(self.server._realauthfds, [])
125
+ self.assertEqual(self.server._realacctfds, [])
126
+
127
+ def testPrepareSocketAuthFds(self):
128
+ self.server._poll = MockPoll()
129
+ self.server._fdmap = {}
130
+ self.server.authfds = [MockFd(12), MockFd(14)]
131
+ self.server._PrepareSockets()
132
+
133
+ self.assertEqual(list(self.server._fdmap.keys()), [12, 14])
134
+ self.assertEqual(self.server._poll.registry,
135
+ {12: select.POLLIN | select.POLLPRI | select.POLLERR,
136
+ 14: select.POLLIN | select.POLLPRI | select.POLLERR})
137
+
138
+ def testPrepareSocketAcctFds(self):
139
+ self.server._poll = MockPoll()
140
+ self.server._fdmap = {}
141
+ self.server.acctfds = [MockFd(12), MockFd(14)]
142
+ self.server._PrepareSockets()
143
+
144
+ self.assertEqual(list(self.server._fdmap.keys()), [12, 14])
145
+ self.assertEqual(self.server._poll.registry,
146
+ {12: select.POLLIN | select.POLLPRI | select.POLLERR,
147
+ 14: select.POLLIN | select.POLLPRI | select.POLLERR})
148
+
149
+
150
+ class AuthPacketHandlingTests(unittest.TestCase):
151
+ def setUp(self):
152
+ self.server = Server()
153
+ self.server.hosts['host'] = TrivialObject()
154
+ self.server.hosts['host'].secret = 'supersecret'
155
+ self.packet = TrivialObject()
156
+ self.packet.code = AccessRequest
157
+ self.packet.source = ('host', 'port')
158
+
159
+ def testHandleAuthPacketUnknownHost(self):
160
+ self.packet.source = ('stranger', 'port')
161
+ try:
162
+ self.server._HandleAuthPacket(self.packet)
163
+ except ServerPacketError as e:
164
+ self.assertTrue('unknown host' in str(e))
165
+ else:
166
+ self.fail()
167
+
168
+ def testHandleAuthPacketWrongPort(self):
169
+ self.packet.code = AccountingRequest
170
+ try:
171
+ self.server._HandleAuthPacket(self.packet)
172
+ except ServerPacketError as e:
173
+ self.assertTrue('port' in str(e))
174
+ else:
175
+ self.fail()
176
+
177
+ def testHandleAuthPacket(self):
178
+ def HandleAuthPacket(self, pkt):
179
+ self.handled = pkt
180
+ hap = Server.HandleAuthPacket
181
+ Server.HandleAuthPacket = HandleAuthPacket
182
+
183
+ self.server._HandleAuthPacket(self.packet)
184
+ self.assertTrue(self.server.handled is self.packet)
185
+
186
+ Server.HandleAuthPacket = hap
187
+
188
+
189
+ class AcctPacketHandlingTests(unittest.TestCase):
190
+ def setUp(self):
191
+ self.server = Server()
192
+ self.server.hosts['host'] = TrivialObject()
193
+ self.server.hosts['host'].secret = 'supersecret'
194
+ self.packet = TrivialObject()
195
+ self.packet.code = AccountingRequest
196
+ self.packet.source = ('host', 'port')
197
+
198
+ def testHandleAcctPacketUnknownHost(self):
199
+ self.packet.source = ('stranger', 'port')
200
+ try:
201
+ self.server._HandleAcctPacket(self.packet)
202
+ except ServerPacketError as e:
203
+ self.assertTrue('unknown host' in str(e))
204
+ else:
205
+ self.fail()
206
+
207
+ def testHandleAcctPacketWrongPort(self):
208
+ self.packet.code = AccessRequest
209
+ try:
210
+ self.server._HandleAcctPacket(self.packet)
211
+ except ServerPacketError as e:
212
+ self.assertTrue('port' in str(e))
213
+ else:
214
+ self.fail()
215
+
216
+ def testHandleAcctPacket(self):
217
+ def HandleAcctPacket(self, pkt):
218
+ self.handled = pkt
219
+ hap = Server.HandleAcctPacket
220
+ Server.HandleAcctPacket = HandleAcctPacket
221
+
222
+ self.server._HandleAcctPacket(self.packet)
223
+ self.assertTrue(self.server.handled is self.packet)
224
+
225
+ Server.HandleAcctPacket = hap
226
+
227
+
228
+ class OtherTests(unittest.TestCase):
229
+ def setUp(self):
230
+ self.server = Server()
231
+
232
+ def tearDown(self):
233
+ UnmockClassMethods(Server)
234
+
235
+ def testCreateReplyPacket(self):
236
+ class TrivialPacket:
237
+ source = object()
238
+
239
+ def CreateReply(self, **kw):
240
+ reply = TrivialObject()
241
+ reply.kw = kw
242
+ return reply
243
+
244
+ reply = self.server.CreateReplyPacket(TrivialPacket(),
245
+ one='one', two='two')
246
+ self.assertTrue(isinstance(reply, TrivialObject))
247
+ self.assertTrue(reply.source is TrivialPacket.source)
248
+ self.assertEqual(reply.kw, dict(one='one', two='two'))
249
+
250
+ def testAuthProcessInput(self):
251
+ fd = MockFd(1)
252
+ self.server._realauthfds = [1]
253
+ MockClassMethod(Server, '_GrabPacket')
254
+ MockClassMethod(Server, '_HandleAuthPacket')
255
+
256
+ self.server._ProcessInput(fd)
257
+ self.assertEqual([x[0] for x in self.server.called],
258
+ ['_GrabPacket', '_HandleAuthPacket'])
259
+ self.assertEqual(self.server.called[0][1][1], fd)
260
+
261
+ def testAcctProcessInput(self):
262
+ fd = MockFd(1)
263
+ self.server._realauthfds = []
264
+ self.server._realacctfds = [1]
265
+ MockClassMethod(Server, '_GrabPacket')
266
+ MockClassMethod(Server, '_HandleAcctPacket')
267
+
268
+ self.server._ProcessInput(fd)
269
+ self.assertEqual([x[0] for x in self.server.called],
270
+ ['_GrabPacket', '_HandleAcctPacket'])
271
+ self.assertEqual(self.server.called[0][1][1], fd)
272
+
273
+
274
+ class ServerRunTests(unittest.TestCase):
275
+ def setUp(self):
276
+ self.server = Server()
277
+ self.origpoll = select.poll
278
+ select.poll = MockPoll
279
+
280
+ def tearDown(self):
281
+ MockPoll.results = []
282
+ select.poll = self.origpoll
283
+ UnmockClassMethods(Server)
284
+
285
+ def testRunInitializes(self):
286
+ MockClassMethod(Server, '_PrepareSockets')
287
+ self.assertRaises(MockFinished, self.server.Run)
288
+ self.assertEqual(self.server.called, [('_PrepareSockets', (), {})])
289
+ self.assertTrue(isinstance(self.server._fdmap, dict))
290
+ self.assertTrue(isinstance(self.server._poll, MockPoll))
291
+
292
+ def testRunIgnoresPollErrors(self):
293
+ self.server.authfds = [MockFd()]
294
+ MockPoll.results = [(0, select.POLLERR)]
295
+ self.assertRaises(MockFinished, self.server.Run)
296
+
297
+ def testRunIgnoresServerPacketErrors(self):
298
+ def RaisePacketError(self, fd):
299
+ raise ServerPacketError
300
+ MockClassMethod(Server, '_ProcessInput', RaisePacketError)
301
+ self.server.authfds = [MockFd()]
302
+ MockPoll.results = [(0, select.POLLIN)]
303
+ self.assertRaises(MockFinished, self.server.Run)
304
+
305
+ def testRunIgnoresPacketErrors(self):
306
+ def RaisePacketError(self, fd):
307
+ raise PacketError
308
+ MockClassMethod(Server, '_ProcessInput', RaisePacketError)
309
+ self.server.authfds = [MockFd()]
310
+ MockPoll.results = [(0, select.POLLIN)]
311
+ self.assertRaises(MockFinished, self.server.Run)
312
+
313
+ def testRunRunsProcessInput(self):
314
+ MockClassMethod(Server, '_ProcessInput')
315
+ self.server.authfds = fd = [MockFd()]
316
+ MockPoll.results = [(0, select.POLLIN)]
317
+ self.assertRaises(MockFinished, self.server.Run)
318
+ self.assertEqual(self.server.called, [('_ProcessInput', (fd[0],), {})])
319
+
320
+
321
+ if not hasattr(select, 'poll'):
322
+ del SocketTests
323
+ del ServerRunTests
@@ -0,0 +1,126 @@
1
+ from pyrad import tools
2
+ import unittest
3
+
4
+
5
+ class EncodingTests(unittest.TestCase):
6
+ def testStringEncoding(self):
7
+ self.assertRaises(ValueError, tools.EncodeString, 'x' * 254)
8
+ self.assertEqual(
9
+ tools.EncodeString('1234567890'),
10
+ b'1234567890')
11
+
12
+ def testInvalidStringEncodingRaisesTypeError(self):
13
+ self.assertRaises(TypeError, tools.EncodeString, 1)
14
+
15
+ def testAddressEncoding(self):
16
+ self.assertRaises((ValueError, Exception), tools.EncodeAddress, 'TEST123')
17
+ self.assertEqual(
18
+ tools.EncodeAddress('192.168.0.255'),
19
+ b'\xc0\xa8\x00\xff')
20
+
21
+ def testInvalidAddressEncodingRaisesTypeError(self):
22
+ self.assertRaises(TypeError, tools.EncodeAddress, 1)
23
+
24
+ def testIntegerEncoding(self):
25
+ self.assertEqual(tools.EncodeInteger(0x01020304), b'\x01\x02\x03\x04')
26
+
27
+ def testInteger64Encoding(self):
28
+ self.assertEqual(
29
+ tools.EncodeInteger64(0xFFFFFFFFFFFFFFFF), b'\xff' * 8
30
+ )
31
+
32
+ def testUnsignedIntegerEncoding(self):
33
+ self.assertEqual(tools.EncodeInteger(0xFFFFFFFF), b'\xff\xff\xff\xff')
34
+
35
+ def testInvalidIntegerEncodingRaisesTypeError(self):
36
+ self.assertRaises(TypeError, tools.EncodeInteger, 'ONE')
37
+
38
+ def testDateEncoding(self):
39
+ self.assertEqual(tools.EncodeDate(0x01020304), b'\x01\x02\x03\x04')
40
+
41
+ def testInvalidDataEncodingRaisesTypeError(self):
42
+ self.assertRaises(TypeError, tools.EncodeDate, '1')
43
+
44
+ def testEncodeAscendBinary(self):
45
+ self.assertEqual(
46
+ tools.EncodeAscendBinary('family=ipv4 action=discard direction=in dst=10.10.255.254/32'),
47
+ b'\x01\x00\x01\x00\x00\x00\x00\x00\n\n\xff\xfe\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
48
+
49
+ def testStringDecoding(self):
50
+ self.assertEqual(
51
+ tools.DecodeString(b'1234567890'),
52
+ '1234567890')
53
+
54
+ def testAddressDecoding(self):
55
+ self.assertEqual(
56
+ tools.DecodeAddress(b'\xc0\xa8\x00\xff'),
57
+ '192.168.0.255')
58
+
59
+ def testIntegerDecoding(self):
60
+ self.assertEqual(
61
+ tools.DecodeInteger(b'\x01\x02\x03\x04'),
62
+ 0x01020304)
63
+
64
+ def testInteger64Decoding(self):
65
+ self.assertEqual(
66
+ tools.DecodeInteger64(b'\xff' * 8), 0xFFFFFFFFFFFFFFFF
67
+ )
68
+
69
+ def testDateDecoding(self):
70
+ self.assertEqual(
71
+ tools.DecodeDate(b'\x01\x02\x03\x04'),
72
+ 0x01020304)
73
+
74
+ def testOctetsEncoding(self):
75
+ self.assertEqual(tools.EncodeOctets('0x01020304'), b'\x01\x02\x03\x04')
76
+ self.assertEqual(tools.EncodeOctets(b'0x01020304'), b'\x01\x02\x03\x04')
77
+ self.assertEqual(tools.EncodeOctets('16909060'), b'\x01\x02\x03\x04')
78
+ # encodes to 253 bytes
79
+ self.assertEqual(tools.EncodeOctets('0x0102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D'), b'\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r')
80
+ self.assertRaisesRegex(ValueError, 'Can only encode strings of <= 253 characters', tools.EncodeOctets, '0x0102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E0F100102030405060708090A0B0C0D0E')
81
+
82
+ def testUnknownTypeEncoding(self):
83
+ self.assertRaises(ValueError, tools.EncodeAttr, 'unknown', None)
84
+
85
+ def testUnknownTypeDecoding(self):
86
+ self.assertRaises(ValueError, tools.DecodeAttr, 'unknown', None)
87
+
88
+ def testEncodeFunction(self):
89
+ self.assertEqual(
90
+ tools.EncodeAttr('string', 'string'),
91
+ b'string')
92
+ self.assertEqual(
93
+ tools.EncodeAttr('octets', b'string'),
94
+ b'string')
95
+ self.assertEqual(
96
+ tools.EncodeAttr('ipaddr', '192.168.0.255'),
97
+ b'\xc0\xa8\x00\xff')
98
+ self.assertEqual(
99
+ tools.EncodeAttr('integer', 0x01020304),
100
+ b'\x01\x02\x03\x04')
101
+ self.assertEqual(
102
+ tools.EncodeAttr('date', 0x01020304),
103
+ b'\x01\x02\x03\x04')
104
+ self.assertEqual(
105
+ tools.EncodeAttr('integer64', 0xFFFFFFFFFFFFFFFF),
106
+ b'\xff'*8)
107
+
108
+ def testDecodeFunction(self):
109
+ self.assertEqual(
110
+ tools.DecodeAttr('string', b'string'),
111
+ 'string')
112
+ self.assertEqual(
113
+ tools.EncodeAttr('octets', b'string'),
114
+ b'string')
115
+ self.assertEqual(
116
+ tools.DecodeAttr('ipaddr', b'\xc0\xa8\x00\xff'),
117
+ '192.168.0.255')
118
+ self.assertEqual(
119
+ tools.DecodeAttr('integer', b'\x01\x02\x03\x04'),
120
+ 0x01020304)
121
+ self.assertEqual(
122
+ tools.DecodeAttr('integer64', b'\xff'*8),
123
+ 0xFFFFFFFFFFFFFFFF)
124
+ self.assertEqual(
125
+ tools.DecodeAttr('date', b'\x01\x02\x03\x04'),
126
+ 0x01020304)