On Wed, Mar 9, 2016 at 3:35 AM, <[email protected]> wrote:

> Unit test for GelfLayout.encode
>
>
> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
> Commit:
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/58152b79
> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/58152b79
> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/58152b79
>
> Branch: refs/heads/gelf-layout-gc-free
> Commit: 58152b79b0c883ba6df57b06bbb4e2c96353232e
> Parents: 7467e5d
> Author: Mikael Ståldal <[email protected]>
> Authored: Tue Mar 8 17:34:43 2016 +0100
> Committer: Mikael Ståldal <[email protected]>
> Committed: Tue Mar 8 17:34:43 2016 +0100
>
> ----------------------------------------------------------------------
>  .../log4j/core/layout/GelfLayoutTest.java       | 75 +++++++++++---------
>  .../test/appender/EncodingListAppender.java     | 64 +++++++++++++++++
>  .../log4j/test/appender/ListAppender.java       |  9 ++-
>  3 files changed, 112 insertions(+), 36 deletions(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
> ----------------------------------------------------------------------
> diff --git
> a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
> b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
> index 2aa7eda..c82fa21 100644
> ---
> a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
> +++
> b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
> @@ -16,32 +16,28 @@
>   */
>  package org.apache.logging.log4j.core.layout;
>
> -import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
> -
> -import java.io.ByteArrayInputStream;
> -import java.io.IOException;
> -import java.io.InputStream;
> -import java.util.List;
> -import java.util.zip.GZIPInputStream;
> -import java.util.zip.InflaterInputStream;
> -
> +import com.fasterxml.jackson.core.io.JsonStringEncoder;
>  import org.apache.commons.io.IOUtils;
>  import org.apache.logging.log4j.Level;
>  import org.apache.logging.log4j.ThreadContext;
> -import org.apache.logging.log4j.core.Appender;
> -import org.apache.logging.log4j.core.BasicConfigurationFactory;
> -import org.apache.logging.log4j.core.LogEvent;
> -import org.apache.logging.log4j.core.Logger;
> -import org.apache.logging.log4j.core.LoggerContext;
> +import org.apache.logging.log4j.core.*;
>  import org.apache.logging.log4j.core.config.ConfigurationFactory;
>  import org.apache.logging.log4j.core.layout.GelfLayout.CompressionType;
>  import org.apache.logging.log4j.core.util.KeyValuePair;
> +import org.apache.logging.log4j.test.appender.EncodingListAppender;
>  import org.apache.logging.log4j.test.appender.ListAppender;
>  import org.junit.AfterClass;
>  import org.junit.BeforeClass;
>  import org.junit.Test;
>
> -import com.fasterxml.jackson.core.io.JsonStringEncoder;
> +import java.io.ByteArrayInputStream;
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.util.List;
> +import java.util.zip.GZIPInputStream;
> +import java.util.zip.InflaterInputStream;
> +
> +import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
>
>  public class GelfLayoutTest {
>      static ConfigurationFactory configFactory = new
> BasicConfigurationFactory();
> @@ -85,18 +81,20 @@ public class GelfLayoutTest {
>          final GelfLayout layout = GelfLayout.createLayout(HOSTNAME, new
> KeyValuePair[] {
>                  new KeyValuePair(KEY1, VALUE1),
>                  new KeyValuePair(KEY2, VALUE2), }, compressionType, 1024);
> -        // ConsoleAppender appender = new ConsoleAppender("Console",
> layout);
>          final ListAppender eventAppender = new ListAppender("Events",
> null, null, true, false);
>          final ListAppender rawAppender = new ListAppender("Raw", null,
> layout, true, true);
>          final ListAppender formattedAppender = new
> ListAppender("Formatted", null, layout, true, false);
> +        final EncodingListAppender encodedAppender = new
> EncodingListAppender("Encoded", null, layout, false, true);
>          eventAppender.start();
>          rawAppender.start();
>          formattedAppender.start();
> +        encodedAppender.start();
>
>          // set appenders on root and set level to debug
>          root.addAppender(eventAppender);
>          root.addAppender(rawAppender);
>          root.addAppender(formattedAppender);
> +        root.addAppender(encodedAppender);
>          root.setLevel(Level.DEBUG);
>
>          root.debug(LINE1);
> @@ -116,6 +114,7 @@ public class GelfLayoutTest {
>          final List<LogEvent> events = eventAppender.getEvents();
>          final List<byte[]> raw = rawAppender.getData();
>          final List<String> messages = formattedAppender.getMessages();
> +        final List<byte[]> raw2 = encodedAppender.getData();
>          final String threadName = Thread.currentThread().getName();
>
>          //@formatter:off
> @@ -148,42 +147,52 @@ public class GelfLayoutTest {
>                  messages.get(1));
>          //@formatter:on
>          final byte[] compressed = raw.get(2);
> +        final byte[] compressed2 = raw2.get(2);
>          final ByteArrayInputStream bais = new
> ByteArrayInputStream(compressed);
> -        InputStream inflaterStream = null;
> +        final ByteArrayInputStream bais2 = new
> ByteArrayInputStream(compressed2);
> +        InputStream inflaterStream;
> +        InputStream inflaterStream2;
>          switch (compressionType) {
>          case GZIP:
>              inflaterStream = new GZIPInputStream(bais);
> +            inflaterStream2 = new GZIPInputStream(bais2);
>              break;
>          case ZLIB:
>              inflaterStream = new InflaterInputStream(bais);
> +            inflaterStream2 = new InflaterInputStream(bais2);
>              break;
>          case OFF:
>              inflaterStream = bais;
> +            inflaterStream2 = bais2;
>              break;
>          default:
>              throw new IllegalStateException("Missing test case clause");
>          }
>          final byte[] uncompressed = IOUtils.toByteArray(inflaterStream);
> +        final byte[] uncompressed2 = IOUtils.toByteArray(inflaterStream2);
>          inflaterStream.close();
> +        inflaterStream2.close();
>          final String uncompressedString = new String(uncompressed,
> layout.getCharset());
> +        final String uncompressedString2 = new String(uncompressed2,
> layout.getCharset());
>          //@formatter:off
> -        assertJsonEquals("{" +
> -                        "\"version\": \"1.1\"," +
> -                        "\"host\": \"" + HOSTNAME + "\"," +
> -                        "\"timestamp\": " +
> GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
> -                        "\"level\": 3," +
> -                        "\"_thread\": \"" + threadName + "\"," +
> -                        "\"_logger\": \"\"," +
> -                        "\"short_message\": \"" + LINE3 + "\"," +
> -                        "\"full_message\": \"" +
> String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
> -                                GelfLayout.formatThrowable(exception))) +
> "\"," +
> -                        "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
> -                        "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
> -                        "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
> -                        "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
> -                        "}",
> -                uncompressedString);
> +        String expected = "{" +
> +                "\"version\": \"1.1\"," +
> +                "\"host\": \"" + HOSTNAME + "\"," +
> +                "\"timestamp\": " +
> GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
> +                "\"level\": 3," +
> +                "\"_thread\": \"" + threadName + "\"," +
> +                "\"_logger\": \"\"," +
> +                "\"short_message\": \"" + LINE3 + "\"," +
> +                "\"full_message\": \"" +
> String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
> +                GelfLayout.formatThrowable(exception))) + "\"," +
> +                "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
> +                "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
> +                "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
> +                "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
> +                "}";
>          //@formatter:on
> +        assertJsonEquals(expected, uncompressedString);
> +        assertJsonEquals(expected, uncompressedString2);
>      }
>
>      @Test
>
>
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> ----------------------------------------------------------------------
> diff --git
> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> new file mode 100644
> index 0000000..810e18f
> --- /dev/null
> +++
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> @@ -0,0 +1,64 @@
> +package org.apache.logging.log4j.test.appender;
> +
> +import org.apache.logging.log4j.core.Filter;
> +import org.apache.logging.log4j.core.Layout;
> +import org.apache.logging.log4j.core.LogEvent;
> +import org.apache.logging.log4j.core.layout.ByteBufferDestination;
> +import org.apache.logging.log4j.core.layout.SerializedLayout;
> +
> +import java.io.Serializable;
> +import java.nio.ByteBuffer;
> +
> +/**
> + * This appender is primarily used for testing. Use in a real environment
> is discouraged as the
> + * List could eventually grow to cause an OutOfMemoryError.
> + *
> + * This appender will use {@link Layout#encode(Object,
> ByteBufferDestination)} (and not {@link Layout#toByteArray(LogEvent)}).
> + */
> +public class EncodingListAppender extends ListAppender {
> +
> +    public EncodingListAppender(String name) {
> +        super(name);
> +    }
> +
> +    public EncodingListAppender(String name, Filter filter, Layout<?
> extends Serializable> layout, boolean newline, boolean raw) {
> +        super(name, filter, layout, newline, raw);
> +    }
> +
> +    private class Destination implements ByteBufferDestination {
> +        ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4096]);
> +        @Override
> +        public ByteBuffer getByteBuffer() {
> +            return byteBuffer;
> +        }
> +
> +        @Override
> +        public ByteBuffer drain(final ByteBuffer buf) {
> +            throw new IllegalStateException("Unexpected message larger
> than 4096 bytes");
> +        }
> +    }
> +
> +    @Override
> +    public synchronized void append(final LogEvent event) {
> +        final Layout<? extends Serializable> layout = getLayout();
> +        if (layout == null) {
> +            events.add(event);
> +        } else if (layout instanceof SerializedLayout) {
> +            Destination content = new Destination();
> +            content.byteBuffer.put(layout.getHeader());
> +            layout.encode(event, content);
> +            content.getByteBuffer().rewind();
> +            byte[] record = new byte[content.getByteBuffer().remaining()];
> +            content.getByteBuffer().get(record);
> +            data.add(record);
>
I think there is a bug here. ByteBuffer.rewind() does not change limit, it
just sets the position back to zero. (Meaning you no longer know how many
bytes were put into the buffer.) I believe you want to use
ByteBuffer.flip() instead of rewind().
If you use flip(), the limit is set to the current position before the
position is reset to zero. After a flip(), the remaining() method will
return the difference between the limit and the current position, which is
what you want: the number of bytes you just wrote into the buffer.



> +        } else {
> +            Destination content = new Destination();
> +            layout.encode(event, content);
> +            content.getByteBuffer().rewind();
> +            byte[] record = new byte[content.getByteBuffer().remaining()];
> +            content.getByteBuffer().get(record);
> +            write(record);
> +        }
> +    }
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> ----------------------------------------------------------------------
> diff --git
> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> index 05fa157..cd9ec82 100644
> ---
> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> +++
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> @@ -36,6 +36,9 @@ import
> org.apache.logging.log4j.core.layout.SerializedLayout;
>  /**
>   * This appender is primarily used for testing. Use in a real environment
> is discouraged as the
>   * List could eventually grow to cause an OutOfMemoryError.
> + *
> + * This appender will use {@link Layout#toByteArray(LogEvent)}.
> + *
>   * @see
> org.apache.logging.log4j.junit.LoggerContextRule#getListAppender(String)
> ILC.getListAppender
>   */
>  @Plugin(name = "List", category = "Core", elementType = "appender",
> printObject = true)
> @@ -45,11 +48,11 @@ public class ListAppender extends AbstractAppender {
>
>      // Use CopyOnWriteArrayList?
>
> -    private final List<LogEvent> events = new ArrayList<>();
> +    final List<LogEvent> events = new ArrayList<>();
>
>      private final List<String> messages = new ArrayList<>();
>
> -    private final List<byte[]> data = new ArrayList<>();
> +    final List<byte[]> data = new ArrayList<>();
>
>      private final boolean newLine;
>
> @@ -93,7 +96,7 @@ public class ListAppender extends AbstractAppender {
>          }
>      }
>
> -    private void write(final byte[] bytes) {
> +    void write(final byte[] bytes) {
>          if (raw) {
>              data.add(bytes);
>              return;
>
>

Reply via email to