package edu.harvard.econcs.turkserver.server; import static org.junit.Assert.*; import java.util.Map; import org.apache.commons.configuration.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; import edu.harvard.econcs.turkserver.Codec; import edu.harvard.econcs.turkserver.cometd.MockServerSession; import edu.harvard.econcs.turkserver.config.TSConfig; import edu.harvard.econcs.turkserver.mturk.FakeHITController; import edu.harvard.econcs.turkserver.schema.Quiz; import edu.harvard.econcs.turkserver.schema.Session; import edu.harvard.econcs.turkserver.server.Lobby.NullLobby; import edu.harvard.econcs.turkserver.server.SessionRecord.SessionStatus; import edu.harvard.econcs.turkserver.server.mysql.MockDataTracker; @SuppressWarnings("unchecked") public class GroupServerTest { static final String USER_CHANNEL = "/service/user"; MockDataTracker tracker; GroupServer server; NullLobby lobby; @Before public void setUp() throws Exception { tracker = new MockDataTracker(); Configuration conf = TSConfig.getDefault(); conf.setProperty(TSConfig.EXP_REPEAT_LIMIT, 1); conf.setProperty(TSConfig.SERVER_HITGOAL, 2); QuizFactory qf = new QuizFactory.NullQuizFactory(); QuizPolicy onePassQuiz = new QuizPolicy.PercentageQuizPolicy(1d, 1); WorkerAuthenticator workerAuth = new WorkerAuthenticator(tracker, qf, onePassQuiz, conf); server = new GroupServer( tracker, new FakeHITController(), workerAuth, new Experiments(null, null, tracker, null), conf, lobby = new Lobby.NullLobby() ); } @After public void tearDown() throws Exception { } @Test public void testHITView() { MockServerSession session = new MockServerSession(); String hitId = "someHitId"; assertFalse(tracker.hitExistsInDB(hitId)); server.sessionView(session, hitId); // Verify that this hitId is stored now assertTrue(tracker.hitExistsInDB(hitId)); } @Test public void testAcceptOverlap() { String hitId = "testHITId"; Session s = new Session(); s.setHitId(hitId); s.setWorkerId("someOtherWorker"); s.setExperimentId("random experiment"); // Means worker is in experiment assertEquals(SessionStatus.EXPERIMENT, SessionRecord.status(s)); tracker.saveSession(s); MockServerSession conn = new MockServerSession(); server.sessionAccept(conn, hitId, "someAssignment", "thisWorker"); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_sessionoverlap, ((Map<String, Object>) conn.lastData).get("status")); } @Test public void testAcceptSimultaneousLimit() { String hitId = "testHITId"; String workerId = "testWorkerId"; String assignmentId = "testAssignmentId"; Session takenSession = new Session(); takenSession.setHitId(hitId); takenSession.setWorkerId(workerId); takenSession.setAssignmentId(assignmentId); assertEquals(SessionStatus.ASSIGNED, SessionRecord.status(takenSession)); tracker.saveSession(takenSession); String hitId2 = "testHITId2"; String assignmentId2 = "assignmentId2"; MockServerSession conn = new MockServerSession(); // Attempt to take new session server.sessionAccept(conn, hitId2, assignmentId2, workerId); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_simultaneoussessions, ((Map<String, Object>) conn.lastData).get("status")); } @Test public void testAcceptHITLimit() { String hitId = "testHITId"; String workerId = "testWorkerId"; String assignmentId = "testAssignmentId"; Session s = new Session(); s.setHitId(hitId); s.setWorkerId(workerId); s.setAssignmentId(assignmentId); s.setInactivePercent(0.0); // Identifies completed session assertEquals(SessionStatus.COMPLETED, SessionRecord.status(s)); tracker.saveSession(s); String hitId2 = "testHITId2"; String assignmentId2 = "assignmentId2"; MockServerSession conn = new MockServerSession(); // Attempt to take new session server.sessionAccept(conn, hitId2, assignmentId2, workerId); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_toomanysessions, ((Map<String, Object>) conn.lastData).get("status")); } @Test public void testAcceptQuizRequired() { MockServerSession conn = new MockServerSession(); server.sessionAccept(conn, "hitId", "assignmentId", "workerId"); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_quizneeded, ((Map<String, Object>) conn.lastData).get("status")); } @Test public void testAcceptQuizFailsauce() { String hitId = "testHITId"; String workerId = "testWorkerId"; String assignmentId = "testAssignmentId"; Quiz failedQuiz = new Quiz(); failedQuiz.setNumCorrect(0); failedQuiz.setNumTotal(1); failedQuiz.setScore(0d); tracker.saveQuizResults(hitId, workerId, failedQuiz); MockServerSession conn = new MockServerSession(); server.sessionAccept(conn, hitId, assignmentId, workerId); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_failsauce, ((Map<String, Object>) conn.lastData).get("status")); } @Test public void testAcceptLobby() { String hitId = "testHITId"; String workerId = "testWorkerId"; String assignmentId = "testAssignmentId"; Quiz passedQuiz = new Quiz(); passedQuiz.setNumCorrect(1); passedQuiz.setNumTotal(1); passedQuiz.setScore(1d); tracker.saveQuizResults(hitId, workerId, passedQuiz); MockServerSession conn = new MockServerSession(); server.sessionAccept(conn, hitId, assignmentId, workerId); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_connectlobby, ((Map<String, Object>) conn.lastData).get("status")); } @Test public void testAcceptCompleted() { String hitId = "testHITId"; String assignmentId = "testAssignmentId"; String workerId = "workerId"; Session s = new Session(); s.setHitId(hitId); s.setWorkerId(workerId); s.setInactivePercent(0.00); tracker.saveSession(s); // Pretend that we have a previous HITWorker for this guy HITWorkerImpl hitw = new HITWorkerImpl(null, s); server.hitWorkerTable.put(hitId, workerId, hitw); assertEquals(0, server.completedHITs); assertEquals(SessionStatus.COMPLETED, SessionRecord.status(s)); MockServerSession conn = new MockServerSession(); server.sessionAccept(conn, hitId, assignmentId, workerId); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_expfinished, ((Map<String, Object>) conn.lastData).get("status")); // Try to submit the HIT and ensure it goes through server.updateCompletion(); server.sessionSubmit(conn, "some random results"); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_completed, ((Map<String, Object>) conn.lastData).get("status")); assertEquals(1, server.completedHITs); // Make sure that a double-submit doesn't count twice server.updateCompletion(); server.sessionSubmit(conn, "some random results"); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_completed, ((Map<String, Object>) conn.lastData).get("status") ); assertEquals(1, server.completedHITs); } /* * Test a reconnect after disconnecting */ @Test public void testReconnect() { String hitId = "testHITId"; String workerId = "testWorkerId"; String assignmentId = "testAssignmentId"; Quiz passedQuiz = new Quiz(); passedQuiz.setNumCorrect(1); passedQuiz.setNumTotal(1); passedQuiz.setScore(1d); tracker.saveQuizResults(hitId, workerId, passedQuiz); MockServerSession conn = new MockServerSession(); server.sessionAccept(conn, hitId, assignmentId, workerId); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_connectlobby, ((Map<String, Object>) conn.lastData).get("status")); Session record = tracker.getStoredSessionInfo(hitId); assertEquals(record.getHitId(), hitId); assertEquals(record.getAssignmentId(), assignmentId); assertEquals(record.getWorkerId(), workerId); server.sessionDisconnect(conn); // Check workerId cleared assertEquals(record.getWorkerId(), null); MockServerSession conn2 = new MockServerSession(); // Accept again server.sessionAccept(conn2, hitId, assignmentId, workerId); assertEquals(conn2.lastChannel, USER_CHANNEL); assertEquals(Codec.status_connectlobby, ((Map<String, Object>) conn2.lastData).get("status")); // Check workerId reassigned assertEquals(record.getWorkerId(), workerId); } @Test public void testAcceptBatchFinished() { String hitId = "testHITId"; String workerId = "workerId"; Session s = new Session(); s.setHitId(hitId); s.setWorkerId(workerId); s.setInactivePercent(0.00); s.setComment("something"); tracker.saveSession(s); String hitId2 = "testHITId2"; Session s2 = new Session(); s2.setHitId(hitId2); s2.setWorkerId(workerId); s2.setInactivePercent(0.00); s2.setComment("something"); tracker.saveSession(s2); assertEquals(SessionStatus.COMPLETED, SessionRecord.status(s)); assertEquals(SessionStatus.COMPLETED, SessionRecord.status(s2)); server.updateCompletion(); assertEquals(2, server.completedHITs); MockServerSession conn = new MockServerSession(); server.sessionAccept(conn, "someHitId", "someAssignmentId", "someWorkerId"); assertEquals(conn.lastChannel, USER_CHANNEL); assertEquals(Codec.status_batchfinished, ((Map<String, Object>) conn.lastData).get("status")); /* * Check that lobby was notified * TODO this should be more robust */ assertTrue(!lobby.gotUsers); server.groupCompleted(null); assertTrue(lobby.gotUsers); } }