new files with new names (old test passed)
							parent
							
								
									db4cf6a734
								
							
						
					
					
						commit
						11b86dd2aa
					
				| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
package meerkat.pollingstation;
 | 
			
		||||
 | 
			
		||||
import com.google.common.util.concurrent.FutureCallback;
 | 
			
		||||
import meerkat.protobuf.PollingStation;
 | 
			
		||||
import meerkat.rest.ProtobufMessageBodyReader;
 | 
			
		||||
import meerkat.rest.ProtobufMessageBodyWriter;
 | 
			
		||||
import org.eclipse.jetty.server.Server;
 | 
			
		||||
import org.eclipse.jetty.servlet.ServletContextHandler;
 | 
			
		||||
import org.eclipse.jetty.servlet.ServletHolder;
 | 
			
		||||
import org.glassfish.jersey.server.ResourceConfig;
 | 
			
		||||
import org.glassfish.jersey.servlet.ServletContainer;
 | 
			
		||||
 | 
			
		||||
import java.util.LinkedList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by Laura on 3/20/2017.
 | 
			
		||||
 */
 | 
			
		||||
public class ReceiverScanHandler implements PollingStationScanner.Consumer{
 | 
			
		||||
 | 
			
		||||
    public final static String CALLBACKS_ATTRIBUTE_NAME = "callbacks";
 | 
			
		||||
 | 
			
		||||
    private final Server server;
 | 
			
		||||
    private final List<FutureCallback<PollingStation.ScannedData>> callbacks;
 | 
			
		||||
 | 
			
		||||
    public ReceiverScanHandler(int port, String subAddress) {
 | 
			
		||||
 | 
			
		||||
        callbacks = new LinkedList<>();
 | 
			
		||||
 | 
			
		||||
        server = new Server(port);
 | 
			
		||||
 | 
			
		||||
        ServletContextHandler servletContextHandler = new ServletContextHandler(server, subAddress);
 | 
			
		||||
        servletContextHandler.setAttribute(CALLBACKS_ATTRIBUTE_NAME, (Iterable<FutureCallback<PollingStation.ScannedData>>) callbacks);
 | 
			
		||||
 | 
			
		||||
        ResourceConfig resourceConfig = new ResourceConfig(ReceiverWebAPI.class);
 | 
			
		||||
        resourceConfig.register(ProtobufMessageBodyReader.class);
 | 
			
		||||
        resourceConfig.register(ProtobufMessageBodyWriter.class);
 | 
			
		||||
 | 
			
		||||
        ServletHolder servletHolder = new ServletHolder(new ServletContainer(resourceConfig));
 | 
			
		||||
 | 
			
		||||
        servletContextHandler.addServlet(servletHolder, "/*");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void start() throws Exception {
 | 
			
		||||
        server.start();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void stop() throws Exception {
 | 
			
		||||
        server.stop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void subscribe(FutureCallback<PollingStation.ScannedData> scanCallback) {
 | 
			
		||||
        callbacks.add(scanCallback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,92 @@
 | 
			
		|||
package meerkat.pollingstation;
 | 
			
		||||
 | 
			
		||||
import com.google.common.util.concurrent.FutureCallback;
 | 
			
		||||
import com.google.protobuf.BoolValue;
 | 
			
		||||
import meerkat.protobuf.PollingStation;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.PostConstruct;
 | 
			
		||||
import javax.servlet.ServletContext;
 | 
			
		||||
import javax.ws.rs.Consumes;
 | 
			
		||||
import javax.ws.rs.POST;
 | 
			
		||||
import javax.ws.rs.Path;
 | 
			
		||||
import javax.ws.rs.Produces;
 | 
			
		||||
import javax.ws.rs.core.Context;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_ERROR_PATH;
 | 
			
		||||
import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_SCAN_PATH;
 | 
			
		||||
import static meerkat.rest.Constants.MEDIATYPE_PROTOBUF;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements a Web-App interface for {@link meerkat.pollingstation.PollingStationScanner.Producer}
 | 
			
		||||
 * This class depends on {@link meerkat.pollingstation.PollingStationWebScanner} and works in conjunction with it
 | 
			
		||||
 */
 | 
			
		||||
@Path("/")
 | 
			
		||||
public class ReceiverWebAPI implements PollingStationScanner.Producer {
 | 
			
		||||
 | 
			
		||||
    @Context
 | 
			
		||||
    ServletContext servletContext;
 | 
			
		||||
 | 
			
		||||
    Iterable<FutureCallback<PollingStation.ScannedData>> callbacks;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This method is called by the Jetty engine when instantiating the servlet
 | 
			
		||||
     */
 | 
			
		||||
    @PostConstruct
 | 
			
		||||
    @SuppressWarnings("unchecked")
 | 
			
		||||
    public void init() throws Exception {
 | 
			
		||||
        Object context = servletContext.getAttribute(PollingStationWebScanner.CALLBACKS_ATTRIBUTE_NAME);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            callbacks = (Iterable<FutureCallback<PollingStation.ScannedData>>) context;
 | 
			
		||||
        } catch (ClassCastException e) {
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @POST
 | 
			
		||||
    @Path(POLLING_STATION_WEB_SCANNER_SCAN_PATH)
 | 
			
		||||
    @Consumes(MEDIATYPE_PROTOBUF)
 | 
			
		||||
    @Produces(MEDIATYPE_PROTOBUF)
 | 
			
		||||
    @Override
 | 
			
		||||
    public BoolValue newScan(PollingStation.ScannedData scannedData) {
 | 
			
		||||
 | 
			
		||||
        boolean handled = false;
 | 
			
		||||
 | 
			
		||||
        for (FutureCallback<PollingStation.ScannedData> callback : callbacks){
 | 
			
		||||
 | 
			
		||||
            callback.onSuccess(scannedData);
 | 
			
		||||
            handled = true;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return BoolValue.newBuilder()
 | 
			
		||||
                .setValue(handled)
 | 
			
		||||
                .build();
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @POST
 | 
			
		||||
    @Path(POLLING_STATION_WEB_SCANNER_ERROR_PATH)
 | 
			
		||||
    @Consumes(MEDIATYPE_PROTOBUF)
 | 
			
		||||
    @Produces(MEDIATYPE_PROTOBUF)
 | 
			
		||||
    @Override
 | 
			
		||||
    public BoolValue reportScanError(PollingStation.ErrorMsg errorMsg) {
 | 
			
		||||
 | 
			
		||||
        boolean handled = false;
 | 
			
		||||
 | 
			
		||||
        for (FutureCallback<PollingStation.ScannedData> callback : callbacks){
 | 
			
		||||
 | 
			
		||||
            callback.onFailure(new IOException(errorMsg.getMsg()));
 | 
			
		||||
            handled = true;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return BoolValue.newBuilder()
 | 
			
		||||
                .setValue(handled)
 | 
			
		||||
                .build();
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
package meerkat.pollingstation;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by Laura on 3/20/2017.
 | 
			
		||||
 */
 | 
			
		||||
public class ScannerClientAPI {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,162 @@
 | 
			
		|||
package meerkat.pollingstation;
 | 
			
		||||
 | 
			
		||||
import com.google.common.util.concurrent.FutureCallback;
 | 
			
		||||
import com.google.protobuf.ByteString;
 | 
			
		||||
import meerkat.protobuf.PollingStation.ErrorMsg;
 | 
			
		||||
import meerkat.protobuf.PollingStation.ScannedData;
 | 
			
		||||
import meerkat.rest.Constants;
 | 
			
		||||
import meerkat.rest.ProtobufMessageBodyReader;
 | 
			
		||||
import meerkat.rest.ProtobufMessageBodyWriter;
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import javax.ws.rs.client.Client;
 | 
			
		||||
import javax.ws.rs.client.ClientBuilder;
 | 
			
		||||
import javax.ws.rs.client.Entity;
 | 
			
		||||
import javax.ws.rs.client.WebTarget;
 | 
			
		||||
import javax.ws.rs.core.Response;
 | 
			
		||||
import java.util.concurrent.Semaphore;
 | 
			
		||||
 | 
			
		||||
import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_ERROR_PATH;
 | 
			
		||||
import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_SCAN_PATH;
 | 
			
		||||
import static org.hamcrest.MatcherAssert.assertThat;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by Arbel on 25/05/2016.
 | 
			
		||||
 */
 | 
			
		||||
public class ReceiverTest {
 | 
			
		||||
 | 
			
		||||
    private PollingStationScanner.Consumer scanner;
 | 
			
		||||
    private static final String ADDRESS = "http://localhost";
 | 
			
		||||
    private static final String SUB_ADDRESS = "";
 | 
			
		||||
    private static final int PORT = 8080;
 | 
			
		||||
 | 
			
		||||
    private Semaphore semaphore;
 | 
			
		||||
    private Throwable thrown;
 | 
			
		||||
    private boolean dataIsAsExpected;
 | 
			
		||||
 | 
			
		||||
    private class ScanHandler implements FutureCallback<ScannedData> {
 | 
			
		||||
 | 
			
		||||
        private final ScannedData expectedData;
 | 
			
		||||
 | 
			
		||||
        public ScanHandler(ScannedData expectedData) {
 | 
			
		||||
            this.expectedData = expectedData;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onSuccess(ScannedData result) {
 | 
			
		||||
            dataIsAsExpected = result.getChannel().equals(expectedData.getChannel());
 | 
			
		||||
            semaphore.release();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onFailure(Throwable t) {
 | 
			
		||||
            dataIsAsExpected = false;
 | 
			
		||||
            thrown = t;
 | 
			
		||||
            semaphore.release();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private class ErrorHandler implements FutureCallback<ScannedData> {
 | 
			
		||||
 | 
			
		||||
        private final String expectedErrorMessage;
 | 
			
		||||
 | 
			
		||||
        public ErrorHandler(String expectedErrorMessage) {
 | 
			
		||||
            this.expectedErrorMessage = expectedErrorMessage;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onSuccess(ScannedData result) {
 | 
			
		||||
            dataIsAsExpected = false;
 | 
			
		||||
            semaphore.release();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onFailure(Throwable t) {
 | 
			
		||||
            dataIsAsExpected = t.getMessage().equals(expectedErrorMessage);
 | 
			
		||||
            semaphore.release();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    public void init() {
 | 
			
		||||
 | 
			
		||||
        System.err.println("Setting up Scanner WebApp!");
 | 
			
		||||
 | 
			
		||||
        scanner = new ReceiverScanHandler(PORT, SUB_ADDRESS);
 | 
			
		||||
 | 
			
		||||
        semaphore = new Semaphore(0);
 | 
			
		||||
        thrown = null;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            scanner.start();
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            assertThat("Could not start server: " + e.getMessage(), false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSuccessfulScan() throws InterruptedException {
 | 
			
		||||
 | 
			
		||||
        Client client = ClientBuilder.newClient();
 | 
			
		||||
        client.register(ProtobufMessageBodyReader.class);
 | 
			
		||||
        client.register(ProtobufMessageBodyWriter.class);
 | 
			
		||||
        WebTarget webTarget = client.target(ADDRESS + ":" + PORT)
 | 
			
		||||
                .path(SUB_ADDRESS).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH);
 | 
			
		||||
 | 
			
		||||
        byte[] data = {(byte) 1, (byte) 2};
 | 
			
		||||
 | 
			
		||||
        ScannedData scannedData = ScannedData.newBuilder()
 | 
			
		||||
                .setChannel(ByteString.copyFrom(data))
 | 
			
		||||
                .build();
 | 
			
		||||
 | 
			
		||||
        scanner.subscribe(new ScanHandler(scannedData));
 | 
			
		||||
 | 
			
		||||
        Response response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(scannedData, Constants.MEDIATYPE_PROTOBUF));
 | 
			
		||||
        response.close();
 | 
			
		||||
 | 
			
		||||
        semaphore.acquire();
 | 
			
		||||
        assertThat("Scanner has thrown an error", thrown == null);
 | 
			
		||||
        assertThat("Scanned data received was incorrect", dataIsAsExpected);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testErroneousScan() throws InterruptedException {
 | 
			
		||||
 | 
			
		||||
        Client client = ClientBuilder.newClient();
 | 
			
		||||
        client.register(ProtobufMessageBodyReader.class);
 | 
			
		||||
        client.register(ProtobufMessageBodyWriter.class);
 | 
			
		||||
        WebTarget webTarget = client.target(ADDRESS + ":" + PORT)
 | 
			
		||||
                .path(SUB_ADDRESS).path(POLLING_STATION_WEB_SCANNER_ERROR_PATH);
 | 
			
		||||
 | 
			
		||||
        ErrorMsg errorMsg = ErrorMsg.newBuilder()
 | 
			
		||||
                .setMsg("!Error Message!")
 | 
			
		||||
                .build();
 | 
			
		||||
 | 
			
		||||
        scanner.subscribe(new ErrorHandler(errorMsg.getMsg()));
 | 
			
		||||
 | 
			
		||||
        Response response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(errorMsg, Constants.MEDIATYPE_PROTOBUF));
 | 
			
		||||
        response.close();
 | 
			
		||||
 | 
			
		||||
        semaphore.acquire();
 | 
			
		||||
        assertThat("Scanner error received was incorrect", dataIsAsExpected);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @After
 | 
			
		||||
    public void close() {
 | 
			
		||||
 | 
			
		||||
        System.err.println("ReceiverScanHandler shutting down...");
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            scanner.stop();
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            assertThat("Could not stop server: " + e.getMessage(), false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue