initial import
[vuplus_webkit] / Tools / Scripts / webkitpy / common / net / credentials_unittest.py
1 # Copyright (C) 2009 Google Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 #    * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 #    * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 #    * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 from __future__ import with_statement
30
31 import os
32 import tempfile
33 import unittest
34 from webkitpy.common.net.credentials import Credentials
35 from webkitpy.common.system.executive import Executive
36 from webkitpy.common.system.outputcapture import OutputCapture
37 from webkitpy.thirdparty.mock import Mock
38
39
40 # FIXME: Other unit tests probably want this class.
41 class _TemporaryDirectory(object):
42     def __init__(self, **kwargs):
43         self._kwargs = kwargs
44         self._directory_path = None
45
46     def __enter__(self):
47         self._directory_path = tempfile.mkdtemp(**self._kwargs)
48         return self._directory_path
49
50     def __exit__(self, type, value, traceback):
51         os.rmdir(self._directory_path)
52
53
54 class CredentialsTest(unittest.TestCase):
55     example_security_output = """keychain: "/Users/test/Library/Keychains/login.keychain"
56 class: "inet"
57 attributes:
58     0x00000007 <blob>="bugs.webkit.org (test@webkit.org)"
59     0x00000008 <blob>=<NULL>
60     "acct"<blob>="test@webkit.org"
61     "atyp"<blob>="form"
62     "cdat"<timedate>=0x32303039303832353233353231365A00  "20090825235216Z\000"
63     "crtr"<uint32>=<NULL>
64     "cusi"<sint32>=<NULL>
65     "desc"<blob>="Web form password"
66     "icmt"<blob>="default"
67     "invi"<sint32>=<NULL>
68     "mdat"<timedate>=0x32303039303930393137323635315A00  "20090909172651Z\000"
69     "nega"<sint32>=<NULL>
70     "path"<blob>=<NULL>
71     "port"<uint32>=0x00000000 
72     "prot"<blob>=<NULL>
73     "ptcl"<uint32>="htps"
74     "scrp"<sint32>=<NULL>
75     "sdmn"<blob>=<NULL>
76     "srvr"<blob>="bugs.webkit.org"
77     "type"<uint32>=<NULL>
78 password: "SECRETSAUCE"
79 """
80
81     def test_keychain_lookup_on_non_mac(self):
82         class FakeCredentials(Credentials):
83             def _is_mac_os_x(self):
84                 return False
85         credentials = FakeCredentials("bugs.webkit.org")
86         self.assertEqual(credentials._is_mac_os_x(), False)
87         self.assertEqual(credentials._credentials_from_keychain("foo"), ["foo", None])
88
89     def test_security_output_parse(self):
90         credentials = Credentials("bugs.webkit.org")
91         self.assertEqual(credentials._parse_security_tool_output(self.example_security_output), ["test@webkit.org", "SECRETSAUCE"])
92
93     def test_security_output_parse_entry_not_found(self):
94         credentials = Credentials("foo.example.com")
95         if not credentials._is_mac_os_x():
96             return # This test does not run on a non-Mac.
97
98         # Note, we ignore the captured output because it is already covered
99         # by the test case CredentialsTest._assert_security_call (below).
100         outputCapture = OutputCapture()
101         outputCapture.capture_output()
102         self.assertEqual(credentials._run_security_tool(), None)
103         outputCapture.restore_output()
104
105     def _assert_security_call(self, username=None):
106         executive_mock = Mock()
107         credentials = Credentials("example.com", executive=executive_mock)
108
109         expected_stderr = "Reading Keychain for example.com account and password.  Click \"Allow\" to continue...\n"
110         OutputCapture().assert_outputs(self, credentials._run_security_tool, [username], expected_stderr=expected_stderr)
111
112         security_args = ["/usr/bin/security", "find-internet-password", "-g", "-s", "example.com"]
113         if username:
114             security_args += ["-a", username]
115         executive_mock.run_command.assert_called_with(security_args)
116
117     def test_security_calls(self):
118         self._assert_security_call()
119         self._assert_security_call(username="foo")
120
121     def test_credentials_from_environment(self):
122         executive_mock = Mock()
123         credentials = Credentials("example.com", executive=executive_mock)
124
125         saved_environ = os.environ.copy()
126         os.environ['WEBKIT_BUGZILLA_USERNAME'] = "foo"
127         os.environ['WEBKIT_BUGZILLA_PASSWORD'] = "bar"
128         username, password = credentials._credentials_from_environment()
129         self.assertEquals(username, "foo")
130         self.assertEquals(password, "bar")
131         os.environ = saved_environ
132
133     def test_read_credentials_without_git_repo(self):
134         # FIXME: This should share more code with test_keyring_without_git_repo
135         class FakeCredentials(Credentials):
136             def _is_mac_os_x(self):
137                 return True
138
139             def _credentials_from_keychain(self, username):
140                 return ("test@webkit.org", "SECRETSAUCE")
141
142             def _credentials_from_environment(self):
143                 return (None, None)
144
145         with _TemporaryDirectory(suffix="not_a_git_repo") as temp_dir_path:
146             credentials = FakeCredentials("bugs.webkit.org", cwd=temp_dir_path)
147             # FIXME: Using read_credentials here seems too broad as higher-priority
148             # credential source could be affected by the user's environment.
149             self.assertEqual(credentials.read_credentials(), ("test@webkit.org", "SECRETSAUCE"))
150
151
152     def test_keyring_without_git_repo(self):
153         # FIXME: This should share more code with test_read_credentials_without_git_repo
154         class MockKeyring(object):
155             def get_password(self, host, username):
156                 return "NOMNOMNOM"
157
158         class FakeCredentials(Credentials):
159             def _is_mac_os_x(self):
160                 return True
161
162             def _credentials_from_keychain(self, username):
163                 return ("test@webkit.org", None)
164
165             def _credentials_from_environment(self):
166                 return (None, None)
167
168         with _TemporaryDirectory(suffix="not_a_git_repo") as temp_dir_path:
169             credentials = FakeCredentials("fake.hostname", cwd=temp_dir_path, keyring=MockKeyring())
170             # FIXME: Using read_credentials here seems too broad as higher-priority
171             # credential source could be affected by the user's environment.
172             self.assertEqual(credentials.read_credentials(), ("test@webkit.org", "NOMNOMNOM"))
173
174
175 if __name__ == '__main__':
176     unittest.main()