package edu.harvard.econcs.turkserver.server;
import static org.junit.Assert.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.ImmutableMap;
import edu.harvard.econcs.turkserver.api.HITWorkerGroup;
import edu.harvard.econcs.turkserver.cometd.MockServerSession;
import edu.harvard.econcs.turkserver.config.TSConfig;
import edu.harvard.econcs.turkserver.schema.Session;
public class LobbySyncTest {
class TestLobbyListener implements LobbyListener {
ConcurrentLinkedQueue<HITWorkerGroup> groups = new ConcurrentLinkedQueue<HITWorkerGroup>();
@Override
public void broadcastLobbyMessage(Object data) {}
@Override
public void createNewExperiment(HITWorkerGroupImpl group) {
// System.out.println("Got " + group);
groups.add(group);
// Simulate taking some time to make an experiment, since this is in the synchronized block
try { Thread.sleep(Math.round(Math.random() * 10));
} catch (InterruptedException e) { e.printStackTrace(); }
}
@Override
public int getNumExperimentsRunning() { return 0; }
@Override
public int getNumUsersConnected() { return 0; }
}
int total = 300;
int groupsize = 3;
ReadyStateLobby lobby;
TestLobbyListener listener;
@Before
public void setUp() throws Exception {
Configuration conf = new PropertiesConfiguration();
conf.addProperty(TSConfig.SERVER_LOBBY_DEFAULT, true);
lobby = new ReadyStateLobby(new DummyConfigurator(groupsize), conf);
lobby.setListener(listener = new TestLobbyListener());
}
@After
public void tearDown() throws Exception {
}
@Test
public void test() throws InterruptedException {
Set<Thread> threadz = new HashSet<>();
final Map<String, Object> lobbyReady = ImmutableMap.<String, Object>of("ready", true);
for( int i = 0; i < total; i++ ) {
final Session record = new Session();
record.setHitId("HIT " + i);
record.setAssignmentId("Assignment " + i);
record.setWorkerId("Worker " + i);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
// Sleep a random amount of time
try {
Thread.sleep(Math.round(Math.random() * 10));
} catch (InterruptedException e) {}
HITWorkerImpl hitw = new HITWorkerImpl(new MockServerSession(), record);
lobby.userJoined(hitw);
// Send a possible random lobby status update for SNAFU checking
if( Math.random() < 0.5 )
lobby.updateStatus(hitw, lobbyReady);
}
});
t.start();
threadz.add(t);
}
for( Thread t : threadz ) t.join();
int totalUsers = 0;
int totalGroups = 0;
Set<String> ids = new HashSet<String>();
int numGroups = this.total / groupsize;
// Check that each group size is correct
for( HITWorkerGroup group : listener.groups ) {
// System.out.println(group);
assertEquals(groupsize, group.groupSize());
totalUsers += group.groupSize();
totalGroups++;
for( String worker : group.getHITIds() )
ids.add(worker);
}
// Check for sufficent # groups
System.out.println("Groups: " + listener.groups.size());
assertEquals(numGroups, listener.groups.size());
assertEquals(numGroups, totalGroups);
// Check for all users covered
System.out.println("Unique users out: " + ids.size());
System.out.println("Total users out: " + totalUsers);
assertEquals(this.total, ids.size());
assertEquals(this.total, totalUsers);
}
}