blob: bfb5a7b58981e2bb9471ae581a5c110c9f3e2901 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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 com.android.tradefed.util.net;
import static org.mockito.Mockito.doNothing;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.MultiMap;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.StreamUtil;
import com.android.tradefed.util.net.IHttpHelper.DataSizeException;
import junit.framework.TestCase;
import org.mockito.Mockito;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Unit tests for {@link HttpHelper}.
*/
public class HttpHelperTest extends TestCase {
private static final String TEST_URL_STRING = "http://foo";
private static final String TEST_POST_DATA = "this is post data";
private static final String TEST_DATA = "this is test data";
private TestHttpHelper mHelper;
/**
* {@inheritDoc}
*/
@Override
protected void setUp() throws Exception {
super.setUp();
mHelper = new TestHttpHelper();
}
/**
* {@inheritDoc}
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
mHelper.close();
}
/**
* Test {@link HttpHelper#buildParameters(MultiMap)}.
*/
public void testBuildParams() {
MultiMap<String, String> paramMap = new MultiMap<String, String>();
paramMap.put("key", "value");
assertEquals("key=value", mHelper.buildParameters(paramMap));
paramMap.clear();
paramMap.put("key1", "value1");
paramMap.put("key2", "value2");
String params = mHelper.buildParameters(paramMap);
assertTrue(params.contains("key1=value1"));
assertTrue(params.contains("key2=value2"));
assertTrue(params.contains("&"));
paramMap.clear();
paramMap.put("key", "value1");
paramMap.put("key", "value2");
assertEquals("key=value1&key=value2", mHelper.buildParameters(paramMap));
paramMap.clear();
paramMap.put("key+f?o=o;", "value");
assertEquals("key%2Bf%3Fo%3Do%3B=value", mHelper.buildParameters(paramMap));
}
/**
* Test {@link HttpHelper#buildUrl(String, MultiMap)} with simple parameters.
*/
public void testBuildUrl() {
assertEquals("http://foo", mHelper.buildUrl(TEST_URL_STRING, null));
MultiMap<String, String> paramMap = new MultiMap<String, String>();
assertEquals("http://foo", mHelper.buildUrl(TEST_URL_STRING, paramMap));
paramMap.put("key", "value");
assertEquals("http://foo?key=value", mHelper.buildUrl(TEST_URL_STRING, paramMap));
}
/**
* Normal case test for {@link HttpHelper#doGet(String)}
*/
public void testDoGet() throws IOException, DataSizeException {
assertEquals(TEST_DATA, mHelper.doGet(TEST_URL_STRING));
}
/**
* Test that {@link HttpHelper#doGet(String)} throws {@link DataSizeException} when the
* remote stream returns too much data.
*/
public void testDoGet_datasize() throws IOException {
mHelper.close();
mHelper = new TestHttpHelper() {
@Override
InputStream getRemoteUrlStream(URL url) {
// test with 64K + 1
return new ByteArrayInputStream(new byte[IHttpHelper.MAX_DATA_SIZE + 1]);
}
};
try {
mHelper.doGet(TEST_URL_STRING);
fail("DataSizeException not thrown");
} catch (DataSizeException e) {
// expected
}
}
/**
* Normal case test for {@link HttpHelper#doGet(String, OutputStream)}
*/
public void testDoGetStream() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
mHelper.doGet(TEST_URL_STRING, out);
StreamUtil.flushAndCloseStream(out);
assertEquals(TEST_DATA, out.toString());
}
/**
* Normal case test for {@link HttpHelper#doGetWithRetry(String)}.
*/
public void testDoGetWithRetry() throws IOException, DataSizeException {
assertEquals(TEST_DATA, mHelper.doGetWithRetry(TEST_URL_STRING));
}
/**
* Test that {@link HttpHelper#doGetWithRetry(String)} throws a {@link DataSizeException} when
* the remote stream returns too much data.
*/
public void testDoGetWithRetry_datasize() throws IOException {
mHelper.close();
mHelper = new TestHttpHelper() {
@Override
InputStream getRemoteUrlStream(URL url) {
// test with 64K + 1
return new ByteArrayInputStream(new byte[IHttpHelper.MAX_DATA_SIZE + 1]);
}
};
try {
mHelper.doGetWithRetry(TEST_URL_STRING);
fail("DataSizeException not thrown");
} catch (DataSizeException e) {
// expected
}
}
/**
* Test that {@link HttpHelper#doGetWithRetry(String)} throws a {@link IOException} if an
* {@link IOException} is thrown on each attempt.
*/
public void testDoGetWithRetry_ioexception() throws DataSizeException {
mHelper.close();
mHelper = new TestHttpHelper() {
@Override
public String doGet(String url) throws IOException {
throw new IOException();
}
};
try {
mHelper.doGetWithRetry(TEST_URL_STRING);
fail("IOException not thrown");
} catch (IOException e) {
// expected
}
}
/**
* Test that {@link HttpHelper#doGetWithRetry(String)} returns data if an {@link IOException} is
* thrown on the first attempt, but is fine on the second attempt.
*/
public void testDoGetWithRetry_retry() throws IOException, DataSizeException {
mHelper.close();
RunUtil mockRunUtil = Mockito.spy(RunUtil.class);
mHelper =
new TestHttpHelper() {
boolean mExceptionThrown = false;
@Override
public IRunUtil getRunUtil() {
return mockRunUtil;
}
@Override
public String doGet(String url) throws IOException, DataSizeException {
if (!mExceptionThrown) {
mExceptionThrown = true;
throw new IOException();
}
return super.doGet(url);
}
};
mHelper.setMaxTime(5000);
// Avoid doing actual sleep in the retry
doNothing().when(mockRunUtil).sleep(Mockito.anyLong());
assertEquals(TEST_DATA, mHelper.doGetWithRetry(TEST_URL_STRING));
}
/**
* Normal case test for {@link HttpHelper#doPostWithRetry(String, String)}.
*/
public void testDoPostWithRetry() throws IOException, DataSizeException {
assertEquals(TEST_DATA, mHelper.doPostWithRetry(TEST_URL_STRING, TEST_POST_DATA));
assertEquals(TEST_POST_DATA, mHelper.getOutputStream().toString());
}
/**
* Test that {@link HttpHelper#doPostWithRetry(String, String)} throws a
* {@link DataSizeException} when the remote stream returns too much data.
*/
public void testDoPostWithRetry_datasize() throws IOException {
mHelper.close();
mHelper = new TestHttpHelper() {
@Override
InputStream getConnectionInputStream(HttpURLConnection conn) {
// test with 64K + 1
return new ByteArrayInputStream(new byte[IHttpHelper.MAX_DATA_SIZE + 1]);
}
};
try {
mHelper.doPostWithRetry(TEST_URL_STRING, TEST_POST_DATA);
fail("DataSizeException not thrown");
} catch (DataSizeException e) {
// expected
}
}
/**
* Test that {@link HttpHelper#doPostWithRetry(String, String)} throws a {@link IOException} if
* an {@link IOException} is thrown on each attempt.
*/
public void testDoPostWithRetry_ioexception() throws DataSizeException {
mHelper.close();
mHelper = new TestHttpHelper() {
@Override
public HttpURLConnection createConnection(URL url, String method, String contentType)
throws IOException {
throw new IOException();
}
};
try {
mHelper.doPostWithRetry(TEST_URL_STRING, TEST_POST_DATA);
fail("IOException not thrown");
} catch (IOException e) {
// expected
}
}
/**
* Test that {@link HttpHelper#doPostWithRetry(String, String)} returns data if an
* {@link IOException} is thrown on the first attempt, but is fine on the second attempt.
*/
public void testDoPostWithRetry_retry() throws IOException, DataSizeException {
mHelper.close();
mHelper = new TestHttpHelper() {
boolean mExceptionThrown = false;
@Override
public HttpURLConnection createConnection(URL url, String method, String contentType)
throws IOException {
if (!mExceptionThrown) {
mExceptionThrown = true;
throw new IOException();
}
return super.createConnection(url, method, contentType);
}
};
assertEquals(TEST_DATA, mHelper.doPostWithRetry(TEST_URL_STRING, TEST_POST_DATA));
assertEquals(TEST_POST_DATA, mHelper.getOutputStream().toString());
}
/**
* A class which extends {@link HttpHelper} for testing without using the network.
*/
private class TestHttpHelper extends HttpHelper {
InputStream mInputStream = new ByteArrayInputStream(TEST_DATA.getBytes());
OutputStream mOutputStream = new ByteArrayOutputStream();
/**
* Create a {@link TestHttpHelper}
*/
public TestHttpHelper() {
// Override all the polling related values to make this unit test run as fast as
// possible while still delivering consistent results.
setOpTimeout(300);
setInitialPollInterval(10);
setMaxPollInterval(50);
setMaxTime(50);
}
/**
* Close any open streams.
*/
public void close() {
StreamUtil.close(mInputStream);
StreamUtil.close(mOutputStream);
}
/**
* Get the output stream used in {@link #doPostWithRetry(String, String)}.
*/
public OutputStream getOutputStream() {
return mOutputStream;
}
/**
* {@inheritDoc}
*/
@Override
InputStream getRemoteUrlStream(URL url) {
return mInputStream;
}
/**
* {@inheritDoc}
*/
@Override
public HttpURLConnection createConnection(URL url, String method, String contentType)
throws IOException {
return null;
}
/**
* {@inheritDoc}
*/
@Override
InputStream getConnectionInputStream(HttpURLConnection conn) throws IOException {
return mInputStream;
}
/**
* {@inheritDoc}
*/
@Override
OutputStream getConnectionOutputStream(HttpURLConnection conn) throws IOException {
return mOutputStream;
}
}
}