Chromium Code Reviews| OLD | NEW |
|---|---|
| (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.mock; | |
| 17 import static org.mockito.Mockito.spy; | |
| 18 import static org.mockito.Mockito.verify; | |
| 19 import static org.mockito.Mockito.when; | |
| 20 | |
| 21 import android.accounts.AccountManager; | |
| 22 import android.accounts.AccountManagerCallback; | |
| 23 import android.accounts.AccountManagerFuture; | |
| 24 import android.accounts.AuthenticatorException; | |
| 25 import android.accounts.OperationCanceledException; | |
| 26 import android.app.Activity; | |
| 27 import android.os.Bundle; | |
| 28 import android.os.Handler; | |
| 29 | |
| 30 import org.chromium.base.BaseChromiumApplication; | |
| 31 import org.chromium.testing.local.LocalRobolectricTestRunner; | |
| 32 import org.junit.Test; | |
| 33 import org.junit.runner.RunWith; | |
| 34 import org.robolectric.Robolectric; | |
| 35 import org.robolectric.annotation.Config; | |
| 36 import org.robolectric.annotation.Implementation; | |
| 37 import org.robolectric.annotation.Implements; | |
| 38 import org.robolectric.shadows.ShadowAccountManager; | |
| 39 | |
| 40 import java.io.IOException; | |
| 41 | |
| 42 /** | |
| 43 * Robolectic tests for HttpNegotiateAuthenticator | |
|
cbentzel
2015/06/30 12:53:55
Nit: Robolectric
aberent
2015/07/02 21:13:35
Done.
| |
| 44 */ | |
| 45 @RunWith(LocalRobolectricTestRunner.class) | |
| 46 @Config(manifest = Config.NONE, | |
| 47 shadows = HttpNegotiateAuthenticatorTest.ExtendedShadowAccountManager.cl ass, | |
| 48 application = BaseChromiumApplication.class) | |
| 49 public class HttpNegotiateAuthenticatorTest { | |
| 50 static final String KEY_INCOMING_AUTH_TOKEN = "incomingAuthToken"; | |
| 51 static final String KEY_SPNEGO_CONTEXT = "spnegoContext"; | |
| 52 static final String KEY_CAN_DELEGATE = "canDelegate"; | |
| 53 | |
| 54 static final String SPNEGO_FEATURE = "SPNEGO"; | |
| 55 static final String SPNEGO_TOKEN_TYPE_BASE = "SPNEGO:HOSTBASED:"; | |
| 56 | |
| 57 static int sCallCount = 0; | |
| 58 static String sAccountTypeReceived; | |
| 59 static String sAuthTokenTypeReceived; | |
| 60 static String sFeaturesReceived[]; | |
| 61 static Bundle sAddAccountOptionsReceived; | |
| 62 static Bundle sAuthTokenOptionsReceived; | |
| 63 static AccountManagerCallback<Bundle> sCallbackReceived; | |
| 64 static Handler sHandlerReceived; | |
| 65 | |
| 66 /** | |
| 67 * Robolectic's ShadowAccountManager doesn't implement getAccountsByTypeAndF eature so extend it. | |
| 68 * We simply check the call is correct, and don't try to emulate it | |
| 69 * Note: Shadow classes need to be public and static. | |
| 70 */ | |
| 71 @Implements(AccountManager.class) | |
| 72 public static class ExtendedShadowAccountManager extends ShadowAccountManage r { | |
| 73 @Implementation | |
| 74 public AccountManagerFuture<Bundle> getAuthTokenByFeatures(String accoun tType, | |
| 75 String authTokenType, String[] features, Activity activity, | |
| 76 Bundle addAccountOptions, Bundle getAuthTokenOptions, | |
| 77 AccountManagerCallback<Bundle> callback, Handler handler) { | |
| 78 sCallCount++; | |
| 79 sAccountTypeReceived = accountType; | |
| 80 sAuthTokenTypeReceived = authTokenType; | |
| 81 sFeaturesReceived = features; | |
| 82 sAddAccountOptionsReceived = addAccountOptions; | |
| 83 sAuthTokenOptionsReceived = getAuthTokenOptions; | |
| 84 sCallbackReceived = callback; | |
| 85 sHandlerReceived = handler; | |
| 86 | |
| 87 return null; | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 /** | |
| 92 * Test of {@link HttpNegotiateAuthenticator#getNextAuthToken} | |
| 93 */ | |
| 94 @Test | |
| 95 public void testGetNextAuthToken() { | |
| 96 HttpNegotiateAuthenticator authenticator = | |
| 97 HttpNegotiateAuthenticator.create("Dummy_Account"); | |
| 98 Robolectric.buildActivity(Activity.class).create().start().resume().visi ble(); | |
| 99 authenticator.getNextAuthToken(0, "test_principal", "", true); | |
| 100 assertThat("getAuthTokenByFeatures called precisely once", sCallCount, e qualTo(1)); | |
| 101 assertThat("Received account type matches input", sAccountTypeReceived, | |
| 102 equalTo("Dummy_Account")); | |
| 103 assertThat("AuthTokenType is \"SPNEGO:HOSTBASED:test_principal\"", sAuth TokenTypeReceived, | |
| 104 equalTo("SPNEGO:HOSTBASED:test_principal")); | |
| 105 assertThat("Features are precisely {\"SPNEGO\"}", sFeaturesReceived, | |
| 106 equalTo(new String[] {"SPNEGO"})); | |
| 107 assertThat("No account options requested", sAddAccountOptionsReceived, n ullValue()); | |
| 108 assertThat("There is no existing context", | |
| 109 sAuthTokenOptionsReceived.get(KEY_SPNEGO_CONTEXT), nullValue()); | |
| 110 assertThat("The existing token is empty", | |
| 111 sAuthTokenOptionsReceived.getString(KEY_INCOMING_AUTH_TOKEN), eq ualTo("")); | |
| 112 assertThat("Delegation is allowed", sAuthTokenOptionsReceived.getBoolean (KEY_CAN_DELEGATE), | |
| 113 equalTo(true)); | |
| 114 assertThat("getAuthTokenByFeatures was called with a callback", sCallbac kReceived, | |
| 115 notNullValue()); | |
| 116 assertThat("getAuthTokenByFeatures was called with a handler", sHandlerR eceived, | |
| 117 notNullValue()); | |
| 118 } | |
| 119 | |
| 120 /** | |
| 121 * Test of callback called when getting the auth token completes. | |
| 122 */ | |
| 123 @Test | |
| 124 public void testAccountManagerCallbackRun() { | |
| 125 // Spy on the authenticator so that we can override and intercept the na tive method call. | |
| 126 HttpNegotiateAuthenticator authenticator = | |
| 127 spy(HttpNegotiateAuthenticator.create("Dummy_Account")); | |
| 128 doNothing().when(authenticator).nativeSetResult(anyLong(), anyInt(), any String()); | |
| 129 | |
| 130 Robolectric.buildActivity(Activity.class).create().start().resume().visi ble(); | |
| 131 | |
| 132 // Call getNextAuthToken to get the callback | |
| 133 authenticator.getNextAuthToken(1234, "test_principal", "", true); | |
| 134 | |
| 135 // Avoid warning when creating mock accountManagerFuture, can't take .cl ass of an | |
| 136 // instantiated generic type, yet compiler complains if I leave it unins tantiated. | |
| 137 @SuppressWarnings("unchecked") | |
| 138 AccountManagerFuture<Bundle> accountManagerFuture = mock(AccountManagerF uture.class); | |
| 139 Bundle resultBundle = new Bundle(); | |
| 140 Bundle context = new Bundle(); | |
| 141 context.putString("String", "test_context"); | |
| 142 resultBundle.putBundle(KEY_SPNEGO_CONTEXT, context); | |
| 143 resultBundle.putString(AccountManager.KEY_AUTHTOKEN, "output_token"); | |
| 144 try { | |
| 145 when(accountManagerFuture.getResult()).thenReturn(resultBundle); | |
| 146 } catch (OperationCanceledException | AuthenticatorException | IOExcepti on e) { | |
| 147 // Can never happen - artifact of Mockito. | |
| 148 fail(); | |
| 149 } | |
| 150 sCallbackReceived.run(accountManagerFuture); | |
| 151 verify(authenticator).nativeSetResult(1234, 0, "output_token"); | |
| 152 | |
| 153 // Check that the next call to getNextAuthToken uses the correct context | |
| 154 authenticator.getNextAuthToken(5678, "test_principal", "", true); | |
| 155 assertThat("The spnego context is preserved between calls", | |
| 156 sAuthTokenOptionsReceived.getBundle(KEY_SPNEGO_CONTEXT), equalTo (context)); | |
| 157 | |
| 158 // Test exception path | |
|
cbentzel
2015/06/30 12:53:55
Should you also test the non-ABORTED error cases?
aberent
2015/07/02 21:13:35
Done.
| |
| 159 try { | |
| 160 when(accountManagerFuture.getResult()).thenThrow(new OperationCancel edException()); | |
| 161 } catch (OperationCanceledException | AuthenticatorException | IOExcepti on e) { | |
| 162 // Can never happen - artifact of Mockito. | |
| 163 fail(); | |
| 164 } | |
| 165 sCallbackReceived.run(accountManagerFuture); | |
| 166 verify(authenticator).nativeSetResult(5678, NetError.ERR_ABORTED, null); | |
| 167 } | |
| 168 } | |
| OLD | NEW |