package org.ggp.base.apps.tiltyard;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import org.ggp.base.util.http.HttpReader;
import org.ggp.base.util.http.HttpWriter;
import org.ggp.base.util.loader.RemoteResourceLoader;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import external.JSON.JSONArray;
import external.JSON.JSONObject;
public class TiltyardRequestFarmTest extends Assert {
@Before
public void setUp() {
new RequestFarmLoopThread().start();
}
@Test
public void testThroughput() {
new ResponderLoopThread(2000).start();
new ReceiverLoopThread("OK").start();
runTestingLoop();
}
/* TODO(schreib): Get all of these working at the same time.
@Test
public void testConnectionError() {
new ReceiverLoopThread("CE").start();
runTestingLoop();
}
@Test
public void testTimeout() {
new ResponderLoopThread(4000).start();
new ReceiverLoopThread("TO").start();
runTestingLoop();
}
*/
static long doMath(long a) {
return a/2+3;
}
// Connections are run asynchronously in their own threads.
class ResponderThread extends Thread {
private Socket conn;
private int sleepTime;
public ResponderThread(Socket connection, int sleepTime) {
conn = connection;
this.sleepTime = sleepTime;
}
@Override
public void run() {
try {
String line = HttpReader.readAsServer(conn);
Thread.sleep(sleepTime);
HttpWriter.writeAsServer(conn, "" + doMath(Long.parseLong(line)));
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
AtomicInteger nSuccesses = new AtomicInteger(0);
// Connections are run asynchronously in their own threads.
class ReceiverThread extends Thread {
private Socket conn;
private String response;
public ReceiverThread(Socket connection, String expectedResponse) {
conn = connection;
response = expectedResponse;
}
@Override
public void run() {
try {
String line = HttpReader.readAsServer(conn);
HttpWriter.writeAsServer(conn, "cool");
conn.close();
JSONObject batchResponseJSON = new JSONObject(line);
assertTrue(batchResponseJSON.has("responses"));
assertEquals(2, batchResponseJSON.getJSONArray("responses").length());
JSONObject responseJSON = batchResponseJSON.getJSONArray("responses").getJSONObject(0);
assertEquals(response, responseJSON.getString("responseType"));
if (responseJSON.getString("responseType").equals("OK")) {
long original = Long.parseLong(new JSONObject(responseJSON.getString("originalRequest")).getString("requestContent"));
long response = Long.parseLong(responseJSON.getString("response"));
assertEquals(response, doMath(original));
}
nSuccesses.incrementAndGet();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ResponderLoopThread extends Thread {
private int sleepTime;
public ResponderLoopThread(int sleepTime) {
this.sleepTime = sleepTime;
}
@Override
public void run() {
try {
@SuppressWarnings("resource")
ServerSocket listener = new ServerSocket(12345);
while (true) {
try {
Socket connection = listener.accept();
new ResponderThread(connection, sleepTime).start();
} catch (Exception e) {
System.err.println(e);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ReceiverLoopThread extends Thread {
private String response;
public ReceiverLoopThread(String expectResponse) {
response = expectResponse;
}
@Override
public void run() {
try {
@SuppressWarnings("resource")
ServerSocket listener = new ServerSocket(12346);
while (true) {
try {
Socket connection = listener.accept();
new ReceiverThread(connection, response).start();
} catch (Exception e) {
System.err.println(e);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class RequestFarmLoopThread extends Thread {
@Override
public void run() {
try {
TiltyardRequestFarm.testMode = true;
TiltyardRequestFarm.main(new String[]{});
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void runTestingLoop() {
try {
Random r = new Random();
JSONObject theBatchRequest = new JSONObject();
JSONArray theRequests = new JSONArray();
JSONObject theRequest = new JSONObject();
theRequest.put("targetPort", 12345);
theRequest.put("targetHost", "127.0.0.1");
theRequest.put("timeoutClock", 3000);
theRequest.put("forPlayerName", "");
theRequests.put(theRequest);
theRequests.put(theRequest);
theBatchRequest.put("requests", theRequests);
theBatchRequest.put("callbackURL", "http://127.0.0.1:12346");
int nRequests = 0;
while (true) {
theRequest.put("requestContent", "" + r.nextLong());
theRequest.put("timestamp", System.currentTimeMillis());
assertEquals("okay", RemoteResourceLoader.postRawWithTimeout("http://127.0.0.1:" + TiltyardRequestFarm.SERVER_PORT, theBatchRequest.toString(), 5000));
nRequests++;
Thread.sleep(10);
int curNumSuccesses = nSuccesses.get();
System.out.println("Successes so far: " + curNumSuccesses + " vs Requests: " + nRequests);
if (curNumSuccesses > 3000) {
assertTrue(nRequests > curNumSuccesses);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}