package net.sf.openrocket.communication;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import net.sf.openrocket.util.BuildProperties;
import net.sf.openrocket.util.ComparablePair;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.junit.Test;
public class UpdateInfoTest extends BaseTestCase {
/** The connection delay */
private static final int DELAY = 100;
/** How much long does the test allow it to take */
private static final int ALLOWANCE = 2000;
private HttpURLConnectionMock setup() {
HttpURLConnectionMock connection = new HttpURLConnectionMock();
Communicator.setConnectionSource(new ConnectionSourceStub(connection));
connection.setConnectionDelay(DELAY);
connection.setUseCaches(true);
connection.setContentType("text/plain");
return connection;
}
private void check(HttpURLConnectionMock connection) {
assertEquals(Communicator.UPDATE_INFO_URL + "?version=" + BuildProperties.getVersion(),
connection.getTrueUrl());
assertTrue(connection.getConnectTimeout() > 0);
assertEquals(BuildProperties.getVersion() + "+" + BuildProperties.getBuildSource(),
connection.getRequestProperty("X-OpenRocket-Version"));
assertNotNull(connection.getRequestProperty("X-OpenRocket-Country"));
assertNotNull(connection.getRequestProperty("X-OpenRocket-ID"));
assertNotNull(connection.getRequestProperty("X-OpenRocket-OS"));
assertNotNull(connection.getRequestProperty("X-OpenRocket-Java"));
assertTrue(connection.getInstanceFollowRedirects());
assertEquals("GET", connection.getRequestMethod());
assertFalse(connection.getUseCaches());
}
@Test
public void testUpdateAvailable() throws IOException {
HttpURLConnectionMock connection = setup();
connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
String content =
"Version: 6.6.6pre A \n" +
"Extra: information\n" +
"100:hundred\n" +
"50: m\u00e4 \n\n" +
"1: one\n" +
"-2: none";
connection.setContent(content);
UpdateInfoRetriever retriever = new UpdateInfoRetriever();
retriever.start();
// Info is null while processing
assertNull(retriever.getUpdateInfo());
waitfor(retriever);
assertFalse(connection.hasFailed());
UpdateInfo info = retriever.getUpdateInfo();
assertNotNull(info);
check(connection);
assertEquals("6.6.6pre A", info.getLatestVersion());
List<ComparablePair<Integer, String>> updates = info.getUpdates();
assertEquals(3, updates.size());
Collections.sort(updates);
assertEquals(1, (int) updates.get(0).getU());
assertEquals("one", updates.get(0).getV());
assertEquals(50, (int) updates.get(1).getU());
assertEquals("m\u00e4", updates.get(1).getV());
assertEquals(100, (int) updates.get(2).getU());
assertEquals("hundred", updates.get(2).getV());
}
@Test
public void testUpdateNotAvailable() throws IOException {
HttpURLConnectionMock connection = setup();
connection.setResponseCode(Communicator.UPDATE_INFO_NO_UPDATE_CODE);
String content =
"Version: 6.6.6pre A \n" +
"Extra: information\n" +
"100:hundred\n" +
"50: m\u00e4 \n\n" +
"1: one\n" +
"-2: none";
connection.setContent(content);
UpdateInfoRetriever retriever = new UpdateInfoRetriever();
retriever.start();
// Info is null while processing
assertNull(retriever.getUpdateInfo());
waitfor(retriever);
assertFalse(connection.hasFailed());
UpdateInfo info = retriever.getUpdateInfo();
assertNotNull(info);
check(connection);
assertEquals(BuildProperties.getVersion(), info.getLatestVersion());
assertEquals(0, info.getUpdates().size());
}
@Test
public void testInvalidResponses() {
HttpURLConnectionMock connection = setup();
connection.setResponseCode(404);
connection.setContent("Version: 1.2.3");
UpdateInfoRetriever retriever = new UpdateInfoRetriever();
retriever.start();
assertNull(retriever.getUpdateInfo());
waitfor(retriever);
assertFalse(connection.hasFailed());
assertNull(retriever.getUpdateInfo());
check(connection);
connection = setup();
connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
connection.setContentType("text/xml");
retriever = new UpdateInfoRetriever();
retriever.start();
assertNull(retriever.getUpdateInfo());
waitfor(retriever);
assertFalse(connection.hasFailed());
assertNull(retriever.getUpdateInfo());
check(connection);
connection = setup();
connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
String content =
"100:hundred\n" +
"50: m\u00e4 \n\n" +
"1: one\n";
connection.setContent(content);
retriever = new UpdateInfoRetriever();
retriever.start();
assertNull(retriever.getUpdateInfo());
waitfor(retriever);
assertFalse(connection.hasFailed());
assertNull(retriever.getUpdateInfo());
check(connection);
connection = setup();
connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
connection.setContent(new byte[0]);
retriever = new UpdateInfoRetriever();
retriever.start();
assertNull(retriever.getUpdateInfo());
waitfor(retriever);
assertFalse(connection.hasFailed());
assertNull(retriever.getUpdateInfo());
check(connection);
}
@Test
public void testRandomInputData() {
Random rnd = new Random();
for (int i = 0; i < 10; i++) {
int size = (int) ((1 + 0.3 * rnd.nextGaussian()) * Math.pow(i, 6));
byte[] buf = new byte[size];
rnd.nextBytes(buf);
HttpURLConnectionMock connection = setup();
connection.setResponseCode(Communicator.UPDATE_INFO_UPDATE_AVAILABLE);
connection.setContent(buf);
UpdateInfoRetriever retriever = new UpdateInfoRetriever();
retriever.start();
assertNull(retriever.getUpdateInfo());
waitfor(retriever);
assertFalse(connection.hasFailed());
assertNull(retriever.getUpdateInfo());
check(connection);
}
}
private void waitfor(UpdateInfoRetriever retriever) {
long t = System.currentTimeMillis();
while (retriever.isRunning()) {
if (System.currentTimeMillis() >= t + ALLOWANCE) {
fail("retriever took too long to respond");
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
//System.out.println("Waiting took " + (System.currentTimeMillis()-t) + " ms");
}
}