package net.johnewart.gearman.integ;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import net.johnewart.gearman.client.NetworkGearmanClient;
import net.johnewart.gearman.common.Job;
import net.johnewart.gearman.common.JobStatus;
import net.johnewart.gearman.common.events.GearmanClientEventListener;
import net.johnewart.gearman.common.events.WorkEvent;
import net.johnewart.gearman.common.interfaces.GearmanClient;
import net.johnewart.gearman.common.interfaces.GearmanFunction;
import net.johnewart.gearman.common.interfaces.GearmanWorker;
import net.johnewart.gearman.engine.queue.factories.MemoryJobQueueFactory;
import net.johnewart.gearman.exceptions.JobSubmissionException;
import net.johnewart.gearman.exceptions.WorkException;
import net.johnewart.gearman.net.Connection;
import net.johnewart.gearman.server.config.GearmanServerConfiguration;
import net.johnewart.gearman.server.config.ServerConfiguration;
import net.johnewart.gearman.server.net.ServerListener;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
public class BasicServerIntegrationTest {
private final Logger LOG = LoggerFactory.getLogger(BasicServerIntegrationTest.class);
public BasicServerIntegrationTest() { }
public void runTest() throws InterruptedException, IOException, JobSubmissionException, WorkException {
int port = 8888;
String hostname = "localhost";
GearmanServerConfiguration primaryConfig = new GearmanServerConfiguration();
primaryConfig.setHostName(hostname);
primaryConfig.setPort(port);
primaryConfig.setJobQueueFactory(new MemoryJobQueueFactory(primaryConfig.getMetricRegistry()));
ServerRunner runner = new ServerRunner(primaryConfig);
Thread t1 = new Thread(runner);
t1.start();
LOG.debug("Sleeping for 5s to let things start up");
Thread.sleep(5000);
LOG.debug("Running tests...");
CountingReverseFunc reverseFunc = new CountingReverseFunc(10);
Set<Connection> connectionSet = ImmutableSet.of(new Connection(hostname, port));
ImmutableMap<String, GearmanFunction> functions = ImmutableMap.of("reverse", (GearmanFunction)reverseFunc);
WorkerRunner workerRunner = new WorkerRunner(connectionSet, functions);
Thread t3 = new Thread(workerRunner);
t3.start();
String[] jobStrings = {
"HELLO",
"FOO",
"BAR",
"ONE",
"BYE",
"SNARF",
"BAZ",
"GEARMAN",
"FOOBAR",
"BIGFOOT"
};
final AtomicInteger integer = new AtomicInteger(0);
GearmanClient client = new NetworkGearmanClient("localhost", port);
GearmanClientEventListener listener = new GearmanClientEventListener() {
@Override
public void handleWorkData(String jobHandle, byte[] data) {
LOG.debug("handleWorkData for " + jobHandle);
}
@Override
public void handleWorkWarning(String jobHandle, byte[] warning) {
LOG.debug ("handleWorkWarning for " + jobHandle);
}
@Override
public void handleWorkStatus(String jobHandle, JobStatus jobStatus) {
LOG.debug ("handleWorkStatus for " + jobHandle);
integer.addAndGet(1);
}
};
client.registerEventListener(listener);
for(int i = 0; i < 10; i++) {
byte[] jobData = jobStrings[i].getBytes();
byte[] reversedData = jobData.clone();
ArrayUtils.reverse(reversedData);
byte[] result = client.submitJob("reverse", jobData);
Assert.assertArrayEquals(result, reversedData);
LOG.debug(String.format("Result: %s", new String(result)));
}
assertThat(reverseFunc.isComplete(), is(true));
assertEquals(integer.get(), 100);
client.shutdown();
workerRunner.stop();
LOG.debug("Stopping worker thread");
t3.join();
LOG.debug("Stopping server thread");
runner.stop();
t1.join();
LOG.debug("Done!");
}
public static void main(String... args) throws InterruptedException, IOException, JobSubmissionException, WorkException {
BasicServerIntegrationTest basicServerIntegrationTest = new BasicServerIntegrationTest();
basicServerIntegrationTest.runTest();
}
private class CountingReverseFunc implements GearmanFunction {
private final int maxHits;
private int hits;
public CountingReverseFunc(int num) {
this.maxHits = num;
this.hits = 0;
}
public boolean isComplete() {
return hits == maxHits;
}
@Override
public byte[] process(WorkEvent workEvent) {
Job job = workEvent.job;
GearmanWorker worker = workEvent.worker;
hits += 1;
LOG.debug(String.format("Processing job '%s' with data '%s'", job.getFunctionName(), new String(job.getData())));
byte[] data = job.getData().clone();
for(int i = 0; i < 10; i++) {
try {
worker.sendStatus(job, i, 10);
} catch (IOException e) {
LOG.error("Unable to send status: ", e);
}
}
ArrayUtils.reverse(data);
return data;
}
}
private class ServerRunner implements Runnable {
private final ServerListener server;
public ServerRunner(ServerConfiguration serverConfig) {
server = new ServerListener(serverConfig);
}
@Override
public void run() {
server.start();
}
public void stop() {
server.stop();
}
}
}