1# Copyright 2016 Google Inc. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import unittest
16import mock
17
18import google.auth.credentials
19import google_auth_httplib2
20import httplib2
21import oauth2client.client
22
23from googleapiclient import _auth
24
25
26class TestAuthWithGoogleAuth(unittest.TestCase):
27    def setUp(self):
28        _auth.HAS_GOOGLE_AUTH = True
29        _auth.HAS_OAUTH2CLIENT = False
30
31    def tearDown(self):
32        _auth.HAS_GOOGLE_AUTH = True
33        _auth.HAS_OAUTH2CLIENT = True
34
35    def test_default_credentials(self):
36        with mock.patch("google.auth.default", autospec=True) as default:
37            default.return_value = (mock.sentinel.credentials, mock.sentinel.project)
38
39            credentials = _auth.default_credentials()
40
41            self.assertEqual(credentials, mock.sentinel.credentials)
42
43    def test_credentials_from_file(self):
44        with mock.patch(
45            "google.auth.load_credentials_from_file", autospec=True
46        ) as default:
47            default.return_value = (mock.sentinel.credentials, mock.sentinel.project)
48
49            credentials = _auth.credentials_from_file("credentials.json")
50
51            self.assertEqual(credentials, mock.sentinel.credentials)
52            default.assert_called_once_with(
53                "credentials.json", scopes=None, quota_project_id=None
54            )
55
56    def test_default_credentials_with_scopes(self):
57        with mock.patch("google.auth.default", autospec=True) as default:
58            default.return_value = (mock.sentinel.credentials, mock.sentinel.project)
59            credentials = _auth.default_credentials(scopes=["1", "2"])
60
61            default.assert_called_once_with(scopes=["1", "2"], quota_project_id=None)
62            self.assertEqual(credentials, mock.sentinel.credentials)
63
64    def test_default_credentials_with_quota_project(self):
65        with mock.patch("google.auth.default", autospec=True) as default:
66            default.return_value = (mock.sentinel.credentials, mock.sentinel.project)
67            credentials = _auth.default_credentials(quota_project_id="my-project")
68
69            default.assert_called_once_with(scopes=None, quota_project_id="my-project")
70            self.assertEqual(credentials, mock.sentinel.credentials)
71
72    def test_with_scopes_non_scoped(self):
73        credentials = mock.Mock(spec=google.auth.credentials.Credentials)
74
75        returned = _auth.with_scopes(credentials, mock.sentinel.scopes)
76
77        self.assertEqual(credentials, returned)
78
79    def test_with_scopes_scoped(self):
80        class CredentialsWithScopes(
81            google.auth.credentials.Credentials, google.auth.credentials.Scoped
82        ):
83            pass
84
85        credentials = mock.Mock(spec=CredentialsWithScopes)
86        credentials.requires_scopes = True
87
88        returned = _auth.with_scopes(credentials, mock.sentinel.scopes)
89
90        self.assertNotEqual(credentials, returned)
91        self.assertEqual(returned, credentials.with_scopes.return_value)
92        credentials.with_scopes.assert_called_once_with(mock.sentinel.scopes, default_scopes=None)
93
94    def test_authorized_http(self):
95        credentials = mock.Mock(spec=google.auth.credentials.Credentials)
96
97        authorized_http = _auth.authorized_http(credentials)
98
99        self.assertIsInstance(authorized_http, google_auth_httplib2.AuthorizedHttp)
100        self.assertEqual(authorized_http.credentials, credentials)
101        self.assertIsInstance(authorized_http.http, httplib2.Http)
102        self.assertIsInstance(authorized_http.http.timeout, int)
103        self.assertGreater(authorized_http.http.timeout, 0)
104
105
106class TestAuthWithOAuth2Client(unittest.TestCase):
107    def setUp(self):
108        _auth.HAS_GOOGLE_AUTH = False
109        _auth.HAS_OAUTH2CLIENT = True
110
111    def tearDown(self):
112        _auth.HAS_GOOGLE_AUTH = True
113        _auth.HAS_OAUTH2CLIENT = True
114
115    def test_default_credentials(self):
116        default_patch = mock.patch(
117            "oauth2client.client.GoogleCredentials.get_application_default"
118        )
119
120        with default_patch as default:
121            default.return_value = mock.sentinel.credentials
122
123            credentials = _auth.default_credentials()
124
125            self.assertEqual(credentials, mock.sentinel.credentials)
126
127    def test_credentials_from_file(self):
128        with self.assertRaises(EnvironmentError):
129            credentials = _auth.credentials_from_file("credentials.json")
130
131    def test_default_credentials_with_scopes_and_quota_project(self):
132        with self.assertRaises(EnvironmentError):
133            credentials = _auth.default_credentials(
134                scopes=["1", "2"], quota_project_id="my-project"
135            )
136
137    def test_with_scopes_non_scoped(self):
138        credentials = mock.Mock(spec=oauth2client.client.Credentials)
139
140        returned = _auth.with_scopes(credentials, mock.sentinel.scopes)
141
142        self.assertEqual(credentials, returned)
143
144    def test_with_scopes_scoped(self):
145        credentials = mock.Mock(spec=oauth2client.client.GoogleCredentials)
146        credentials.create_scoped_required.return_value = True
147
148        returned = _auth.with_scopes(credentials, mock.sentinel.scopes)
149
150        self.assertNotEqual(credentials, returned)
151        self.assertEqual(returned, credentials.create_scoped.return_value)
152        credentials.create_scoped.assert_called_once_with(mock.sentinel.scopes)
153
154    def test_authorized_http(self):
155        credentials = mock.Mock(spec=oauth2client.client.Credentials)
156
157        authorized_http = _auth.authorized_http(credentials)
158
159        http = credentials.authorize.call_args[0][0]
160
161        self.assertEqual(authorized_http, credentials.authorize.return_value)
162        self.assertIsInstance(http, httplib2.Http)
163        self.assertIsInstance(http.timeout, int)
164        self.assertGreater(http.timeout, 0)
165
166
167class TestAuthWithoutAuth(unittest.TestCase):
168    def setUp(self):
169        _auth.HAS_GOOGLE_AUTH = False
170        _auth.HAS_OAUTH2CLIENT = False
171
172    def tearDown(self):
173        _auth.HAS_GOOGLE_AUTH = True
174        _auth.HAS_OAUTH2CLIENT = True
175
176    def test_default_credentials(self):
177        with self.assertRaises(EnvironmentError):
178            print(_auth.default_credentials())
179
180
181class TestGoogleAuthWithoutHttplib2(unittest.TestCase):
182    def setUp(self):
183        _auth.google_auth_httplib2 = None
184
185    def tearDown(self):
186        _auth.google_auth_httplib2 = google_auth_httplib2
187
188    def test_default_credentials(self):
189        credentials = mock.Mock(spec=google.auth.credentials.Credentials)
190        with self.assertRaises(ValueError):
191            _auth.authorized_http(credentials)
192