/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.android.sync.net.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URISyntaxException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mozilla.android.sync.test.helpers.HTTPServerTestHelper;
import org.mozilla.android.sync.test.helpers.MockServer;
import org.mozilla.android.sync.test.helpers.WaitHelper;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.setup.auth.AuthenticateAccountStage;
import org.mozilla.gecko.sync.setup.auth.AuthenticateAccountStage.AuthenticateAccountStageDelegate;
import org.simpleframework.http.Request;
import org.simpleframework.http.Response;
import ch.boye.httpclientandroidlib.HttpResponse;
/**
* Tests the authentication request stage of manual Account setup.
* @author liuche
*
*/
public class TestAccountAuthenticatorStage {
private static final int TEST_PORT = HTTPServerTestHelper.getTestPort();
private static final String TEST_SERVER = "http://localhost:" + TEST_PORT;
private static final String USERNAME = "john-hashed";
private static final String PASSWORD = "password";
private MockServer authServer;
private HTTPServerTestHelper serverHelper = new HTTPServerTestHelper();
private AuthenticateAccountStage authStage = new AuthenticateAccountStage();
private AuthenticateAccountStageDelegate testCallback;
@Before
public void setup() {
// Make mock server to check authentication header.
authServer = new MockServer() {
@Override
protected void handle(Request request, Response response, int code, String body) {
try {
final int c;
String responseAuth = request.getValue("Authorization");
// Trim whitespace, HttpResponse has an extra space?
if (expectedBasicAuthHeader.equals(responseAuth.trim())) {
c = 200;
} else {
c = 401;
}
Logger.debug(LOG_TAG, "Handling request...");
PrintStream bodyStream = this.handleBasicHeaders(request, response, c, "application/json");
bodyStream.println(body);
bodyStream.close();
} catch (IOException e) {
Logger.error(LOG_TAG, "Oops.", e);
}
}
};
authServer.expectedBasicAuthHeader = authStage.makeAuthHeader(USERNAME, PASSWORD);
// Authentication delegate to handle HTTP responses.
testCallback = new AuthenticateAccountStageDelegate() {
protected int numFailedTries = 0;
@Override
public void handleSuccess(boolean isSuccess) {
if (isSuccess) {
// Succeed on retry (after failing first attempt).
assertEquals(1, numFailedTries);
testWaiter().performNotify();
} else {
numFailedTries++;
// Fail only once.
if (numFailedTries != 1) {
testWaiter().performNotify(new Exception("Failed on retry."));
return;
}
String authHeader = authStage.makeAuthHeader(USERNAME, PASSWORD);
try {
authStage.authenticateAccount(testCallback, TEST_SERVER, authHeader);
} catch (URISyntaxException e) {
fail("Malformed URI.");
}
}
}
@Override
public void handleFailure(HttpResponse response) {
fail("Unexpected response " + response.getStatusLine().getStatusCode());
}
@Override
public void handleError(Exception e) {
fail("Unexpected error during authentication.");
}
};
assertTrue(testWaiter().isIdle());
}
@After
public void cleanup() {
serverHelper.stopHTTPServer();
assertTrue(testWaiter().isIdle());
}
@Test
public void testAuthenticationRetry() {
serverHelper.startHTTPServer(authServer);
testWaiter().performWait(new Runnable() {
@Override
public void run() {
// Try auth request with incorrect password. We want to fail the first time.
String authHeader = authStage.makeAuthHeader(USERNAME, "wrong-password");
try {
authStage.authenticateAccount(testCallback, TEST_SERVER, authHeader);
} catch (URISyntaxException e) {
fail("Malformed URI.");
}
}
});
}
protected static WaitHelper testWaiter() {
return WaitHelper.getTestWaiter();
}
}