package com.samknows.tests;
import android.os.ConditionVariable;
import android.support.annotation.NonNull;
import org.robolectric.RobolectricTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.samknows.XCT;
import com.samknows.libcore.SKPorting;
import com.samknows.measurement.TestRunner.SKTestRunner;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.samknows.tests.DownloadTest.*;
@RunWith(RobolectricTestRunner.class)
public class DownloadTestTests {
final long cMicrosecondInNanoSeconds = 1000;
final long cMillisecondInNanoSeconds = cMicrosecondInNanoSeconds * 1000;
final long cSecondInNanoSeconds = cMillisecondInNanoSeconds * 1000;
final long cTenthOfASecondInNanoSeconds = cSecondInNanoSeconds / 10;
@org.junit.Before
public void setUp() throws Exception {
}
@org.junit.After
public void tearDown() throws Exception {
// https://github.com/robolectric/robolectric/issues/1890
// "Robolectric testing has been designed on the assumption that no state is preserved
// between tests & you're always starting from scratch.
// Singletons & other static state maintained by your
// application and/or test can break that assumption"
SKTestRunner.sSetRunningTestRunner(null);
}
final String cFakeIpAddress = "127.0.0.1";
public class MyMockInputStream extends InputStream {
int mBlockSize = 0;
MyMockInputStream(int blockSize) {
mBlockSize = blockSize;
}
@Override
public int available() throws IOException {
return mBlockSize;
}
final String header = "HTTP/1.1 200 OK\n\n\n";
final byte[] headerBytes = header.getBytes();
// boolean bReadHeader = false;
@Override
public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException {
// We need to return THIS to start...
// then anything!
Arrays.fill(buffer, (byte) 0);
// if (bReadHeader == false) {
// bReadHeader = true;
SKPorting.sAssert(headerBytes.length <= byteCount);
System.arraycopy(headerBytes, 0, buffer, byteOffset, headerBytes.length);
// }
return byteCount;
// int bytesLeftToCopy = byteCount;
// while (bytesLeftToCopy > 0) {
// int bytesThisTime = Math.min(bytesLeftToCopy, headerBytes.length);
// System.arraycopy(headerBytes, 0, buffer, byteOffset, bytesThisTime);
// byteOffset += bytesThisTime;
// bytesLeftToCopy -= bytesThisTime;
// }
// return byteCount;
}
@Override
public int read() throws IOException {
// We keep this running for ever!
// Just return one byte with zero!
return 0;
}
}
public class MockSKSocket implements ISKHttpSocket {
public int mOpenCalledCount = 0;
public int mSetTcpNoDelayCalledCount = 0;
public int mSetReceiveBufferSizeCount = 0;
public int mSetSendBufferSizeCount = 0;
public int mSetSoTimeoutCalledCount = 0;
public int mConnectCalledCount = 0;
public int mGetInputStreamCalledCount = 0;
public int mGetOutputStreamCalledCount = 0;
public int mCloseCalledCount = 0;
private int mReceiveBufferSize = 512;
private int mSendBufferSize = 512;
static final String cDummyIpAddress = "127.0.0.1";
private ByteArrayOutputStream outputStream;
@Override
public void open() {
mOpenCalledCount++;
}
@Override
public void setTcpNoDelay(boolean on) throws SocketException {
mSetTcpNoDelayCalledCount++;
}
@Override
public void setReceiveBufferSize(int size) throws SocketException {
mSetReceiveBufferSizeCount++;
mReceiveBufferSize = size;
}
@Override
public int getReceiveBufferSize() throws SocketException {
return mReceiveBufferSize;
}
@Override
public void setSendBufferSize(int size) throws SocketException {
mSetSendBufferSizeCount++;
mSendBufferSize = size;
}
@Override
public int getSendBufferSize() throws SocketException {
return mSendBufferSize;
}
@Override
public void setSoTimeout(int timeout) throws SocketException {
mSetSoTimeoutCalledCount++;
}
@Override
public String connect(String target, int port, int timeout) throws IOException {
mConnectCalledCount++;
return cDummyIpAddress;
}
@Override
public InputStream getInputStream() throws IOException {
mGetInputStreamCalledCount++;
// byte[] buf = new byte[]();
// ByteArrayInputStream stubInputStream = new ByteArrayInputStream(buf);
//InputStream stubInputStream = IOUtils.toInputStream("HTTP/1.1 200 OK\n");
InputStream stubInputStream = new MyMockInputStream(512);
return stubInputStream;
}
@Override
public OutputStream getOutputStream() throws IOException {
mGetOutputStreamCalledCount++;
outputStream = new ByteArrayOutputStream();
return outputStream;
}
@Override
public void close() {
mCloseCalledCount++;
}
}
public DownloadTestTests() {
}
static final String cLiveServer = "all-the1.samknows.com";
static final String cLivePort = "80";
static final String mFile = "1000MB.bin";
static final Double mWarmupMaxTimeSeconds = 2.0;
static final Double mTransferMaxTimeSeconds = 10.0;
static final Integer mNumberOfThreads = 1;
static final Integer mBufferSizeBytes = 1048576;
private static DownloadTest sCreateDownloadTest() {
List<Param> params = new ArrayList<>();
params.add(new Param(SKAbstractBaseTest.PORT, cLivePort));
params.add(new Param(SKAbstractBaseTest.TARGET, cLiveServer));
params.add(new Param(SKAbstractBaseTest.FILE, mFile));
params.add(new Param(HttpTest.WARMUPMAXTIME, String.valueOf((int) (mWarmupMaxTimeSeconds * 1000000.0)))); // Microseconds!
params.add(new Param(HttpTest.TRANSFERMAXTIME, String.valueOf((int) (mTransferMaxTimeSeconds * 1000000.0)))); // Microseconds
params.add(new Param(HttpTest.NTHREADS, String.valueOf(mNumberOfThreads)));
params.add(new Param(HttpTest.BUFFERSIZE, String.valueOf(mBufferSizeBytes)));
DownloadTest theTest = DownloadTest.sCreateDownloadTest(params);
return theTest;
}
// Try a MOCK test. This is proving problematic, as the response required isn't a simple one.
/*
@Test
public void testDownloadTest() throws Exception{
final boolean[] responseCalled = {false};
final ConditionVariable cv = new ConditionVariable();
final DownloadTest downloadTest = sCreateDownloadTest();
final MockSKSocket mockSocket = new MockSKSocket();
// Set dummy SKTestRunner instance, or the tests will give lots of assertions...
SKTestRunner.sSetRunningTestRunner(new SKTestRunner());
Thread thread = new Thread() {
@Override
public void run() {
// We should now be able to test the test has worked as expected.
downloadTest.runBlockingTestToFinishInThisThread(new ISKHttpSocketFactory() {
@Override
public ISKHttpSocket newSocket() {
return mockSocket;
}
});
responseCalled[0] = true;
cv.open();
}
};
thread.start();
cv.block(20000);
// And verify results!
XCT.Assert(responseCalled[0] == true);
XCT.Assert(downloadTest.isSuccessful() == true);
XCT.Assert(downloadTest.getTransferBytesPerSecond() > 0);
XCT.Assert(mockSocket.mOpenCalledCount == 1); // Depends on nThreads
XCT.Assert(mockSocket.mSetTcpNoDelayCalledCount > 0);
XCT.Assert(mockSocket.mSetReceiveBufferSizeCount > 0);
XCT.Assert(mockSocket.mSetSendBufferSizeCount > 0);
XCT.Assert(mockSocket.mSetSoTimeoutCalledCount > 0);
XCT.Assert(mockSocket.mConnectCalledCount > 0);
XCT.Assert(mockSocket.mGetInputStreamCalledCount == 1); // Depends on nThreads
XCT.Assert(mockSocket.mGetOutputStreamCalledCount == 0);
XCT.Assert(mockSocket.mCloseCalledCount == 1); // Depends on nThreads
XCT.Assert(mockSocket.mReceiveBufferSize == 512);
XCT.Assert(mockSocket.mSendBufferSize == 512);
}
*/
// Include a LIVE test, to verify that basic behaviour of the non-mocked system is still fundamentally OK.
// This is less able to make specific assertions.
@Test
public void testDownloadTest_Live() throws Exception{
final boolean[] responseCalled = {false};
final ConditionVariable cv = new ConditionVariable();
final DownloadTest downloadTest = sCreateDownloadTest();
// Set dummy SKTestRunner instance, or the tests will give lots of assertions...
SKTestRunner.sSetRunningTestRunner(new SKTestRunner());
Thread thread = new Thread() {
@Override
public void run() {
// We should now be able to test the test has worked as expected.
downloadTest.runBlockingTestToFinishInThisThread();
responseCalled[0] = true;
cv.open();
}
};
thread.start();
cv.block(20000);
// And verify results!
XCT.Assert(responseCalled[0] == true);
XCT.Assert(downloadTest.isSuccessful() == true);
XCT.Assert(downloadTest.getTransferBytesPerSecond() > 0);
}
}