package net.johnewart.gearman.server; import io.netty.channel.Channel; import net.johnewart.gearman.common.Job; import net.johnewart.gearman.common.interfaces.EngineClient; import net.johnewart.gearman.common.interfaces.EngineWorker; import net.johnewart.gearman.common.packets.request.SubmitJob; import net.johnewart.gearman.common.packets.response.JobAssign; import net.johnewart.gearman.common.packets.response.JobCreated; import net.johnewart.gearman.common.packets.response.WorkCompleteResponse; import net.johnewart.gearman.common.packets.response.WorkResponse; import net.johnewart.gearman.constants.JobPriority; import net.johnewart.gearman.engine.core.JobManager; import net.johnewart.gearman.server.net.NetworkEngineClient; import net.johnewart.gearman.server.net.NetworkManager; import net.johnewart.gearman.server.net.NetworkEngineWorker; import org.hamcrest.core.Is; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Matchers; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; public class NetworkManagerTest { private JobManager mockJobManager; private Channel mockClientChannel, mockWorkerChannel; private NetworkManager networkManager; private NetworkEngineClient client; private NetworkEngineWorker worker; public NetworkManagerTest() { } @Before public void initialize() { mockJobManager = Mockito.mock(JobManager.class); mockClientChannel = Mockito.mock(Channel.class); mockWorkerChannel = Mockito.mock(Channel.class); networkManager = new NetworkManager(mockJobManager); client = new NetworkEngineClient(mockClientChannel); worker = new NetworkEngineWorker(mockWorkerChannel); } @Test public void sendsJobCreatedPacketToClient() throws Exception { final String functionName = "bigJob"; final String uniqueID = "rincewind"; final byte[] submitData = {'b','a', 'r'}; final Job job = new Job(functionName, uniqueID, submitData, JobPriority.NORMAL, false); SubmitJob submitJobPacket = new SubmitJob(functionName, uniqueID, submitData, false); Mockito.when(mockJobManager.storeJobForClient(Matchers.any(Job.class), Matchers.any(EngineClient.class))).thenReturn(job); networkManager.createJob(submitJobPacket, mockClientChannel); Mockito.verify(mockClientChannel).writeAndFlush(Matchers.any(JobCreated.class)); } @Test public void sendWorkCompleteResponseToClientWhenFinished() throws Exception { final String functionName = "bigJob"; final String uniqueID = "rincewind"; final byte[] submitData = {'b','a', 'r'}; final String[] jobHandle = new String[1]; final Job job = new Job(functionName, uniqueID, submitData, JobPriority.NORMAL, false); // Pretend storing works A-OK! Mockito.when(mockJobManager.storeJobForClient(Matchers.any(Job.class), Matchers.any(EngineClient.class))).thenReturn(job); Mockito.when(mockJobManager.storeJob(Matchers.any(Job.class))).thenReturn(job); Mockito.when(mockJobManager.nextJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); Mockito.when(mockJobManager.getCurrentJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); // When we get a JOB_CREATED packet, pull out the job handle Mockito.when(mockClientChannel.writeAndFlush(Matchers.any(JobCreated.class))).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); if (args[0].getClass().equals(JobCreated.class)) { JobCreated response = (JobCreated) args[0]; jobHandle[0] = response.getJobHandle(); } return null; } }); // Submit a job as the client SubmitJob submitJobPacket = new SubmitJob(functionName, uniqueID, submitData, false); networkManager.createJob(submitJobPacket, mockClientChannel); Mockito.verify(mockClientChannel).writeAndFlush(Matchers.any(JobCreated.class)); // Register our worker networkManager.registerAbility(functionName, mockWorkerChannel); // Fetch the job as our worker networkManager.nextJobForWorker(mockWorkerChannel, false); Mockito.verify(mockWorkerChannel).writeAndFlush(Matchers.any(JobAssign.class)); byte[] resultdata = {'f','o', 'o'}; WorkResponse workResponse = new WorkCompleteResponse(jobHandle[0], resultdata); networkManager.workResponse(workResponse, mockWorkerChannel); Mockito.verify(mockClientChannel).writeAndFlush(Matchers.any(WorkCompleteResponse.class)); } @Test public void handleWorkerChannelDisconnected() throws Exception { final String functionName = "bigJob"; final String uniqueID = "rincewind"; final byte[] submitData = {'b','a', 'r'}; final String[] jobHandle = new String[1]; final Job job = new Job(functionName, uniqueID, submitData, JobPriority.NORMAL, false); // Pretend storing works A-OK! Mockito.when(mockJobManager.storeJobForClient(Matchers.any(Job.class), Matchers.any(EngineClient.class))).thenReturn(job); Mockito.when(mockJobManager.storeJob(Matchers.any(Job.class))).thenReturn(job); Mockito.when(mockJobManager.nextJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); Mockito.when(mockJobManager.getCurrentJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); // When we get a JOB_CREATED packet, pull out the job handle Mockito.when(mockClientChannel.writeAndFlush(Matchers.any(JobCreated.class))).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); if (args[0].getClass().equals(JobCreated.class)) { JobCreated response = (JobCreated) args[0]; jobHandle[0] = response.getJobHandle(); } return null; } }); // Submit a job as the client SubmitJob submitJobPacket = new SubmitJob(functionName, uniqueID, submitData, false); networkManager.createJob(submitJobPacket, mockClientChannel); Mockito.verify(mockClientChannel).writeAndFlush(Matchers.any(JobCreated.class)); // Register our worker networkManager.registerAbility(functionName, mockWorkerChannel); Assert.assertThat("There is one worker connected", networkManager.getWorkerList().size(), Is.is(1)); // Fetch the job as our worker networkManager.nextJobForWorker(mockWorkerChannel, false); // Simulate a disconnect networkManager.channelDisconnected(mockWorkerChannel); // Make sure it gets unregistered Mockito.verify(mockJobManager).unregisterWorker(Matchers.any(EngineWorker.class)); Assert.assertThat("There are no workers connected", networkManager.getWorkerList().size(), Is.is(0)); } @Test public void handleClientChannelDisconnected() throws Exception { final String functionName = "bigJob"; final String uniqueID = "rincewind"; final byte[] submitData = {'b','a', 'r'}; final String[] jobHandle = new String[1]; final Job job = new Job(functionName, uniqueID, submitData, JobPriority.NORMAL, false); // Pretend storing works A-OK! Mockito.when(mockJobManager.storeJobForClient(Matchers.any(Job.class), Matchers.any(EngineClient.class))).thenReturn(job); Mockito.when(mockJobManager.storeJob(Matchers.any(Job.class))).thenReturn(job); Mockito.when(mockJobManager.nextJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); Mockito.when(mockJobManager.getCurrentJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); // When we get a JOB_CREATED packet, pull out the job handle Mockito.when(mockClientChannel.writeAndFlush(Matchers.any(JobCreated.class))).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); if (args[0].getClass().equals(JobCreated.class)) { JobCreated response = (JobCreated) args[0]; jobHandle[0] = response.getJobHandle(); } return null; } }); // Submit a job as the client SubmitJob submitJobPacket = new SubmitJob(functionName, uniqueID, submitData, false); networkManager.createJob(submitJobPacket, mockClientChannel); Mockito.verify(mockClientChannel).writeAndFlush(Matchers.any(JobCreated.class)); // Register our worker networkManager.registerAbility(functionName, mockWorkerChannel); // Fetch the job as our worker networkManager.nextJobForWorker(mockWorkerChannel, false); // TODO: Make sure to finish this ... Assert.assertThat("There is one client connected", networkManager.getClientList().size(), Is.is(1)); networkManager.channelDisconnected(mockClientChannel); Assert.assertThat("There are no clients connected", networkManager.getClientList().size(), Is.is(0)); } @Test public void handleWorkerSendsWorkData() throws Exception { final String functionName = "bigJob"; final String uniqueID = "rincewind"; final byte[] submitData = {'b','a', 'r'}; final String[] jobHandle = new String[1]; final Job job = new Job(functionName, uniqueID, submitData, JobPriority.NORMAL, false); // Worker sends a WORK_DATA request packet, that needs to be forwarded to the client(s) // Pretend storing works A-OK! Mockito.when(mockJobManager.storeJobForClient(Matchers.any(Job.class), Matchers.any(EngineClient.class))).thenReturn(job); Mockito.when(mockJobManager.storeJob(Matchers.any(Job.class))).thenReturn(job); Mockito.when(mockJobManager.nextJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); Mockito.when(mockJobManager.getCurrentJobForWorker(Matchers.any(EngineWorker.class))).thenReturn(job); // When we get a JOB_CREATED packet, pull out the job handle Mockito.when(mockClientChannel.writeAndFlush(Matchers.any(JobCreated.class))).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); if (args[0].getClass().equals(JobCreated.class)) { JobCreated response = (JobCreated) args[0]; jobHandle[0] = response.getJobHandle(); } return null; } }); // Submit a job as the client SubmitJob submitJobPacket = new SubmitJob(functionName, uniqueID, submitData, false); networkManager.createJob(submitJobPacket, mockClientChannel); Mockito.verify(mockClientChannel).writeAndFlush(Matchers.any(JobCreated.class)); // Register our worker networkManager.registerAbility(functionName, mockWorkerChannel); // Fetch the job as our worker networkManager.nextJobForWorker(mockWorkerChannel, false); // TODO: Make sure to finish this ... Assert.assertThat("There is one client connected", networkManager.getClientList().size(), Is.is(1)); networkManager.channelDisconnected(mockClientChannel); Assert.assertThat("There are no clients connected", networkManager.getClientList().size(), Is.is(0)); } }