Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: third_party/twisted_8_1/twisted/test/test_strcred.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2007-2008 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for L{strcred}.
6 """
7
8 import os
9 import StringIO
10
11 from twisted import plugin
12 from twisted.trial import unittest
13 from twisted.cred import credentials, checkers, error, strcred
14 from twisted.plugins import cred_file, cred_anonymous
15 from twisted.python import usage
16
17
18 try:
19 import crypt
20 except ImportError:
21 crypt = None
22
23 try:
24 import pwd
25 except ImportError:
26 pwd = None
27
28 try:
29 import spwd
30 except ImportError:
31 spwd = None
32
33
34
35 def getInvalidAuthType():
36 """
37 Helper method to produce an auth type that doesn't exist.
38 """
39 invalidAuthType = 'ThisPluginDoesNotExist'
40 while (invalidAuthType in
41 [factory.authType for factory in strcred.findCheckerFactories()]):
42 invalidAuthType += '_'
43 return invalidAuthType
44
45
46
47 class TestPublicAPI(unittest.TestCase):
48
49 def test_emptyDescription(self):
50 """
51 Test that the description string cannot be empty.
52 """
53 iat = getInvalidAuthType()
54 self.assertRaises(strcred.InvalidAuthType, strcred.makeChecker, iat)
55 self.assertRaises(strcred.InvalidAuthType, strcred.findCheckerFactory, i at)
56
57
58 def test_invalidAuthType(self):
59 """
60 Test that an unrecognized auth type raises an exception.
61 """
62 iat = getInvalidAuthType()
63 self.assertRaises(strcred.InvalidAuthType, strcred.makeChecker, iat)
64 self.assertRaises(strcred.InvalidAuthType, strcred.findCheckerFactory, i at)
65
66
67
68 class TestStrcredFunctions(unittest.TestCase):
69
70 def test_findCheckerFactories(self):
71 """
72 Test that findCheckerFactories returns all available plugins.
73 """
74 availablePlugins = list(strcred.findCheckerFactories())
75 for plg in plugin.getPlugins(strcred.ICheckerFactory):
76 self.assertIn(plg, availablePlugins)
77
78
79 def test_findCheckerFactory(self):
80 """
81 Test that findCheckerFactory returns the first plugin
82 available for a given authentication type.
83 """
84 self.assertIdentical(strcred.findCheckerFactory('file'),
85 cred_file.theFileCheckerFactory)
86
87
88
89 class TestMemoryChecker(unittest.TestCase):
90
91 def setUp(self):
92 self.admin = credentials.UsernamePassword('admin', 'asdf')
93 self.alice = credentials.UsernamePassword('alice', 'foo')
94 self.badPass = credentials.UsernamePassword('alice', 'foobar')
95 self.badUser = credentials.UsernamePassword('x', 'yz')
96 self.checker = strcred.makeChecker('memory:admin:asdf:alice:foo')
97
98
99 def test_isChecker(self):
100 """
101 Verifies that strcred.makeChecker('memory') returns an object
102 that implements the L{ICredentialsChecker} interface.
103 """
104 self.assertTrue(checkers.ICredentialsChecker.providedBy(self.checker))
105 self.assertIn(credentials.IUsernamePassword,
106 self.checker.credentialInterfaces)
107
108
109 def test_badFormatArgString(self):
110 """
111 Test that an argument string which does not contain user:pass
112 pairs (i.e., an odd number of ':' characters) raises an exception.
113 """
114 self.assertRaises(strcred.InvalidAuthArgumentString,
115 strcred.makeChecker, 'memory:a:b:c')
116
117
118 def test_memoryCheckerSucceeds(self):
119 """
120 Test that the checker works with valid credentials.
121 """
122 def _gotAvatar(username):
123 self.assertEquals(username, self.admin.username)
124 return (self.checker
125 .requestAvatarId(self.admin)
126 .addCallback(_gotAvatar))
127
128
129 def test_memoryCheckerFailsUsername(self):
130 """
131 Test that the checker fails with an invalid username.
132 """
133 return self.assertFailure(self.checker.requestAvatarId(self.badUser),
134 error.UnauthorizedLogin)
135
136
137 def test_memoryCheckerFailsPassword(self):
138 """
139 Test that the checker fails with an invalid password.
140 """
141 return self.assertFailure(self.checker.requestAvatarId(self.badPass),
142 error.UnauthorizedLogin)
143
144
145
146 class TestAnonymousChecker(unittest.TestCase):
147
148 def test_isChecker(self):
149 """
150 Verifies that strcred.makeChecker('anonymous') returns an object
151 that implements the L{ICredentialsChecker} interface.
152 """
153 checker = strcred.makeChecker('anonymous')
154 self.assertTrue(checkers.ICredentialsChecker.providedBy(checker))
155 self.assertIn(credentials.IAnonymous, checker.credentialInterfaces)
156
157
158 def testAnonymousAccessSucceeds(self):
159 """
160 Test that we can log in anonymously using this checker.
161 """
162 checker = strcred.makeChecker('anonymous')
163 request = checker.requestAvatarId(credentials.Anonymous())
164 def _gotAvatar(avatar):
165 self.assertIdentical(checkers.ANONYMOUS, avatar)
166 return request.addCallback(_gotAvatar)
167
168
169
170 class TestUnixChecker(unittest.TestCase):
171 users = {
172 'admin': 'asdf',
173 'alice': 'foo',
174 }
175
176
177 def _pwd(self, username):
178 return (username, crypt.crypt(self.users[username], 'F/'),
179 1000, 1000, username, '/home/'+username, '/bin/sh')
180
181
182 def _spwd(self, username):
183 return (username, crypt.crypt(self.users[username], 'F/'),
184 0, 0, 99999, 7, -1, -1, -1)
185
186
187 def setUp(self):
188 self.admin = credentials.UsernamePassword('admin', 'asdf')
189 self.alice = credentials.UsernamePassword('alice', 'foo')
190 self.badPass = credentials.UsernamePassword('alice', 'foobar')
191 self.badUser = credentials.UsernamePassword('x', 'yz')
192 self.checker = strcred.makeChecker('unix')
193 # Hack around the pwd and spwd modules, since we can't really
194 # go about reading your /etc/passwd or /etc/shadow files
195 if pwd:
196 self._pwd_getpwnam = pwd.getpwnam
197 pwd.getpwnam = self._pwd
198 if spwd:
199 self._spwd_getspnam = spwd.getspnam
200 spwd.getspnam = self._spwd
201
202
203 def tearDown(self):
204 if pwd:
205 pwd.getpwnam = self._pwd_getpwnam
206 if spwd:
207 spwd.getspnam = self._spwd_getspnam
208
209
210 def test_isChecker(self):
211 """
212 Verifies that strcred.makeChecker('unix') returns an object
213 that implements the L{ICredentialsChecker} interface.
214 """
215 self.assertTrue(checkers.ICredentialsChecker.providedBy(self.checker))
216 self.assertIn(credentials.IUsernamePassword,
217 self.checker.credentialInterfaces)
218
219
220 def test_unixCheckerSucceeds(self):
221 """
222 Test that the checker works with valid credentials.
223 """
224 def _gotAvatar(username):
225 self.assertEquals(username, self.admin.username)
226 return (self.checker
227 .requestAvatarId(self.admin)
228 .addCallback(_gotAvatar))
229
230
231 def test_unixCheckerFailsUsername(self):
232 """
233 Test that the checker fails with an invalid username.
234 """
235 return self.assertFailure(self.checker.requestAvatarId(self.badUser),
236 error.UnauthorizedLogin)
237
238
239 def test_unixCheckerFailsPassword(self):
240 """
241 Test that the checker fails with an invalid password.
242 """
243 return self.assertFailure(self.checker.requestAvatarId(self.badPass),
244 error.UnauthorizedLogin)
245
246
247 if None in (pwd, spwd, crypt):
248 for method in (test_unixCheckerSucceeds,
249 test_unixCheckerFailsUsername,
250 test_unixCheckerFailsPassword):
251 method.skip = 'pwd and spwd are both unavailable'
252
253
254
255 class TestFileDBChecker(unittest.TestCase):
256 """
257 Test for the --auth=file:... file checker.
258 """
259
260 def setUp(self):
261 self.admin = credentials.UsernamePassword('admin', 'asdf')
262 self.alice = credentials.UsernamePassword('alice', 'foo')
263 self.badPass = credentials.UsernamePassword('alice', 'foobar')
264 self.badUser = credentials.UsernamePassword('x', 'yz')
265 self.filename = self.mktemp()
266 file(self.filename, 'w').write('admin:asdf\nalice:foo\n')
267 self.checker = strcred.makeChecker('file:' + self.filename)
268
269
270 def _fakeFilename(self):
271 filename = '/DoesNotExist'
272 while os.path.exists(filename):
273 filename += '_'
274 return filename
275
276
277 def test_isChecker(self):
278 """
279 Verifies that strcred.makeChecker('memory') returns an object
280 that implements the L{ICredentialsChecker} interface.
281 """
282 self.assertTrue(checkers.ICredentialsChecker.providedBy(self.checker))
283 self.assertIn(credentials.IUsernamePassword,
284 self.checker.credentialInterfaces)
285
286
287 def test_fileCheckerSucceeds(self):
288 """
289 Test that the checker works with valid credentials.
290 """
291 def _gotAvatar(username):
292 self.assertEquals(username, self.admin.username)
293 return (self.checker
294 .requestAvatarId(self.admin)
295 .addCallback(_gotAvatar))
296
297
298 def test_fileCheckerFailsUsername(self):
299 """
300 Test that the checker fails with an invalid username.
301 """
302 return self.assertFailure(self.checker.requestAvatarId(self.badUser),
303 error.UnauthorizedLogin)
304
305
306 def test_fileCheckerFailsPassword(self):
307 """
308 Test that the checker fails with an invalid password.
309 """
310 return self.assertFailure(self.checker.requestAvatarId(self.badPass),
311 error.UnauthorizedLogin)
312
313
314 def test_failsWithEmptyFilename(self):
315 """
316 Test that an empty filename raises an error.
317 """
318 self.assertRaises(ValueError, strcred.makeChecker, 'file')
319 self.assertRaises(ValueError, strcred.makeChecker, 'file:')
320
321
322 def test_warnWithBadFilename(self):
323 """
324 When the file auth plugin is given a file that doesn't exist, it
325 should produce a warning.
326 """
327 oldOutput = cred_file.theFileCheckerFactory.errorOutput
328 newOutput = StringIO.StringIO()
329 cred_file.theFileCheckerFactory.errorOutput = newOutput
330 checker = strcred.makeChecker('file:' + self._fakeFilename())
331 cred_file.theFileCheckerFactory.errorOutput = oldOutput
332 self.assertIn(cred_file.invalidFileWarning, newOutput.getvalue())
333
334
335
336 class DummyOptions(usage.Options, strcred.AuthOptionMixin):
337 """
338 Simple options for testing L{strcred.AuthOptionMixin}.
339 """
340
341
342
343 class TestCheckerOptions(unittest.TestCase):
344
345 def test_createsList(self):
346 """
347 Test that the --auth command line creates a list in the
348 Options instance and appends values to it.
349 """
350 options = DummyOptions()
351 options.parseOptions(['--auth', 'memory'])
352 self.assertEqual(len(options['credCheckers']), 1)
353 options = DummyOptions()
354 options.parseOptions(['--auth', 'memory', '--auth', 'memory'])
355 self.assertEqual(len(options['credCheckers']), 2)
356
357
358 def test_invalidAuthError(self):
359 """
360 Test that the --auth command line raises an exception when it
361 gets a parameter it doesn't understand.
362 """
363 options = DummyOptions()
364 # If someone adds a 'ThisPluginDoesNotExist' then this unit
365 # test should still run.
366 invalidParameter = getInvalidAuthType()
367 self.assertRaises(
368 usage.UsageError,
369 options.parseOptions, ['--auth', invalidParameter])
370 self.assertRaises(
371 usage.UsageError,
372 options.parseOptions, ['--help-auth-type', invalidParameter])
373
374
375 def test_createsDictionary(self):
376 """
377 Test that the --auth command line creates a dictionary
378 mapping supported interfaces to the list of credentials
379 checkers that support it.
380 """
381 options = DummyOptions()
382 options.parseOptions(['--auth', 'memory', '--auth', 'anonymous'])
383 chd = options['credInterfaces']
384 self.assertEquals(len(chd[credentials.IAnonymous]), 1)
385 self.assertEquals(len(chd[credentials.IUsernamePassword]), 1)
386 chdAnonymous = chd[credentials.IAnonymous][0]
387 chdUserPass = chd[credentials.IUsernamePassword][0]
388 self.assertTrue(checkers.ICredentialsChecker.providedBy(chdAnonymous))
389 self.assertTrue(checkers.ICredentialsChecker.providedBy(chdUserPass))
390 self.assertIn(credentials.IAnonymous,
391 chdAnonymous.credentialInterfaces)
392 self.assertIn(credentials.IUsernamePassword,
393 chdUserPass.credentialInterfaces)
394
395
396 def test_credInterfacesProvidesLists(self):
397 """
398 Test that when two --auth arguments are passed along which
399 support the same interface, a list with both is created.
400 """
401 options = DummyOptions()
402 options.parseOptions(['--auth', 'memory', '--auth', 'unix'])
403 self.assertEquals(
404 options['credCheckers'],
405 options['credInterfaces'][credentials.IUsernamePassword])
406
407
408 def test_listDoesNotDisplayDuplicates(self):
409 """
410 Test that the list for --help-auth does not duplicate items.
411 """
412 authTypes = []
413 options = DummyOptions()
414 for cf in options._checkerFactoriesForOptHelpAuth():
415 self.assertNotIn(cf.authType, authTypes)
416 authTypes.append(cf.authType)
417
418
419 def test_displaysListCorrectly(self):
420 """
421 Test that the --help-auth argument correctly displays all
422 available authentication plugins, then exits.
423 """
424 newStdout = StringIO.StringIO()
425 options = DummyOptions()
426 options.authOutput = newStdout
427 self.assertRaises(SystemExit, options.parseOptions, ['--help-auth'])
428 for checkerFactory in strcred.findCheckerFactories():
429 self.assertIn(checkerFactory.authType, newStdout.getvalue())
430
431
432 def test_displaysHelpCorrectly(self):
433 """
434 Test that the --help-auth-for argument will correctly display
435 the help file for a particular authentication plugin.
436 """
437 newStdout = StringIO.StringIO()
438 options = DummyOptions()
439 options.authOutput = newStdout
440 self.assertRaises(
441 SystemExit, options.parseOptions, ['--help-auth-type', 'file'])
442 for line in cred_file.theFileCheckerFactory.authHelp:
443 if line.strip():
444 self.assertIn(line.strip(), newStdout.getvalue())
445
446
447 def test_unexpectedException(self):
448 """
449 When the checker specified by --auth raises an unexpected error, it
450 should be caught and re-raised within a L{usage.UsageError}.
451 """
452 options = DummyOptions()
453 err = self.assertRaises(usage.UsageError, options.parseOptions,
454 ['--auth', 'file'])
455 self.assertEquals(str(err),
456 "Unexpected error: 'file' requires a filename")
457
458
459
460 class OptionsForUsernamePassword(usage.Options, strcred.AuthOptionMixin):
461 supportedInterfaces = (credentials.IUsernamePassword,)
462
463
464
465 class OptionsForUsernameHashedPassword(usage.Options, strcred.AuthOptionMixin):
466 supportedInterfaces = (credentials.IUsernameHashedPassword,)
467
468
469
470 class OptionsSupportsAllInterfaces(usage.Options, strcred.AuthOptionMixin):
471 supportedInterfaces = None
472
473
474
475 class OptionsSupportsNoInterfaces(usage.Options, strcred.AuthOptionMixin):
476 supportedInterfaces = []
477
478
479
480 class TestLimitingInterfaces(unittest.TestCase):
481 """
482 Tests functionality that allows an application to limit the
483 credential interfaces it can support. For the purposes of this
484 test, we use IUsernameHashedPassword, although this will never
485 really be used by the command line.
486
487 (I have, to date, not thought of a half-decent way for a user to
488 specify a hash algorithm via the command-line. Nor do I think it's
489 very useful.)
490
491 I should note that, at first, this test is counter-intuitive,
492 because we're using the checker with a pre-defined hash function
493 as the 'bad' checker. See the documentation for
494 L{twisted.cred.checkers.FilePasswordDB.hash} for more details.
495 """
496
497 def setUp(self):
498 self.filename = self.mktemp()
499 file(self.filename, 'w').write('admin:asdf\nalice:foo\n')
500 self.goodChecker = checkers.FilePasswordDB(self.filename)
501 self.badChecker = checkers.FilePasswordDB(self.filename, hash=self._hash )
502 self.anonChecker = checkers.AllowAnonymousAccess()
503
504
505 def _hash(self, networkUsername, networkPassword, storedPassword):
506 """
507 A dumb hash that doesn't really do anything.
508 """
509 return networkPassword
510
511
512 def test_supportsInterface(self):
513 """
514 Test that the supportsInterface method behaves appropriately.
515 """
516 options = OptionsForUsernamePassword()
517 self.assertTrue(
518 options.supportsInterface(credentials.IUsernamePassword))
519 self.assertFalse(
520 options.supportsInterface(credentials.IAnonymous))
521 self.assertRaises(
522 strcred.UnsupportedInterfaces, options.addChecker, self.anonChecker)
523
524
525 def test_supportsAllInterfaces(self):
526 """
527 Test that the supportsInterface method behaves appropriately
528 when the supportedInterfaces attribute is None.
529 """
530 options = OptionsSupportsAllInterfaces()
531 self.assertTrue(
532 options.supportsInterface(credentials.IUsernamePassword))
533 self.assertTrue(
534 options.supportsInterface(credentials.IAnonymous))
535
536
537 def test_supportsCheckerFactory(self):
538 """
539 Test that the supportsCheckerFactory method behaves appropriately.
540 """
541 options = OptionsForUsernamePassword()
542 fileCF = cred_file.theFileCheckerFactory
543 anonCF = cred_anonymous.theAnonymousCheckerFactory
544 self.assertTrue(options.supportsCheckerFactory(fileCF))
545 self.assertFalse(options.supportsCheckerFactory(anonCF))
546
547
548 def test_canAddSupportedChecker(self):
549 """
550 Test that when addChecker is called with a checker that
551 implements at least one of the interfaces our application
552 supports, it is successful.
553 """
554 options = OptionsForUsernamePassword()
555 options.addChecker(self.goodChecker)
556 iface = options.supportedInterfaces[0]
557 # Test that we did get IUsernamePassword
558 self.assertIdentical(options['credInterfaces'][iface][0], self.goodCheck er)
559 self.assertIdentical(options['credCheckers'][0], self.goodChecker)
560 # Test that we didn't get IUsernameHashedPassword
561 self.assertEquals(len(options['credInterfaces'][iface]), 1)
562 self.assertEquals(len(options['credCheckers']), 1)
563
564
565 def test_failOnAddingUnsupportedChecker(self):
566 """
567 Test that when addChecker is called with a checker that does
568 not implement any supported interfaces, it fails.
569 """
570 options = OptionsForUsernameHashedPassword()
571 self.assertRaises(strcred.UnsupportedInterfaces,
572 options.addChecker, self.badChecker)
573
574
575 def test_unsupportedInterfaceError(self):
576 """
577 Test that the --auth command line raises an exception when it
578 gets a checker we don't support.
579 """
580 options = OptionsSupportsNoInterfaces()
581 authType = cred_anonymous.theAnonymousCheckerFactory.authType
582 self.assertRaises(
583 usage.UsageError,
584 options.parseOptions, ['--auth', authType])
585
586
587 def test_helpAuthLimitsOutput(self):
588 """
589 Test that --help-auth will only list checkers that purport to
590 supply at least one of the credential interfaces our
591 application can use.
592 """
593 options = OptionsForUsernamePassword()
594 for factory in options._checkerFactoriesForOptHelpAuth():
595 invalid = True
596 for interface in factory.credentialInterfaces:
597 if options.supportsInterface(interface):
598 invalid = False
599 if invalid:
600 raise strcred.UnsupportedInterfaces()
601
602
603 def test_helpAuthTypeLimitsOutput(self):
604 """
605 Test that --help-auth-type will display a warning if you get
606 help for an authType that does not supply at least one of the
607 credential interfaces our application can use.
608 """
609 options = OptionsForUsernamePassword()
610 # Find an interface that we can use for our test
611 invalidFactory = None
612 for factory in strcred.findCheckerFactories():
613 if not options.supportsCheckerFactory(factory):
614 invalidFactory = factory
615 break
616 self.assertNotIdentical(invalidFactory, None)
617 # Capture output and make sure the warning is there
618 newStdout = StringIO.StringIO()
619 options.authOutput = newStdout
620 self.assertRaises(SystemExit, options.parseOptions,
621 ['--help-auth-type', 'anonymous'])
622 self.assertIn(strcred.notSupportedWarning, newStdout.getvalue())
623
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/test/test_stdio.py ('k') | third_party/twisted_8_1/twisted/test/test_strerror.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698