1 # Copyright (C) 2009 Google Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
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
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.
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.
29 from __future__ import with_statement
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
40 # FIXME: Other unit tests probably want this class.
41 class _TemporaryDirectory(object):
42 def __init__(self, **kwargs):
44 self._directory_path = None
47 self._directory_path = tempfile.mkdtemp(**self._kwargs)
48 return self._directory_path
50 def __exit__(self, type, value, traceback):
51 os.rmdir(self._directory_path)
54 class CredentialsTest(unittest.TestCase):
55 example_security_output = """keychain: "/Users/test/Library/Keychains/login.keychain"
58 0x00000007 <blob>="bugs.webkit.org (test@webkit.org)"
59 0x00000008 <blob>=<NULL>
60 "acct"<blob>="test@webkit.org"
62 "cdat"<timedate>=0x32303039303832353233353231365A00 "20090825235216Z\000"
65 "desc"<blob>="Web form password"
66 "icmt"<blob>="default"
68 "mdat"<timedate>=0x32303039303930393137323635315A00 "20090909172651Z\000"
71 "port"<uint32>=0x00000000
76 "srvr"<blob>="bugs.webkit.org"
78 password: "SECRETSAUCE"
81 def test_keychain_lookup_on_non_mac(self):
82 class FakeCredentials(Credentials):
83 def _is_mac_os_x(self):
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])
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"])
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.
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()
105 def _assert_security_call(self, username=None):
106 executive_mock = Mock()
107 credentials = Credentials("example.com", executive=executive_mock)
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)
112 security_args = ["/usr/bin/security", "find-internet-password", "-g", "-s", "example.com"]
114 security_args += ["-a", username]
115 executive_mock.run_command.assert_called_with(security_args)
117 def test_security_calls(self):
118 self._assert_security_call()
119 self._assert_security_call(username="foo")
121 def test_credentials_from_environment(self):
122 executive_mock = Mock()
123 credentials = Credentials("example.com", executive=executive_mock)
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
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):
139 def _credentials_from_keychain(self, username):
140 return ("test@webkit.org", "SECRETSAUCE")
142 def _credentials_from_environment(self):
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"))
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):
158 class FakeCredentials(Credentials):
159 def _is_mac_os_x(self):
162 def _credentials_from_keychain(self, username):
163 return ("test@webkit.org", None)
165 def _credentials_from_environment(self):
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"))
175 if __name__ == '__main__':