File: committer_auth_unittest.py

package info (click to toggle)
qtwebkit-opensource-src 5.7.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 291,692 kB
  • ctags: 268,122
  • sloc: cpp: 1,360,420; python: 70,286; ansic: 42,986; perl: 35,476; ruby: 12,236; objc: 9,465; xml: 8,396; asm: 3,873; yacc: 2,397; sh: 1,647; makefile: 650; lex: 644; java: 110
file content (220 lines) | stat: -rwxr-xr-x 9,892 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/usr/bin/env python
#
# Copyright (C) 2011 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import StringIO
import __builtin__
import buildbot.status.web.auth
import contextlib
import os
import unittest

from committer_auth import CommitterAuth


# This subclass of StringIO supports the context manager protocol so it works
# with "with" statements, just like real files.
class CMStringIO(StringIO.StringIO):
    def __enter__(self):
        return self

    def __exit__(self, exception, value, traceback):
        self.close()


@contextlib.contextmanager
def open_override(func):
    original_open = __builtin__.open
    __builtin__.open = func
    yield
    __builtin__.open = original_open


class CommitterAuthTest(unittest.TestCase):
    def setUp(self):
        self.auth = CommitterAuth('path/to/auth.json')
        self.auth.open_auth_json_file = self.fake_auth_json_file
        self.auth.open_webkit_committers_file = self.fake_committers_file
        self.auth.open_trac_credentials_file = self.fake_htdigest_file

    def fake_open_function(self, expected_filename):
        def fake_open(name, mode='r'):
            self.fake_open_was_called = True
            self.assertEqual(expected_filename, name)
        return fake_open

    def test_authentication_success(self):
        self.assertTrue(self.auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('', self.auth.errmsg())
        self.assertTrue(self.auth.authenticate('committer2@example.com', 'committer2password'))
        self.assertEqual('', self.auth.errmsg())

    def test_committer_without_trac_credentials_fails(self):
        self.assertFalse(self.auth.authenticate('committer3@webkit.org', 'committer3password'))
        self.assertEqual('Invalid username/password', self.auth.errmsg())

    def test_fail_to_open_auth_json_file(self):
        def raise_IOError():
            raise IOError(2, 'No such file or directory', 'path/to/auth.json')
        auth = CommitterAuth('path/to/auth.json')
        auth.open_auth_json_file = raise_IOError
        self.assertFalse(auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('Error opening auth.json file: No such file or directory', auth.errmsg())

    def test_fail_to_open_trac_credentials_file(self):
        def raise_IOError():
            raise IOError(2, 'No such file or directory', 'path/to/trac/credentials')
        self.auth.open_trac_credentials_file = raise_IOError
        self.assertFalse(self.auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('Error opening Trac credentials file: No such file or directory', self.auth.errmsg())

    def test_fail_to_open_webkit_committers_file(self):
        def raise_IOError():
            raise IOError(2, 'No such file or directory', 'path/to/webkit/committers')
        self.auth.open_webkit_committers_file = raise_IOError
        self.assertFalse(self.auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('Error opening WebKit committers file: No such file or directory', self.auth.errmsg())

    def test_implements_IAuth(self):
        self.assertTrue(buildbot.status.web.auth.IAuth.implementedBy(CommitterAuth))

    def test_invalid_auth_json_file(self):
        auth = CommitterAuth('path/to/auth.json')
        auth.open_auth_json_file = self.invalid_auth_json_file
        self.assertFalse(auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('Error parsing auth.json file: No JSON object could be decoded', auth.errmsg())

    def test_invalid_committers_file(self):
        self.auth.open_webkit_committers_file = self.invalid_committers_file
        self.assertFalse(self.auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('Error parsing WebKit committers file', self.auth.errmsg())

    def test_invalid_trac_credentials_file(self):
        self.auth.open_trac_credentials_file = self.invalid_htdigest_file
        self.assertFalse(self.auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('Error parsing Trac credentials file', self.auth.errmsg())

    def test_missing_auth_json_keys(self):
        auth = CommitterAuth('path/to/auth.json')
        auth.open_auth_json_file = lambda: CMStringIO('{ "trac_credentials": "path/to/trac/credentials" }')
        self.assertFalse(auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('auth.json file is missing "webkit_committers" key', auth.errmsg())

        auth.open_auth_json_file = lambda: CMStringIO('{ "webkit_committers": "path/to/webkit/committers" }')
        auth.open_webkit_committers_file = self.fake_committers_file
        self.assertFalse(auth.authenticate('committer@webkit.org', 'committerpassword'))
        self.assertEqual('auth.json file is missing "trac_credentials" key', auth.errmsg())

    def test_open_auth_json_file(self):
        auth = CommitterAuth('path/to/auth.json')
        self.fake_open_was_called = False
        with open_override(self.fake_open_function(auth.auth_json_filename())):
            auth.open_auth_json_file()
        self.assertTrue(self.fake_open_was_called)

    def test_open_trac_credentials_file(self):
        auth = CommitterAuth('path/to/auth.json')
        auth.trac_credentials_filename = lambda: 'trac credentials filename'
        self.fake_open_was_called = False
        with open_override(self.fake_open_function(auth.trac_credentials_filename())):
            auth.open_trac_credentials_file()
        self.assertTrue(self.fake_open_was_called)

    def test_open_webkit_committers_file(self):
        auth = CommitterAuth('path/to/auth.json')
        auth.webkit_committers_filename = lambda: 'webkit committers filename'
        self.fake_open_was_called = False
        with open_override(self.fake_open_function(auth.webkit_committers_filename())):
            auth.open_webkit_committers_file()
        self.assertTrue(self.fake_open_was_called)

    def test_non_committer_fails(self):
        self.assertFalse(self.auth.authenticate('noncommitter@example.com', 'noncommitterpassword'))
        self.assertEqual('Invalid username/password', self.auth.errmsg())

    def test_trac_credentials_filename(self):
        self.assertEqual('path/to/trac/credentials', self.auth.trac_credentials_filename())

    def test_unknown_user_fails(self):
        self.assertFalse(self.auth.authenticate('nobody@example.com', 'nobodypassword'))
        self.assertEqual('Invalid username/password', self.auth.errmsg())

    def test_username_is_prefix_of_valid_user(self):
        self.assertFalse(self.auth.authenticate('committer@webkit.orgg', 'committerpassword'))
        self.assertEqual('Invalid username/password', self.auth.errmsg())

    def test_webkit_committers(self):
        self.assertEqual(['committer@webkit.org', 'committer2@example.com', 'committer3@webkit.org'], self.auth.webkit_committers())

    def test_webkit_committers_filename(self):
        self.assertEqual('path/to/webkit/committers', self.auth.webkit_committers_filename())

    def test_wrong_password_fails(self):
        self.assertFalse(self.auth.authenticate('committer@webkit.org', 'wrongpassword'))
        self.assertEqual('Invalid username/password', self.auth.errmsg())

    def fake_auth_json_file(self):
        return CMStringIO("""{
    "trac_credentials": "path/to/trac/credentials",
    "webkit_committers": "path/to/webkit/committers"
}""")

    def invalid_auth_json_file(self):
        return CMStringIO('~!@#$%^&*()_+')

    def fake_committers_file(self):
        return CMStringIO("""[groups]
group1 = user@example.com,user2@example.com
group2 = user3@example.com

group3 =
group4 =

webkit = committer@webkit.org,committer2@example.com,committer3@webkit.org

[service:/]
*    = r
""")

    def invalid_committers_file(self):
        return CMStringIO("""[groups]

[[groups2]
""")

    def fake_htdigest_file(self):
        return CMStringIO("""committer@webkit.org:Mac OS Forge:761c8dcb7d9b5908007ed142f62fe73a
committer2@example.com:Mac OS Forge:faeee69acc2e49af3a0dbb15bd593ef4
noncommitter@example.com:Mac OS Forge:b99aa7ad32306a654ca4d57839fde9c1
""")

    def invalid_htdigest_file(self):
        return CMStringIO("""committer@webkit.org:Mac OS Forge:761c8dcb7d9b5908007ed142f62fe73a
committer2@example.com:Mac OS Forge:faeee69acc2e49af3a0dbb15bd593ef4
noncommitter@example.com:Mac OS Forge:b99aa7ad32306a654ca4d57839fde9c1
committer4@example.com:Mac OS Forge:::
""")


if __name__ == '__main__':
    unittest.main()