/*
* Copyright 2014-2016 CyberVision, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kaaproject.kaa.server.verifiers.twitter.verifier;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.BeforeClass;
import org.junit.Test;
import org.kaaproject.kaa.server.common.verifier.UserVerifierCallback;
import org.kaaproject.kaa.server.verifiers.twitter.config.gen.TwitterAvroConfig;
import org.mockito.Mockito;
import org.springframework.test.util.ReflectionTestUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class TwitterUserVerifierTest extends TwitterUserVerifier {
private static final String INVALID_TOKEN_CODE = "89";
private static TwitterUserVerifier verifier;
private static TwitterAvroConfig config;
@BeforeClass
public static void setUp() {
config = mock(TwitterAvroConfig.class);
when(config.getMaxParallelConnections()).thenReturn(5);
}
@Test
public void successfulVerificationTest() {
String userId = "12456789123456";
verifier = new MyTwitterVerifier(200, "{" +
" \"contributors_enabled\": true," +
" \"geo_enabled\": true," +
" \"id\": 38895958," +
" \"id_str\": \"" + userId + "\"," +
" \"is_translator\": false," +
" \"lang\": \"en\"," +
" \"name\": \"Sean Cook\"}");
verifier.init(null, config);
verifier.start();
UserVerifierCallback callback = mock(UserVerifierCallback.class);
verifier.checkAccessToken(userId, "someToken someSecret", callback);
verify(callback, Mockito.timeout(1000).atLeastOnce()).onSuccess();
verifier.stop();
}
@Test
public void incompatibleUserIdsTest() {
String invalidUserId = "12456789123456";
verifier = new MyTwitterVerifier(200, "{" +
" \"contributors_enabled\": true," +
" \"geo_enabled\": true," +
" \"id\": 38895958," +
" \"id_str\": \"123456\"," +
" \"is_translator\": false," +
" \"lang\": \"en\"," +
" \"name\": \"Sean Cook\"}");
verifier.init(null, config);
verifier.start();
UserVerifierCallback callback = mock(UserVerifierCallback.class);
verifier.checkAccessToken(invalidUserId, "someToken someSecret", callback);
verify(callback, Mockito.timeout(1000).atLeastOnce()).onVerificationFailure(anyString());
verifier.stop();
}
@Test
public void invalidUserAccessTokenTest() {
verifier = new MyTwitterVerifier(400, "{\"errors\":[{\"message\":\"Sorry," +
" that page does not exist\",\"code\": " + INVALID_TOKEN_CODE + "}]}");
verifier.init(null, config);
verifier.start();
UserVerifierCallback callback = mock(UserVerifierCallback.class);
verifier.checkAccessToken("invalidUserId", "someToken someSecret", callback);
verify(callback, Mockito.timeout(1000).atLeastOnce()).onTokenInvalid();
}
@Test
public void otherResponseCodeTest() {
verifier = new MyTwitterVerifier(406, "{}");
verifier.init(null, config);
verifier.start();
UserVerifierCallback callback = mock(UserVerifierCallback.class);
verifier.checkAccessToken("invalidUserId", "someToken someSecret", callback);
// no exception is thrown, if onVerificationFailure(String) was called
verify(callback, Mockito.timeout(1000).atLeastOnce()).onVerificationFailure(anyString());
verifier.stop();
}
@Test
public void badResponseWithOtherErrorCodeTest() {
String otherErrorCode = "215";
verifier = new MyTwitterVerifier(400, "{\"errors\":[{\"message\":\"Sorry," +
" that page does not exist\",\"code\": " + otherErrorCode + "}]}");
verifier.init(null, config);
verifier.start();
UserVerifierCallback callback = mock(UserVerifierCallback.class);
verifier.checkAccessToken("invalidUserId", "someToken someSecret", callback);
verify(callback, Mockito.timeout(1000).atLeastOnce()).onVerificationFailure(any(String.class));
}
@Test
public void connectionErrorTest() throws IOException {
verifier = new TwitterUserVerifier();
verifier.init(null, config);
verifier.start();
CloseableHttpClient httpClientMock = mock(CloseableHttpClient.class);
doThrow(new IOException()).when(httpClientMock).execute(any(HttpHost.class), any(HttpRequest.class));
ReflectionTestUtils.setField(verifier, "httpClient", httpClientMock);
UserVerifierCallback callback = mock(UserVerifierCallback.class);
verifier.checkAccessToken("id", "token secret", callback);
Mockito.verify(callback, Mockito.timeout(1000)).onConnectionError(any(String.class));
}
@Test
public void internalErrorTest() throws IOException {
verifier = new TwitterUserVerifier();
verifier.init(null, config);
verifier.start();
CloseableHttpClient httpClientMock = mock(CloseableHttpClient.class);
// Throw any descendant of Exception, as the indicator of an internal error
doThrow(new NullPointerException()).when(httpClientMock).execute(any(HttpGet.class));
ReflectionTestUtils.setField(verifier, "httpClient", httpClientMock);
UserVerifierCallback callback = mock(UserVerifierCallback.class);
verifier.checkAccessToken("id", "token secret", callback);
Mockito.verify(callback, Mockito.timeout(1000)).onInternalError(any(String.class));
}
private static class MyTwitterVerifier extends TwitterUserVerifier {
int responseCode;
String inputStreamString = "";
MyTwitterVerifier(int responseCode, String intputStreamString) {
this.responseCode = responseCode;
this.inputStreamString = intputStreamString;
}
@Override
protected CloseableHttpResponse establishConnection(String accessToken) {
CloseableHttpResponse connection = mock(CloseableHttpResponse.class);
try {
StatusLine statusLine = mock(StatusLine.class);
when(statusLine.getStatusCode()).thenReturn(responseCode);
HttpEntity httpEntity = mock(HttpEntity.class);
when(httpEntity.getContent()).thenReturn(new ByteArrayInputStream(inputStreamString.
getBytes(StandardCharsets.UTF_8)));
when(connection.getStatusLine()).thenReturn(statusLine);
when(connection.getEntity()).thenReturn(httpEntity);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
}
}