pyrad 2.4__py3-none-any.whl → 2.5.1__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.
- docs/Makefile +20 -0
- docs/make.bat +36 -0
- docs/source/_static/logo.png +0 -0
- docs/source/api/client.rst +10 -0
- docs/source/api/dictionary.rst +10 -0
- docs/source/api/host.rst +7 -0
- docs/source/api/packet.rst +48 -0
- docs/source/api/proxy.rst +7 -0
- docs/source/api/server.rst +13 -0
- docs/source/conf.py +158 -0
- docs/source/index.rst +75 -0
- example/acct.py +41 -0
- example/auth.py +37 -0
- example/auth_async.py +164 -0
- example/client-coa.py +61 -0
- example/coa.py +40 -0
- example/dictionary +405 -0
- example/dictionary.freeradius +91 -0
- example/pyrad.log +0 -0
- example/server.py +68 -0
- example/server_async.py +117 -0
- example/status.py +26 -0
- pyrad/__init__.py +3 -3
- pyrad/client.py +14 -6
- pyrad/client_async.py +16 -13
- pyrad/dictfile.py +2 -5
- pyrad/dictionary.py +6 -7
- pyrad/host.py +1 -1
- pyrad/packet.py +145 -114
- pyrad/proxy.py +2 -2
- pyrad/server.py +3 -7
- pyrad/server_async.py +3 -4
- pyrad/tests/__init__.py +5 -0
- pyrad/tests/mock.py +145 -0
- pyrad/tests/test_bidict.py +56 -0
- pyrad/tests/test_client.py +183 -0
- pyrad/tests/test_dictionary.py +357 -0
- pyrad/tests/test_host.py +87 -0
- pyrad/tests/test_packet.py +679 -0
- pyrad/tests/test_proxy.py +96 -0
- pyrad/tests/test_server.py +323 -0
- pyrad/tests/test_tools.py +126 -0
- pyrad/tools.py +254 -158
- {pyrad-2.4.dist-info → pyrad-2.5.1.dist-info}/METADATA +45 -22
- pyrad-2.5.1.dist-info/RECORD +51 -0
- {pyrad-2.4.dist-info → pyrad-2.5.1.dist-info}/WHEEL +1 -1
- {pyrad-2.4.dist-info → pyrad-2.5.1.dist-info/licenses}/LICENSE.txt +1 -1
- pyrad-2.5.1.dist-info/top_level.txt +3 -0
- pyrad-2.4.dist-info/RECORD +0 -19
- pyrad-2.4.dist-info/top_level.txt +0 -1
- {pyrad-2.4.dist-info → pyrad-2.5.1.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)
|