~justin-fathomdb/nova/justinsb-openstack-api-volumes

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/test/test_strcred.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

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