
Author: seb Date: Mon Nov 27 16:38:52 2006 New Revision: 1006 Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/MockSocketServer.java logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/NOPOutputStream.java logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SerializationPerfTest.java logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java Modified: logback/trunk/logback-access/pom.xml logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/SocketAppender.java logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java Log: Added some tests for SocketAppender Modified: logback/trunk/logback-access/pom.xml ============================================================================== --- logback/trunk/logback-access/pom.xml (original) +++ logback/trunk/logback-access/pom.xml Mon Nov 27 16:38:52 2006 @@ -91,6 +91,7 @@ <excludes> <exclude>**/AllTest.java</exclude> <exclude>**/PackageTest.java</exclude> + <exclude>**/SerializationPerfTest.java</exclude> </excludes> </configuration> </plugin> Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/SocketAppender.java ============================================================================== --- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/SocketAppender.java (original) +++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/SocketAppender.java Mon Nov 27 16:38:52 2006 @@ -54,7 +54,7 @@ @Override protected void postProcessEvent(Object event) { AccessEvent ae = (AccessEvent)event; - ae.prepareForSerialization(); + ae.prepareForDeferredProcessing(); } } Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java ============================================================================== --- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java (original) +++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/spi/AccessEvent.java Mon Nov 27 16:38:52 2006 @@ -42,6 +42,7 @@ String postContent; Map<String, Object> requestHeaderMap; + Map<String, Object> requestParameterMap; long contentLength = SENTINEL; int statusCode = SENTINEL; @@ -209,12 +210,27 @@ public void buildRequestHeaderMap() { requestHeaderMap = new HashMap<String, Object>(); Enumeration e = httpRequest.getHeaderNames(); + if (e == null) { + return; + } while (e.hasMoreElements()) { String key = (String) e.nextElement(); requestHeaderMap.put(key, httpRequest.getHeader(key)); } } - + + public void buildRequestParameterMap() { + requestParameterMap = new HashMap<String, Object>(); + Enumeration e = httpRequest.getParameterNames(); + if (e == null) { + return; + } + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + requestParameterMap.put(key, httpRequest.getParameter(key)); + } + } + public String getResponseHeader(String key) { return serverAdapter.getResponseHeader(key); } @@ -319,7 +335,20 @@ return serverAdapter; } - public void prepareForSerialization() { + public void prepareForDeferredProcessing() { + buildRequestHeaderMap(); + buildRequestParameterMap(); + getLocalPort(); + getMethod(); + getProtocol(); + getRemoteAddr(); + getRemoteHost(); + getRemoteUser(); + getRequestURI(); + getRequestURL(); + getServerName(); + getTimeStamp(); + getStatusCode(); getContentLength(); //getPostContent(); Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/MockSocketServer.java ============================================================================== --- (empty file) +++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/MockSocketServer.java Mon Nov 27 16:38:52 2006 @@ -0,0 +1,73 @@ +/** + * Logback: the reliable, generic, fast and flexible logging framework. + * + * Copyright (C) 1999-2006, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ +package ch.qos.logback.access.net; + +import java.io.BufferedInputStream; +import java.io.ObjectInputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.access.spi.AccessEvent; + + +/** + * @author Sébastien Pennec + */ +public class MockSocketServer extends Thread { + + static final int PORT = 4560; + + final int loopLen; + + List<AccessEvent> accessEventList = new ArrayList<AccessEvent>(); + boolean finished = false; + + MockSocketServer(int loopLen) { + super(); + this.loopLen = loopLen; + } + + @Override + public void run() { + ObjectInputStream ois = null; + ServerSocket serverSocket = null; + // Object readObject; + AccessEvent event; + try { + serverSocket = new ServerSocket(PORT); + Socket socket = serverSocket.accept(); + ois = new ObjectInputStream(new BufferedInputStream(socket + .getInputStream())); + for (int i = 0; i < loopLen; i++) { + event = (AccessEvent) ois.readObject(); + accessEventList.add(event); + } + } catch (Exception se) { + se.printStackTrace(); + } finally { + + if (ois != null) { + try { + ois.close(); + } catch (Exception e) { + } + } + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (Exception e) { + } + } + } + finished = true; + } +} Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/NOPOutputStream.java ============================================================================== --- (empty file) +++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/NOPOutputStream.java Mon Nov 27 16:38:52 2006 @@ -0,0 +1,24 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 1999-2006, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ + +package ch.qos.logback.access.net; + +import java.io.IOException; +import java.io.OutputStream; + +public class NOPOutputStream extends OutputStream { + + @Override + public void write(int b) throws IOException { + // do nothing + + } + +} Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SerializationPerfTest.java ============================================================================== --- (empty file) +++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SerializationPerfTest.java Mon Nov 27 16:38:52 2006 @@ -0,0 +1,96 @@ +package ch.qos.logback.access.net; + +import java.io.IOException; +import java.io.ObjectOutputStream; + +import junit.framework.TestCase; +import ch.qos.logback.access.pattern.helpers.DummyRequest; +import ch.qos.logback.access.pattern.helpers.DummyResponse; +import ch.qos.logback.access.pattern.helpers.DummyServerAdapter; +import ch.qos.logback.access.spi.AccessEvent; + +public class SerializationPerfTest extends TestCase { + + ObjectOutputStream oos; + + int loopNumber = 10000; + int resetFrequency = 100; + int pauseFrequency = 10; + long pauseLengthInMillis = 20; + + + public void setUp() throws Exception { + super.setUp(); + oos = new ObjectOutputStream(new NOPOutputStream()); + + } + + public void tearDown() throws Exception { + super.tearDown(); + oos.close(); + oos = null; + } + + public void test1() throws Exception { + // first run for just in time compiler + int resetCounter = 0; + int pauseCounter = 0; + for (int i = 0; i < loopNumber; i++) { + try { + oos.writeObject(buildNewAccessEvent()); + oos.flush(); + if (++resetCounter >= resetFrequency) { + oos.reset(); + resetCounter = 0; + } + if (++pauseCounter >= pauseFrequency) { + Thread.sleep(pauseLengthInMillis); + pauseCounter = 0; + } + + } catch (IOException ex) { + fail(ex.getMessage()); + } + } + + // second run + Long t1; + Long t2; + Long total = 0L; + resetCounter = 0; + pauseCounter = 0; + // System.out.println("Beginning mesured run"); + for (int i = 0; i < loopNumber; i++) { + try { + t1 = System.nanoTime(); + oos.writeObject(buildNewAccessEvent()); + oos.flush(); + t2 = System.nanoTime(); + total += (t2 - t1); + if (++resetCounter >= resetFrequency) { + oos.reset(); + resetCounter = 0; + } + if (++pauseCounter >= pauseFrequency) { + Thread.sleep(pauseLengthInMillis); + pauseCounter = 0; + } + } catch (IOException ex) { + fail(ex.getMessage()); + } + } + total /= 1000; + System.out.println("Loop done : average time = " + total / loopNumber + + " microsecs after " + loopNumber + " writes."); + } + + private AccessEvent buildNewAccessEvent() { + DummyRequest request = new DummyRequest(); + DummyResponse response = new DummyResponse(); + DummyServerAdapter adapter = new DummyServerAdapter(request, response); + + AccessEvent ae = new AccessEvent(request, response, adapter); + return ae; + } + +} Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java ============================================================================== --- (empty file) +++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java Mon Nov 27 16:38:52 2006 @@ -0,0 +1,77 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 1999-2006, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ +package ch.qos.logback.access.net; + +import junit.framework.TestCase; +import ch.qos.logback.access.pattern.helpers.DummyRequest; +import ch.qos.logback.access.pattern.helpers.DummyResponse; +import ch.qos.logback.access.pattern.helpers.DummyServerAdapter; +import ch.qos.logback.access.spi.AccessEvent; +import ch.qos.logback.access.spi.BasicContext; + + +public class SocketAppenderTest extends TestCase { + + private BasicContext context; + private MockSocketServer mockSocketServer; + + public void testStartFailNoRemoteHost() { + context = new BasicContext(); + SocketAppender appender = new SocketAppender(); + appender.setContext(context); + appender.setPort(123); + appender.start(); + assertEquals(1, context.getStatusManager().getCount()); + } + + public void testRecieveMessage() throws InterruptedException { + startServer(1); + configureClient(); + + context.callAppenders(buildNewAccessEvent()); + // Wait max 2 seconds for mock server to finish. However, it should + // finish much sooner than that. + mockSocketServer.join(2000); + assertTrue(mockSocketServer.finished); + assertEquals(1, mockSocketServer.accessEventList.size()); + + AccessEvent remoteEvent = mockSocketServer.accessEventList.get(0); + assertEquals("headerValue1", remoteEvent.getRequestHeader("headerName1")); + assertEquals("testHost", remoteEvent.getRemoteHost()); + } + + private void startServer(int expectedEventNumber) throws InterruptedException { + mockSocketServer = new MockSocketServer(expectedEventNumber); + mockSocketServer.start(); + // give MockSocketServer head start + Thread.sleep(100); + } + + private void configureClient() { + context = new BasicContext(); + context.setName("test"); + SocketAppender socketAppender = new SocketAppender(); + socketAppender.setContext(context); + socketAppender.setName("socket"); + socketAppender.setPort(MockSocketServer.PORT); + socketAppender.setRemoteHost("localhost"); + context.addAppender(socketAppender); + socketAppender.start(); + } + + private AccessEvent buildNewAccessEvent() { + DummyRequest request = new DummyRequest(); + DummyResponse response = new DummyResponse(); + DummyServerAdapter adapter = new DummyServerAdapter(request, response); + + AccessEvent ae = new AccessEvent(request, response, adapter); + return ae; + } +}