Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Side by Side Diff: net/android/junit/src/org/chromium/net/HttpNegotiateAuthenticatorTest.java

Issue 1128043007: Support Kerberos on Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix cbentzel@'s nits Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.net;
6
7 import static org.hamcrest.CoreMatchers.equalTo;
8 import static org.hamcrest.CoreMatchers.notNullValue;
9 import static org.hamcrest.CoreMatchers.nullValue;
10 import static org.junit.Assert.assertThat;
11 import static org.junit.Assert.fail;
12 import static org.mockito.Matchers.anyInt;
13 import static org.mockito.Matchers.anyLong;
14 import static org.mockito.Matchers.anyString;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.eq;
17 import static org.mockito.Mockito.mock;
18 import static org.mockito.Mockito.spy;
19 import static org.mockito.Mockito.verify;
20 import static org.mockito.Mockito.when;
21
22 import android.accounts.AccountManager;
23 import android.accounts.AccountManagerCallback;
24 import android.accounts.AccountManagerFuture;
25 import android.accounts.AuthenticatorException;
26 import android.accounts.OperationCanceledException;
27 import android.app.Activity;
28 import android.os.Bundle;
29 import android.os.Handler;
30
31 import org.chromium.base.BaseChromiumApplication;
32 import org.chromium.testing.local.LocalRobolectricTestRunner;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.robolectric.Robolectric;
36 import org.robolectric.annotation.Config;
37 import org.robolectric.annotation.Implementation;
38 import org.robolectric.annotation.Implements;
39 import org.robolectric.shadows.ShadowAccountManager;
40
41 import java.io.IOException;
42
43 /**
44 * Robolectric tests for HttpNegotiateAuthenticator
45 */
46 @RunWith(LocalRobolectricTestRunner.class)
47 @Config(manifest = Config.NONE,
48 shadows = HttpNegotiateAuthenticatorTest.ExtendedShadowAccountManager.cl ass,
49 application = BaseChromiumApplication.class)
50 public class HttpNegotiateAuthenticatorTest {
51 static int sCallCount = 0;
52 static String sAccountTypeReceived;
53 static String sAuthTokenTypeReceived;
54 static String sFeaturesReceived[];
55 static Bundle sAddAccountOptionsReceived;
56 static Bundle sAuthTokenOptionsReceived;
57 static AccountManagerCallback<Bundle> sCallbackReceived;
58 static Handler sHandlerReceived;
59
60 /**
61 * Robolectic's ShadowAccountManager doesn't implement getAccountsByTypeAndF eature so extend it.
62 * We simply check the call is correct, and don't try to emulate it Note: Sh adow classes need to
63 * be public and static.
64 */
65 @Implements(AccountManager.class)
66 public static class ExtendedShadowAccountManager extends ShadowAccountManage r {
67 @Implementation
68 public AccountManagerFuture<Bundle> getAuthTokenByFeatures(String accoun tType,
69 String authTokenType, String[] features, Activity activity,
70 Bundle addAccountOptions, Bundle getAuthTokenOptions,
71 AccountManagerCallback<Bundle> callback, Handler handler) {
72 sCallCount++;
73 sAccountTypeReceived = accountType;
74 sAuthTokenTypeReceived = authTokenType;
75 sFeaturesReceived = features;
76 sAddAccountOptionsReceived = addAccountOptions;
77 sAuthTokenOptionsReceived = getAuthTokenOptions;
78 sCallbackReceived = callback;
79 sHandlerReceived = handler;
80
81 return null;
82 }
83 }
84
85 /**
86 * Test of {@link HttpNegotiateAuthenticator#getNextAuthToken}
87 */
88 @Test
89 public void testGetNextAuthToken() {
90 HttpNegotiateAuthenticator authenticator =
91 HttpNegotiateAuthenticator.create("Dummy_Account");
92 Robolectric.buildActivity(Activity.class).create().start().resume().visi ble();
93 authenticator.getNextAuthToken(0, "test_principal", "", true);
94 assertThat("getAuthTokenByFeatures called precisely once", sCallCount, e qualTo(1));
95 assertThat("Received account type matches input", sAccountTypeReceived,
96 equalTo("Dummy_Account"));
97 assertThat("AuthTokenType is \"SPNEGO:HOSTBASED:test_principal\"", sAuth TokenTypeReceived,
98 equalTo("SPNEGO:HOSTBASED:test_principal"));
99 assertThat("Features are precisely {\"SPNEGO\"}", sFeaturesReceived,
100 equalTo(new String[] {"SPNEGO"}));
101 assertThat("No account options requested", sAddAccountOptionsReceived, n ullValue());
102 assertThat("There is no existing context",
103 sAuthTokenOptionsReceived.get(HttpNegotiateConstants.KEY_SPNEGO_ CONTEXT),
104 nullValue());
105 assertThat("The existing token is empty",
106 sAuthTokenOptionsReceived.getString(HttpNegotiateConstants.KEY_I NCOMING_AUTH_TOKEN),
107 equalTo(""));
108 assertThat("Delegation is allowed",
109 sAuthTokenOptionsReceived.getBoolean(HttpNegotiateConstants.KEY_ CAN_DELEGATE),
110 equalTo(true));
111 assertThat("getAuthTokenByFeatures was called with a callback", sCallbac kReceived,
112 notNullValue());
113 assertThat("getAuthTokenByFeatures was called with a handler", sHandlerR eceived,
114 notNullValue());
115 }
116
117 /**
118 * Test of callback called when getting the auth token completes.
119 */
120 @Test
121 public void testAccountManagerCallbackRun() {
122 // Spy on the authenticator so that we can override and intercept the na tive method call.
123 HttpNegotiateAuthenticator authenticator =
124 spy(HttpNegotiateAuthenticator.create("Dummy_Account"));
125 doNothing().when(authenticator).nativeSetResult(anyLong(), anyInt(), any String());
126
127 Robolectric.buildActivity(Activity.class).create().start().resume().visi ble();
128
129 // Call getNextAuthToken to get the callback
130 authenticator.getNextAuthToken(1234, "test_principal", "", true);
131
132 // Avoid warning when creating mock accountManagerFuture, can't take .cl ass of an
133 // instantiated generic type, yet compiler complains if I leave it unins tantiated.
134 @SuppressWarnings("unchecked")
135 AccountManagerFuture<Bundle> accountManagerFuture = mock(AccountManagerF uture.class);
136 Bundle resultBundle = new Bundle();
137 Bundle context = new Bundle();
138 context.putString("String", "test_context");
139 resultBundle.putInt(HttpNegotiateConstants.KEY_SPNEGO_RESULT, HttpNegoti ateConstants.OK);
140 resultBundle.putBundle(HttpNegotiateConstants.KEY_SPNEGO_CONTEXT, contex t);
141 resultBundle.putString(AccountManager.KEY_AUTHTOKEN, "output_token");
142 try {
143 when(accountManagerFuture.getResult()).thenReturn(resultBundle);
144 } catch (OperationCanceledException | AuthenticatorException | IOExcepti on e) {
145 // Can never happen - artifact of Mockito.
146 fail();
147 }
148 sCallbackReceived.run(accountManagerFuture);
149 verify(authenticator).nativeSetResult(1234, 0, "output_token");
150
151 // Check that the next call to getNextAuthToken uses the correct context
152 authenticator.getNextAuthToken(5678, "test_principal", "", true);
153 assertThat("The spnego context is preserved between calls",
154 sAuthTokenOptionsReceived.getBundle(HttpNegotiateConstants.KEY_S PNEGO_CONTEXT),
155 equalTo(context));
156
157 // Test exception path
158 try {
159 when(accountManagerFuture.getResult()).thenThrow(new OperationCancel edException());
160 } catch (OperationCanceledException | AuthenticatorException | IOExcepti on e) {
161 // Can never happen - artifact of Mockito.
162 fail();
163 }
164 sCallbackReceived.run(accountManagerFuture);
165 verify(authenticator).nativeSetResult(5678, NetError.ERR_ABORTED, null);
166 }
167
168 private void checkErrorReturn(Integer spnegoError, int expectedError) {
169 // Spy on the authenticator so that we can override and intercept the na tive method call.
170 HttpNegotiateAuthenticator authenticator =
171 spy(HttpNegotiateAuthenticator.create("Dummy_Account"));
172 doNothing().when(authenticator).nativeSetResult(anyLong(), anyInt(), any String());
173
174 Robolectric.buildActivity(Activity.class).create().start().resume().visi ble();
175
176 // Call getNextAuthToken to get the callback
177 authenticator.getNextAuthToken(1234, "test_principal", "", true);
178
179 // Avoid warning when creating mock accountManagerFuture, can't take .cl ass of an
180 // instantiated generic type, yet compiler complains if I leave it unins tantiated.
181 @SuppressWarnings("unchecked")
182 AccountManagerFuture<Bundle> accountManagerFuture = mock(AccountManagerF uture.class);
183 Bundle resultBundle = new Bundle();
184 if (spnegoError != null) {
185 resultBundle.putInt(HttpNegotiateConstants.KEY_SPNEGO_RESULT, spnego Error);
186 }
187 try {
188 when(accountManagerFuture.getResult()).thenReturn(resultBundle);
189 } catch (OperationCanceledException | AuthenticatorException | IOExcepti on e) {
190 // Can never happen - artifact of Mockito.
191 fail();
192 }
193 sCallbackReceived.run(accountManagerFuture);
194 verify(authenticator).nativeSetResult(anyLong(), eq(expectedError), anyS tring());
195 }
196
197 /**
198 * Test of callback error returns when getting the auth token completes.
199 */
200 @Test
201 public void testAccountManagerCallbackErrorReturns() {
202 checkErrorReturn(null, NetError.ERR_UNEXPECTED);
203 checkErrorReturn(HttpNegotiateConstants.ERR_UNEXPECTED, NetError.ERR_UNE XPECTED);
204 checkErrorReturn(HttpNegotiateConstants.ERR_ABORTED, NetError.ERR_ABORTE D);
205 checkErrorReturn(HttpNegotiateConstants.ERR_UNEXPECTED_SECURITY_LIBRARY_ STATUS,
206 NetError.ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS);
207 checkErrorReturn(
208 HttpNegotiateConstants.ERR_INVALID_RESPONSE, NetError.ERR_INVALI D_RESPONSE);
209 checkErrorReturn(HttpNegotiateConstants.ERR_INVALID_AUTH_CREDENTIALS,
210 NetError.ERR_INVALID_AUTH_CREDENTIALS);
211 checkErrorReturn(HttpNegotiateConstants.ERR_UNSUPPORTED_AUTH_SCHEME,
212 NetError.ERR_UNSUPPORTED_AUTH_SCHEME);
213 checkErrorReturn(HttpNegotiateConstants.ERR_MISSING_AUTH_CREDENTIALS,
214 NetError.ERR_MISSING_AUTH_CREDENTIALS);
215 checkErrorReturn(HttpNegotiateConstants.ERR_UNDOCUMENTED_SECURITY_LIBRAR Y_STATUS,
216 NetError.ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS);
217 checkErrorReturn(
218 HttpNegotiateConstants.ERR_MALFORMED_IDENTITY, NetError.ERR_MALF ORMED_IDENTITY);
219 // 9999 is not a valid return value
220 checkErrorReturn(9999, NetError.ERR_UNEXPECTED);
221 }
222 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698