You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2018/02/20 02:09:29 UTC
[12/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based
layouts to their own modules: JSON, XML, and YAML.
[LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON,
XML, and YAML.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/0eb5212e
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/0eb5212e
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/0eb5212e
Branch: refs/heads/master
Commit: 0eb5212e4ac56030f07e88b9de432977e3808e48
Parents: ec3c623
Author: Gary Gregory <ga...@gmail.com>
Authored: Mon Feb 19 19:09:06 2018 -0700
Committer: Gary Gregory <ga...@gmail.com>
Committed: Mon Feb 19 19:09:06 2018 -0700
----------------------------------------------------------------------
log4j-bom/pom.xml | 24 +
log4j-core-its/pom.xml | 24 +-
.../log4j/core/appender/HttpAppenderTest.java | 316 ++++++++++++
.../appender/JsonCompleteFileAppenderTest.java | 110 +++++
.../SecureSocketAppenderSocketOptionsTest.java | 140 ++++++
.../appender/SocketAppenderBufferSizeTest.java | 77 +++
.../SocketAppenderSocketOptionsTest.java | 109 +++++
.../log4j/core/appender/SocketAppenderTest.java | 412 ++++++++++++++++
.../appender/XmlCompactFileAppenderTest.java | 82 ++++
.../XmlCompactFileAppenderValidationTest.java | 106 ++++
...lCompactFileAsyncAppenderValidationTest.java | 83 ++++
.../appender/XmlCompleteFileAppenderTest.java | 173 +++++++
.../core/appender/XmlFileAppenderTest.java | 76 +++
.../XmlRandomAccessFileAppenderTest.java | 90 ++++
log4j-core/pom.xml | 6 -
.../ContextDataAsEntryListDeserializer.java | 57 ---
.../ContextDataAsEntryListSerializer.java | 58 ---
.../core/jackson/ContextDataDeserializer.java | 65 ---
.../core/jackson/ContextDataSerializer.java | 64 ---
.../jackson/ExtendedStackTraceElementMixIn.java | 90 ----
.../log4j/core/jackson/Initializers.java | 98 ----
.../log4j/core/jackson/InstantMixIn.java | 53 --
.../log4j/core/jackson/JsonConstants.java | 35 --
.../logging/log4j/core/jackson/LevelMixIn.java | 44 --
.../jackson/ListOfMapEntryDeserializer.java | 55 ---
.../core/jackson/ListOfMapEntrySerializer.java | 54 --
.../log4j/core/jackson/Log4jJsonModule.java | 61 ---
.../core/jackson/Log4jJsonObjectMapper.java | 47 --
.../Log4jStackTraceElementDeserializer.java | 82 ----
.../log4j/core/jackson/Log4jXmlModule.java | 50 --
.../core/jackson/Log4jXmlObjectMapper.java | 48 --
.../log4j/core/jackson/Log4jYamlModule.java | 59 ---
.../core/jackson/Log4jYamlObjectMapper.java | 48 --
.../log4j/core/jackson/LogEventJsonMixIn.java | 156 ------
.../jackson/LogEventWithContextListMixIn.java | 155 ------
.../logging/log4j/core/jackson/MapEntry.java | 110 -----
.../logging/log4j/core/jackson/MarkerMixIn.java | 76 ---
.../log4j/core/jackson/MessageSerializer.java | 47 --
.../MutableThreadContextStackDeserializer.java | 51 --
.../core/jackson/ObjectMessageSerializer.java | 47 --
.../core/jackson/SimpleMessageDeserializer.java | 47 --
.../core/jackson/StackTraceElementMixIn.java | 62 ---
.../log4j/core/jackson/ThrowableProxyMixIn.java | 80 ---
...rowableProxyWithStacktraceAsStringMixIn.java | 78 ---
.../ThrowableProxyWithoutStacktraceMixIn.java | 77 ---
.../log4j/core/jackson/XmlConstants.java | 39 --
.../log4j/core/jackson/package-info.java | 21 -
.../core/layout/AbstractJacksonLayout.java | 350 -------------
.../logging/log4j/core/layout/GelfLayout.java | 2 +-
.../log4j/core/layout/JacksonFactory.java | 237 ---------
.../logging/log4j/core/layout/JsonLayout.java | 293 -----------
.../logging/log4j/core/layout/XmlLayout.java | 208 --------
.../logging/log4j/core/layout/YamlLayout.java | 206 --------
.../parser/AbstractJacksonLogEventParser.java | 4 +-
.../log4j/core/parser/JsonLogEventParser.java | 31 --
.../log4j/core/parser/XmlLogEventParser.java | 31 --
.../log4j/core/parser/YamlLogEventParser.java | 31 --
.../logging/log4j/MarkerMixInJsonTest.java | 33 --
.../apache/logging/log4j/MarkerMixInTest.java | 94 ----
.../logging/log4j/MarkerMixInXmlTest.java | 34 --
.../logging/log4j/MarkerMixInYamlTest.java | 34 --
.../log4j/core/appender/HttpAppenderTest.java | 316 ------------
.../appender/JsonCompleteFileAppenderTest.java | 110 -----
.../SecureSocketAppenderSocketOptionsTest.java | 140 ------
.../appender/SocketAppenderBufferSizeTest.java | 77 ---
.../SocketAppenderSocketOptionsTest.java | 109 -----
.../log4j/core/appender/SocketAppenderTest.java | 411 ----------------
.../appender/XmlCompactFileAppenderTest.java | 81 ---
.../XmlCompactFileAppenderValidationTest.java | 106 ----
...lCompactFileAsyncAppenderValidationTest.java | 83 ----
.../appender/XmlCompleteFileAppenderTest.java | 172 -------
.../core/appender/XmlFileAppenderTest.java | 78 ---
.../XmlRandomAccessFileAppenderTest.java | 89 ----
.../log4j/core/impl/ThrowableProxyTest.java | 18 +-
.../jackson/JacksonIssue429MyNamesTest.java | 130 -----
.../log4j/core/jackson/JacksonIssue429Test.java | 95 ----
.../log4j/core/jackson/LevelMixInJsonTest.java | 32 --
.../log4j/core/jackson/LevelMixInTest.java | 106 ----
.../log4j/core/jackson/LevelMixInXmlTest.java | 35 --
.../log4j/core/jackson/LevelMixInYamlTest.java | 32 --
.../jackson/StackTraceElementMixInTest.java | 92 ----
.../ConcurrentLoggingWithJsonLayoutTest.java | 116 -----
.../log4j/core/layout/JsonLayoutTest.java | 487 ------------------
.../log4j/core/layout/LogEventFixtures.java | 6 +-
.../log4j/core/layout/XmlLayoutTest.java | 387 ---------------
.../log4j/core/layout/YamlLayoutTest.java | 380 --------------
.../core/parser/AbstractLogEventParserTest.java | 59 +++
.../core/parser/JsonLogEventParserTest.java | 130 -----
.../log4j/core/parser/LogEventParserTest.java | 55 ---
.../core/parser/XmlLogEventParserTest.java | 130 -----
.../core/parser/YamlLogEventParserTest.java | 126 -----
.../src/test/resources/log4j2-xml-layout.xml | 31 ++
log4j-layout-jackson-json/pom.xml | 167 +++++++
.../json/JsonSetupContextInitializer.java | 51 ++
.../log4j/jackson/json/Log4jJsonModule.java | 58 +++
.../jackson/json/Log4jJsonObjectMapper.java | 47 ++
.../jackson/json/layout/JsonJacksonFactory.java | 60 +++
.../log4j/jackson/json/layout/JsonLayout.java | 327 +++++++++++++
.../jackson/json/parser/JsonLogEventParser.java | 32 ++
.../src/site/manual/index.md | 33 ++
log4j-layout-jackson-json/src/site/site.xml | 52 ++
.../json/JacksonIssue429MyNamesTest.java | 130 +++++
.../log4j/jackson/json/JacksonIssue429Test.java | 95 ++++
.../log4j/jackson/json/LevelMixInJsonTest.java | 34 ++
.../log4j/jackson/json/MarkerMixInJsonTest.java | 34 ++
.../json/StackTraceElementJsonMixInTest.java | 83 ++++
.../ConcurrentLoggingWithJsonLayoutTest.java | 117 +++++
.../jackson/json/layout/JsonLayoutTest.java | 489 +++++++++++++++++++
.../json/layout/ThrowableProxyJsonTest.java | 33 ++
.../json/parser/JsonLogEventParserTest.java | 132 +++++
.../src/test/resources/log4j2-json-layout.xml | 31 ++
.../log4j/jackson/xml/Log4jXmlModule.java | 49 ++
.../log4j/jackson/xml/Log4jXmlObjectMapper.java | 48 ++
.../log4j/jackson/xml/XmlInstantMixIn.java | 56 +++
.../xml/XmlLogEventWithContextListMixIn.java | 50 ++
.../log4j/jackson/xml/XmlMarkerMixIn.java | 79 +++
.../jackson/xml/XmlSetupContextInitializer.java | 42 ++
.../jackson/xml/XmlStackTraceElementMixIn.java | 39 ++
.../xml/layout/Log4jXmlPrettyPrinter.java | 41 ++
.../jackson/xml/layout/XmlJacksonFactory.java | 54 ++
.../log4j/jackson/xml/layout/XmlLayout.java | 226 +++++++++
.../jackson/xml/parser/XmlLogEventParser.java | 32 ++
log4j-layout-jackson-xml/pom.xml | 171 +++++++
.../jackson/xml/AbstractLogEventXmlMixIn.java | 135 +++++
.../ContextDataAsEntryListXmlSerializer.java | 37 ++
.../xml/ExtendedStackTraceElementXmlMixIn.java | 68 +++
.../log4j/jackson/xml/InstantXmlMixIn.java | 56 +++
.../log4j/jackson/xml/Log4jXmlModule.java | 52 ++
.../log4j/jackson/xml/Log4jXmlObjectMapper.java | 48 ++
.../xml/LogEventWithContextListXmlMixIn.java | 48 ++
.../log4j/jackson/xml/MarkerXmlMixIn.java | 79 +++
.../jackson/xml/StackTraceElementXmlMixIn.java | 40 ++
...ableProxyWithStacktraceAsStringXmlMixIn.java | 77 +++
...ThrowableProxyWithoutStacktraceXmlMixIn.java | 60 +++
.../jackson/xml/ThrowableProxyXmlMixIn.java | 78 +++
.../logging/log4j/jackson/xml/XmlMapEntry.java | 41 ++
.../jackson/xml/XmlSetupContextInitializer.java | 38 ++
.../xml/layout/Log4jXmlPrettyPrinter.java | 41 ++
.../jackson/xml/layout/XmlJacksonFactory.java | 54 ++
.../log4j/jackson/xml/layout/XmlLayout.java | 226 +++++++++
.../jackson/xml/parser/XmlLogEventParser.java | 32 ++
.../src/site/manual/index.md | 33 ++
log4j-layout-jackson-xml/src/site/site.xml | 52 ++
.../log4j/jackson/xml/LevelMixInXmlTest.java | 36 ++
.../log4j/jackson/xml/MarkerMixInXmlTest.java | 34 ++
.../xml/StackTraceElementXmlMixInTest.java | 82 ++++
.../ConcurrentLoggingWithXmlLayoutTest.java | 116 +++++
.../xml/layout/ThrowableProxyXmlTest.java | 33 ++
.../log4j/jackson/xml/layout/XmlLayoutTest.java | 440 +++++++++++++++++
.../xml/parser/XmlLogEventParserTest.java | 132 +++++
.../src/test/resources/log4j2-xml-layout.xml | 31 ++
log4j-layout-jackson-yaml/pom.xml | 171 +++++++
.../log4j/jackson/yaml/Log4jYamlModule.java | 59 +++
.../jackson/yaml/Log4jYamlObjectMapper.java | 48 ++
.../yaml/YamlSetupContextInitializer.java | 47 ++
.../jackson/yaml/layout/YamlConstants.java | 35 ++
.../jackson/yaml/layout/YamlJacksonFactory.java | 68 +++
.../log4j/jackson/yaml/layout/YamlLayout.java | 239 +++++++++
.../jackson/yaml/parser/YamlLogEventParser.java | 32 ++
.../src/site/manual/index.md | 33 ++
log4j-layout-jackson-yaml/src/site/site.xml | 52 ++
.../log4j/jackson/yaml/LevelMixInYamlTest.java | 34 ++
.../log4j/jackson/yaml/MarkerMixInYamlTest.java | 34 ++
.../yaml/StackTraceElementYamlMixInTest.java | 83 ++++
.../ConcurrentLoggingWithYamlLayoutTest.java | 113 +++++
.../jackson/yaml/layout/YamlLayoutTest.java | 382 +++++++++++++++
.../yaml/parser/YamlLogEventParserTest.java | 128 +++++
.../src/test/resources/log4j2-yaml-layout.xml | 31 ++
log4j-layout-jackson/pom.xml | 214 ++++++++
.../log4j/jackson/AbstractJacksonFactory.java | 74 +++
.../log4j/jackson/AbstractJacksonLayout.java | 351 +++++++++++++
.../log4j/jackson/AbstractLogEventMixIn.java | 84 ++++
.../ContextDataAsEntryListDeserializer.java | 57 +++
.../ContextDataAsEntryListSerializer.java | 67 +++
.../log4j/jackson/ContextDataDeserializer.java | 65 +++
.../log4j/jackson/ContextDataSerializer.java | 64 +++
.../jackson/ExtendedStackTraceElementMixIn.java | 100 ++++
.../logging/log4j/jackson/InstantMixIn.java | 55 +++
.../logging/log4j/jackson/JsonConstants.java | 36 ++
.../logging/log4j/jackson/LevelMixIn.java | 44 ++
.../jackson/ListOfMapEntryDeserializer.java | 55 +++
.../log4j/jackson/ListOfMapEntrySerializer.java | 58 +++
.../Log4jStackTraceElementDeserializer.java | 82 ++++
.../log4j/jackson/LogEventJsonMixIn.java | 146 ++++++
.../jackson/LogEventWithContextListMixIn.java | 130 +++++
.../apache/logging/log4j/jackson/MapEntry.java | 109 +++++
.../logging/log4j/jackson/MarkerMixIn.java | 71 +++
.../log4j/jackson/MessageSerializer.java | 47 ++
.../MutableThreadContextStackDeserializer.java | 51 ++
.../log4j/jackson/ObjectMessageSerializer.java | 47 ++
.../log4j/jackson/SetupContextInitializer.java | 38 ++
.../jackson/SimpleMessageDeserializer.java | 47 ++
.../log4j/jackson/SimpleModuleInitializer.java | 26 +
.../jackson/StackTraceElementConstants.java | 30 ++
.../log4j/jackson/StackTraceElementMixIn.java | 59 +++
.../log4j/jackson/ThrowableProxyMixIn.java | 70 +++
...rowableProxyWithStacktraceAsStringMixIn.java | 70 +++
.../ThrowableProxyWithoutStacktraceMixIn.java | 69 +++
.../logging/log4j/jackson/XmlConstants.java | 39 ++
.../jackson/layout/AbstractJacksonLayout.java | 378 ++++++++++++++
.../logging/log4j/jackson/package-info.java | 21 +
log4j-layout-jackson/src/site/manual/index.md | 33 ++
log4j-layout-jackson/src/site/site.xml | 52 ++
.../log4j/jackson/AbstractMarkerMixInTest.java | 97 ++++
.../logging/log4j/jackson/LevelMixInTest.java | 106 ++++
.../jackson/ThrowableProxyJacksonTest.java | 51 ++
pom.xml | 4 +
src/changes/changes.xml | 3 +
208 files changed, 11800 insertions(+), 7829 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-bom/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-bom/pom.xml b/log4j-bom/pom.xml
index 97021b2..5ee35e8 100644
--- a/log4j-bom/pom.xml
+++ b/log4j-bom/pom.xml
@@ -42,6 +42,30 @@
<artifactId>log4j-core</artifactId>
<version>${project.version}</version>
</dependency>
+ <!-- Commons code for Jackson-based layouts -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-layout-jackson</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- Jackson-based JSON layout -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-layout-jackson-json</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- Jackson-based XML layout -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-layout-jackson-xml</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- Jackson-based YAML layout -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-layout-jackson-yaml</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<!-- Legacy Log4j 1.2 API -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-core-its/pom.xml b/log4j-core-its/pom.xml
index 2a0cec1..513fce3 100644
--- a/log4j-core-its/pom.xml
+++ b/log4j-core-its/pom.xml
@@ -29,13 +29,14 @@
<description>Integration Tests for the Apache Log4j Implementation</description>
<properties>
<log4jParentDir>${basedir}/..</log4jParentDir>
- <docLabel>Core Documentation</docLabel>
- <projectDir>/core</projectDir>
+ <docLabel>Core Integration Tests Documentation</docLabel>
+ <projectDir>/log4j-core-its</projectDir>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
@@ -46,6 +47,19 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-layout-jackson-json</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-layout-jackson-xml</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
@@ -53,6 +67,12 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <!-- Used for testing HttpAppender -->
+ <dependency>
+ <groupId>com.github.tomakehurst</groupId>
+ <artifactId>wiremock</artifactId>
+ <scope>test</scope>
+ </dependency>
<!-- Required for AsyncLoggers -->
<dependency>
<groupId>com.lmax</groupId>
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
new file mode 100644
index 0000000..4e9a07c
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.containing;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.lookup.JavaLookup;
+import org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration;
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+import org.apache.logging.log4j.core.net.ssl.TestConstants;
+import org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration;
+import org.apache.logging.log4j.jackson.json.layout.JsonLayout;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.status.StatusData;
+import org.apache.logging.log4j.status.StatusListener;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+@Ignore("Fails often on Windows")
+
+/* Fails often on Windows, for example:
+[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.20.1:test (default-test) on project log4j-core: There are test failures.
+[ERROR]
+[ERROR] Please refer to C:\vcs\git\apache\logging\logging-log4j2\log4j-core\target\surefire-reports for the individual test results.
+[ERROR] Please refer to dump files (if any exist) [date]-jvmRun[N].dump, [date].dumpstream and [date]-jvmRun[N].dumpstream.
+[ERROR] ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
+[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
+[ERROR] Process Exit Code: 0
+[ERROR] Crashed tests:
+[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
+[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
+[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
+[ERROR] Process Exit Code: 0
+[ERROR] Crashed tests:
+[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.awaitResultsDone(ForkStarter.java:496)
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.runSuitesForkPerTestSet(ForkStarter.java:443)
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:295)
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:246)
+[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1124)
+[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:954)
+[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:832)
+[ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
+[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
+[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
+[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
+[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
+[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
+[ERROR] at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
+[ERROR] at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
+[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:309)
+[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:194)
+[ERROR] at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:107)
+[ERROR] at org.apache.maven.cli.MavenCli.execute(MavenCli.java:955)
+[ERROR] at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:290)
+[ERROR] at org.apache.maven.cli.MavenCli.main(MavenCli.java:194)
+[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+[ERROR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+[ERROR] at java.lang.reflect.Method.invoke(Method.java:498)
+[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
+[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
+[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
+[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
+[ERROR] Caused by: org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
+[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
+[ERROR] Process Exit Code: 0
+[ERROR] Crashed tests:
+[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:686)
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:535)
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.access$700(ForkStarter.java:116)
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:431)
+[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:408)
+[ERROR] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
+[ERROR] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+[ERROR] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+[ERROR] at java.lang.Thread.run(Thread.java:748)
+[ERROR]
+[ERROR] -> [Help 1]
+[ERROR]
+[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
+[ERROR] Re-run Maven using the -X switch to enable full debug logging.
+[ERROR]
+[ERROR] For more information about the errors and possible solutions, please read the following articles:
+[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
+[ERROR]
+[ERROR] After correcting the problems, you can resume the build with the command
+[ERROR] mvn <goals> -rf :log4j-core
+ */
+public class HttpAppenderTest {
+
+ private static final String LOG_MESSAGE = "Hello, world!";
+
+ private static Log4jLogEvent createLogEvent() {
+ return Log4jLogEvent.newBuilder()
+ .setLoggerName(HttpAppenderTest.class.getName())
+ .setLoggerFqcn(HttpAppenderTest.class.getName())
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage(LOG_MESSAGE))
+ .build();
+ }
+
+ private final ResponseDefinitionBuilder SUCCESS_RESPONSE = aResponse().withStatus(201)
+ .withHeader("Content-Type", "application/json")
+ .withBody("{\"status\":\"created\"}");
+
+ private final ResponseDefinitionBuilder FAILURE_RESPONSE = aResponse().withStatus(400)
+ .withHeader("Content-Type", "application/json")
+ .withBody("{\"status\":\"error\"}");
+
+ private final JavaLookup JAVA_LOOKUP = new JavaLookup();
+
+ @Rule
+ public LoggerContextRule ctx = new LoggerContextRule("HttpAppenderTest.xml");
+
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort()
+ .keystorePath(TestConstants.KEYSTORE_FILE)
+ .keystorePassword(String.valueOf(TestConstants.KEYSTORE_PWD()))
+ .keystoreType(TestConstants.KEYSTORE_TYPE));
+
+ @Test
+ public void testAppend() throws Exception {
+ wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+ .willReturn(SUCCESS_RESPONSE));
+
+ final Appender appender = HttpAppender.newBuilder()
+ .withName("Http")
+ .withLayout(JsonLayout.createDefaultLayout())
+ .setConfiguration(ctx.getConfiguration())
+ .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+ .build();
+ appender.append(createLogEvent());
+
+ wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+ .withHeader("Host", containing("localhost"))
+ .withHeader("Content-Type", containing("application/json"))
+ .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+ }
+
+ @Test
+ public void testAppendHttps() throws Exception {
+ wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+ .willReturn(SUCCESS_RESPONSE));
+
+ final Appender appender = HttpAppender.newBuilder()
+ .withName("Http")
+ .withLayout(JsonLayout.createDefaultLayout())
+ .setConfiguration(ctx.getConfiguration())
+ .setUrl(new URL("https://localhost:" + wireMockRule.httpsPort() + "/test/log4j/"))
+ .setSslConfiguration(SslConfiguration.createSSLConfiguration(null,
+ KeyStoreConfiguration.createKeyStoreConfiguration(TestConstants.KEYSTORE_FILE, TestConstants.KEYSTORE_PWD(), TestConstants.KEYSTORE_TYPE, null),
+ TrustStoreConfiguration.createKeyStoreConfiguration(TestConstants.TRUSTSTORE_FILE, TestConstants.TRUSTSTORE_PWD(), TestConstants.TRUSTSTORE_TYPE, null)))
+ .setVerifyHostname(false)
+ .build();
+ appender.append(createLogEvent());
+
+ wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+ .withHeader("Host", containing("localhost"))
+ .withHeader("Content-Type", containing("application/json"))
+ .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+ }
+
+ @Test
+ public void testAppendMethodPut() throws Exception {
+ wireMockRule.stubFor(put(urlEqualTo("/test/log4j/1234"))
+ .willReturn(SUCCESS_RESPONSE));
+
+ final Appender appender = HttpAppender.newBuilder()
+ .withName("Http")
+ .withLayout(JsonLayout.createDefaultLayout())
+ .setConfiguration(ctx.getConfiguration())
+ .setMethod("PUT")
+ .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/1234"))
+ .build();
+ appender.append(createLogEvent());
+
+ wireMockRule.verify(putRequestedFor(urlEqualTo("/test/log4j/1234"))
+ .withHeader("Host", containing("localhost"))
+ .withHeader("Content-Type", containing("application/json"))
+ .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+ }
+
+ @Test
+ public void testAppendCustomHeader() throws Exception {
+ wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+ .willReturn(SUCCESS_RESPONSE));
+
+ final Appender appender = HttpAppender.newBuilder()
+ .withName("Http")
+ .withLayout(JsonLayout.createDefaultLayout())
+ .setConfiguration(ctx.getConfiguration())
+ .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+ .setHeaders(new Property[] {
+ Property.createProperty("X-Test", "header value"),
+ Property.createProperty("X-Runtime", "${java:runtime}")
+ })
+ .build();
+ appender.append(createLogEvent());
+
+ wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+ .withHeader("Host", containing("localhost"))
+ .withHeader("X-Test", equalTo("header value"))
+ .withHeader("X-Runtime", equalTo(JAVA_LOOKUP.getRuntime()))
+ .withHeader("Content-Type", containing("application/json"))
+ .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+ }
+
+ volatile StatusData error;
+
+ @Test
+ public void testAppendErrorIgnore() throws Exception {
+ wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+ .willReturn(FAILURE_RESPONSE));
+
+ StatusLogger.getLogger().registerListener(new StatusListener() {
+ @Override
+ public void log(final StatusData data) {
+ error = data;
+ }
+
+ @Override
+ public Level getStatusLevel() {
+ return Level.ERROR;
+ }
+
+ @Override
+ public void close() throws IOException { }
+ });
+
+ error = null;
+
+ final Appender appender = HttpAppender.newBuilder()
+ .withName("Http")
+ .withLayout(JsonLayout.createDefaultLayout())
+ .setConfiguration(ctx.getConfiguration())
+ .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+ .build();
+ appender.append(createLogEvent());
+
+ wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+ .withHeader("Host", containing("localhost"))
+ .withHeader("Content-Type", containing("application/json"))
+ .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+
+ assertNotNull(error);
+ assertEquals(Level.ERROR, error.getLevel());
+ assertEquals("Unable to send HTTP in appender [Http]", error.getMessage().toString());
+ }
+
+ @Test(expected = AppenderLoggingException.class)
+ public void testAppendError() throws Exception {
+ wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+ .willReturn(FAILURE_RESPONSE));
+
+ final Appender appender = HttpAppender.newBuilder()
+ .withName("Http")
+ .withLayout(JsonLayout.createDefaultLayout())
+ .setConfiguration(ctx.getConfiguration())
+ .withIgnoreExceptions(false)
+ .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+ .build();
+ appender.append(createLogEvent());
+ }
+
+ @Test(expected = AppenderLoggingException.class)
+ public void testAppendConnectError() throws Exception {
+ final Appender appender = HttpAppender.newBuilder()
+ .withName("Http")
+ .withLayout(JsonLayout.createDefaultLayout())
+ .setConfiguration(ctx.getConfiguration())
+ .withIgnoreExceptions(false)
+ .setUrl(new URL("http://localhost:"+(wireMockRule.port()+1)+"/test/log4j/"))
+ .build();
+ appender.append(createLogEvent());
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
new file mode 100644
index 0000000..4c2da52
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.impl.Log4jLogEventTest;
+import org.apache.logging.log4j.core.selector.ContextSelector;
+import org.apache.logging.log4j.core.selector.CoreContextSelectors;
+import org.apache.logging.log4j.core.time.ClockFactory;
+import org.apache.logging.log4j.junit.CleanFiles;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests a "complete" JSON file.
+ */
+@RunWith(Parameterized.class)
+@Category(Layouts.Json.class)
+public class JsonCompleteFileAppenderTest {
+
+ public JsonCompleteFileAppenderTest(final Class<ContextSelector> contextSelector) {
+ this.loggerContextRule = new LoggerContextRule("JsonCompleteFileAppenderTest.xml", contextSelector);
+ this.cleanFiles = new CleanFiles(logFile);
+ this.ruleChain = RuleChain.outerRule(cleanFiles).around(loggerContextRule);
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ System.setProperty(ClockFactory.PROPERTY_NAME, Log4jLogEventTest.FixedTimeClock.class.getName());
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ System.clearProperty(ClockFactory.PROPERTY_NAME);
+ }
+
+ @Parameters(name = "{0}")
+ public static Class<?>[] getParameters() {
+ return CoreContextSelectors.CLASSES;
+ }
+
+ private final File logFile = new File("target", "JsonCompleteFileAppenderTest.log");
+ private final LoggerContextRule loggerContextRule;
+ private final CleanFiles cleanFiles;
+
+ @Rule
+ public RuleChain ruleChain;
+
+ @Test
+ public void testFlushAtEndOfBatch() throws Exception {
+ final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
+ final String logMsg = "Message flushed with immediate flush=true";
+ logger.info(logMsg);
+ logger.error(logMsg, new IllegalArgumentException("badarg"));
+ this.loggerContextRule.getLoggerContext().stop(); // stops async thread
+
+ List<String> lines = Files.readAllLines(logFile.toPath(), Charset.forName("UTF8"));
+
+ String[] expected = {
+ "[", // equals
+ "{", // equals
+ " \"thread\" : \"main\",", //
+ " \"level\" : \"INFO\",", //
+ " \"loggerName\" : \"com.foo.Bar\",", //
+ " \"message\" : \"Message flushed with immediate flush=true\",", //
+ " \"endOfBatch\" : false,", //
+ " \"loggerFqcn\" : \"org.apache.logging.log4j.spi.AbstractLogger\",", //
+ " \"instant\" : {", //
+ " \"epochSecond\" : 1234567,", //
+ " \"nanoOfSecond\" : 890000000", //
+ " },", //
+ };
+ for (int i = 0; i < expected.length; i++) {
+ String line = lines.get(i);
+ assertTrue("line " + i + " incorrect: [" + line + "], does not contain: [" + expected[i] + ']', line.contains(expected[i]));
+ }
+ final String location = "testFlushAtEndOfBatch";
+ assertTrue("no location", !lines.get(0).contains(location));
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
new file mode 100644
index 0000000..abee218
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import javax.net.ssl.SSLServerSocketFactory;
+
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
+import org.apache.logging.log4j.core.net.SocketOptions;
+import org.apache.logging.log4j.core.net.TcpSocketManager;
+import org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration;
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+import org.apache.logging.log4j.core.net.ssl.StoreConfigurationException;
+import org.apache.logging.log4j.core.net.ssl.TestConstants;
+import org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration;
+import org.apache.logging.log4j.core.util.NullOutputStream;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class SecureSocketAppenderSocketOptionsTest {
+
+ private static final int PORT;
+ private static TcpSocketTestServer tcpSocketTestServer;
+
+ private static SSLServerSocketFactory serverSocketFactory;
+ private static SslConfiguration sslConfiguration;
+
+ static {
+ PORT = AvailablePortFinder.getNextAvailable();
+ System.setProperty("SecureSocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
+ try {
+ initServerSocketFactory();
+ tcpSocketTestServer = new TcpSocketTestServer(serverSocketFactory.createServerSocket(PORT));
+ tcpSocketTestServer.start();
+ loggerContextRule = new LoggerContextRule("log4j-ssl-socket-options.xml");
+ } catch (IOException | StoreConfigurationException e) {
+ throw new IllegalStateException(e);
+ }
+
+ }
+
+ @ClassRule
+ public static final LoggerContextRule loggerContextRule;
+
+ @AfterClass
+ public static void afterClass() {
+ if (tcpSocketTestServer != null) {
+ tcpSocketTestServer.shutdown();
+ }
+ }
+
+ public static void initServerSocketFactory() throws StoreConfigurationException {
+ final KeyStoreConfiguration ksc = KeyStoreConfiguration.createKeyStoreConfiguration(
+ TestConstants.KEYSTORE_FILE, // file
+ TestConstants.KEYSTORE_PWD(), // password
+ null, // passwordEnvironmentVariable
+ null, // passwordFile
+ null, // key store type
+ null); // algorithm
+
+ final TrustStoreConfiguration tsc = TrustStoreConfiguration.createKeyStoreConfiguration(
+ TestConstants.TRUSTSTORE_FILE, // file
+ TestConstants.TRUSTSTORE_PWD(), // password
+ null, // passwordEnvironmentVariable
+ null, // passwordFile
+ null, // key store type
+ null); // algorithm
+ sslConfiguration = SslConfiguration.createSSLConfiguration(null, ksc, tsc);
+ serverSocketFactory = sslConfiguration.getSslServerSocketFactory();
+ }
+
+ @Test
+ public void testSocketOptions() throws IOException {
+ Assert.assertNotNull(loggerContextRule);
+ Assert.assertNotNull(loggerContextRule.getConfiguration());
+ final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+ Assert.assertNotNull(appender);
+ final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+ Assert.assertNotNull(manager);
+ final OutputStream outputStream = manager.getOutputStream();
+ Assert.assertFalse(outputStream instanceof NullOutputStream);
+ final SocketOptions socketOptions = manager.getSocketOptions();
+ Assert.assertNotNull(socketOptions);
+ final Socket socket = manager.getSocket();
+ Assert.assertNotNull(socket);
+ // Test config request
+ Assert.assertEquals(false, socketOptions.isKeepAlive());
+ Assert.assertEquals(null, socketOptions.isOobInline());
+ Assert.assertEquals(false, socketOptions.isReuseAddress());
+ Assert.assertEquals(false, socketOptions.isTcpNoDelay());
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
+ socketOptions.getActualTrafficClass().intValue());
+ Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
+ Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
+ Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
+ Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
+ // Test live socket
+ Assert.assertEquals(false, socket.getKeepAlive());
+ Assert.assertEquals(false, socket.getReuseAddress());
+ Assert.assertEquals(false, socket.getTcpNoDelay());
+ // Assert.assertEquals(10000, socket.getReceiveBufferSize());
+ // This settings changes while we are running, so we cannot assert it.
+ // Assert.assertEquals(8000, socket.getSendBufferSize());
+ Assert.assertEquals(12345, socket.getSoLinger());
+ Assert.assertEquals(54321, socket.getSoTimeout());
+ }
+
+ @Test
+ public void testSocketTrafficClass() throws IOException {
+ Assume.assumeTrue("Run only on Java 7", System.getProperty("java.specification.version").equals("1.7"));
+ Assume.assumeFalse("Do not run on Travis CI", "true".equals(System.getenv("TRAVIS")));
+ final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+ final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+ final Socket socket = manager.getSocket();
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
new file mode 100644
index 0000000..85b6b17
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class SocketAppenderBufferSizeTest {
+
+ private TcpSocketTestServer tcpServer;
+
+ private LoggerContext loggerContext;
+ private Logger logger;
+
+ @Rule
+ public LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-empty.xml");
+
+ @Before
+ public void setup() throws Exception {
+ tcpServer = new TcpSocketTestServer(AvailablePortFinder.getNextAvailable());
+ tcpServer.start();
+ ThreadContext.clearAll();
+ loggerContext = loggerContextRule.getLoggerContext();
+ logger = loggerContext.getLogger(SocketAppenderBufferSizeTest.class.getName());
+ }
+
+ @After
+ public void teardown() {
+ tcpServer.shutdown();
+ loggerContext = null;
+ logger = null;
+ tcpServer.reset();
+ ThreadContext.clearAll();
+ }
+
+ @Test
+ public void testTcpAppenderDefaultEncoderBufferSize() throws Exception {
+ SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
+ }
+
+ @Test
+ public void testTcpAppenderLargeEncoderBufferSize() throws Exception {
+ SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE * 100);
+ }
+
+ @Test
+ public void testTcpAppenderSmallestEncoderBufferSize() throws Exception {
+ SocketAppenderTest.testTcpAppender(tcpServer, logger, 1);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
new file mode 100644
index 0000000..030fa80
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
+import org.apache.logging.log4j.core.net.SocketOptions;
+import org.apache.logging.log4j.core.net.TcpSocketManager;
+import org.apache.logging.log4j.core.util.NullOutputStream;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class SocketAppenderSocketOptionsTest {
+
+ private static final int PORT;
+ private static TcpSocketTestServer tcpSocketTestServer;
+
+ static {
+ PORT = AvailablePortFinder.getNextAvailable();
+ System.setProperty("SocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
+ try {
+ tcpSocketTestServer = new TcpSocketTestServer(PORT);
+ } catch (final IOException e) {
+ throw new IllegalStateException(e);
+ }
+ tcpSocketTestServer.start();
+ loggerContextRule = new LoggerContextRule("log4j-socket-options.xml");
+ }
+
+ @ClassRule
+ public static final LoggerContextRule loggerContextRule;
+
+ @AfterClass
+ public static void afterClass() {
+ if (tcpSocketTestServer != null) {
+ tcpSocketTestServer.shutdown();
+ }
+ }
+
+ @Test
+ public void testSocketOptions() throws IOException {
+ Assert.assertNotNull(loggerContextRule);
+ Assert.assertNotNull(loggerContextRule.getConfiguration());
+ final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+ Assert.assertNotNull(appender);
+ final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+ Assert.assertNotNull(manager);
+ final OutputStream outputStream = manager.getOutputStream();
+ Assert.assertFalse(outputStream instanceof NullOutputStream);
+ final SocketOptions socketOptions = manager.getSocketOptions();
+ Assert.assertNotNull(socketOptions);
+ final Socket socket = manager.getSocket();
+ Assert.assertNotNull(socket);
+ // Test config request
+ Assert.assertEquals(false, socketOptions.isKeepAlive());
+ Assert.assertEquals(false, socketOptions.isOobInline());
+ Assert.assertEquals(false, socketOptions.isReuseAddress());
+ Assert.assertEquals(false, socketOptions.isTcpNoDelay());
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
+ socketOptions.getActualTrafficClass().intValue());
+ Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
+ Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
+ Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
+ Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
+ // Test live socket
+ Assert.assertEquals(false, socket.getKeepAlive());
+ Assert.assertEquals(false, socket.getOOBInline());
+ Assert.assertEquals(false, socket.getReuseAddress());
+ Assert.assertEquals(false, socket.getTcpNoDelay());
+ // Assert.assertEquals(10000, socket.getReceiveBufferSize());
+ // This settings changes while we are running, so we cannot assert it.
+ // Assert.assertEquals(8000, socket.getSendBufferSize());
+ Assert.assertEquals(12345, socket.getSoLinger());
+ Assert.assertEquals(54321, socket.getSoTimeout());
+ }
+
+ @Test
+ public void testSocketTrafficClass() throws IOException {
+ Assume.assumeTrue("Run only on Java 7", System.getProperty("java.specification.version").equals("1.7"));
+ Assume.assumeFalse("Do not run on Travis CI", "true".equals(System.getenv("TRAVIS")));
+ final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+ final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+ final Socket socket = manager.getSocket();
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
new file mode 100644
index 0000000..e02590c
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
@@ -0,0 +1,412 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LoggingException;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Appender;
+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.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.net.Protocol;
+import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.core.util.Throwables;
+import org.apache.logging.log4j.jackson.json.Log4jJsonObjectMapper;
+import org.apache.logging.log4j.jackson.json.layout.JsonLayout;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.MappingIterator;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ *
+ */
+public class SocketAppenderTest {
+
+ private static final int PORT = AvailablePortFinder.getNextAvailable();
+ private static final int DYN_PORT = AvailablePortFinder.getNextAvailable();
+ private static final int ERROR_PORT = AvailablePortFinder.getNextAvailable();
+
+ private static TcpSocketTestServer tcpServer;
+ private static UdpSocketTestServer udpServer;
+
+ private final LoggerContext context = LoggerContext.getContext();
+ private final Logger logger = context.getLogger(SocketAppenderTest.class.getName());
+
+ @BeforeClass
+ public static void setupClass() throws Exception {
+ tcpServer = new TcpSocketTestServer(PORT);
+ tcpServer.start();
+ udpServer = new UdpSocketTestServer();
+ udpServer.start();
+ LoggerContext.getContext().reconfigure();
+ ThreadContext.clearAll();
+ }
+
+ @AfterClass
+ public static void cleanupClass() {
+ tcpServer.shutdown();
+ udpServer.shutdown();
+ ThreadContext.clearAll();
+ }
+
+ @After
+ public void teardown() {
+ ThreadContext.clearAll();
+ removeAndStopAppenders();
+ reset();
+ }
+
+ void removeAndStopAppenders() {
+ final Map<String, Appender> map = logger.getAppenders();
+ for (final Map.Entry<String, Appender> entry : map.entrySet()) {
+ final Appender appender = entry.getValue();
+ logger.removeAppender(appender);
+ appender.stop();
+ }
+ }
+
+ static void reset() {
+ tcpServer.reset();
+ udpServer.reset();
+ }
+
+ @Test
+ public void testTcpAppender1() throws Exception {
+ testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
+ }
+
+ @Test
+ @Ignore("WIP Bug when this method runs after testTcpAppender1()")
+ public void testTcpAppender2() throws Exception {
+ testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
+ }
+
+ static void testTcpAppender(final TcpSocketTestServer tcpTestServer, final Logger logger, final int bufferSize)
+ throws Exception {
+ // @formatter:off
+ final SocketAppender appender = SocketAppender.newBuilder()
+ .withHost("localhost")
+ .withPort(tcpTestServer.getLocalPort())
+ .withReconnectDelayMillis(-1)
+ .withName("test")
+ .withImmediateFail(false)
+ .withBufferSize(bufferSize)
+ .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+ .build();
+ // @formatter:on
+ appender.start();
+ Assert.assertEquals(bufferSize, appender.getManager().getByteBuffer().capacity());
+
+ // set appender on root and set level to debug
+ logger.addAppender(appender);
+ logger.setAdditive(false);
+ logger.setLevel(Level.DEBUG);
+ final String tcKey = "UUID";
+ final String expectedUuidStr = UUID.randomUUID().toString();
+ ThreadContext.put(tcKey, expectedUuidStr);
+ ThreadContext.push(expectedUuidStr);
+ final String expectedExMsg = "This is a test";
+ try {
+ logger.debug("This is a test message");
+ final Throwable child = new LoggingException(expectedExMsg);
+ logger.error("Throwing an exception", child);
+ logger.debug("This is another test message");
+ } finally {
+ ThreadContext.remove(tcKey);
+ ThreadContext.pop();
+ }
+ Thread.sleep(250);
+ LogEvent event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
+ assertNotNull("No event retrieved", event);
+ assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a test message"));
+ assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 0);
+ assertEquals(expectedUuidStr, event.getContextData().getValue(tcKey));
+ event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
+ assertNotNull("No event retrieved", event);
+ assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("Throwing an exception"));
+ assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 1);
+ assertEquals(expectedUuidStr, event.getContextStack().pop());
+ assertNotNull(event.getThrownProxy());
+ assertEquals(expectedExMsg, event.getThrownProxy().getMessage());
+ }
+
+ @Test
+ public void testDefaultProtocol() throws Exception {
+ // @formatter:off
+ final SocketAppender appender = SocketAppender.newBuilder()
+ .withPort(tcpServer.getLocalPort())
+ .withReconnectDelayMillis(-1)
+ .withName("test")
+ .withImmediateFail(false)
+ .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+ .build();
+ // @formatter:on
+ assertNotNull(appender);
+ appender.stop();
+ }
+
+ @Test
+ public void testUdpAppender() throws Exception {
+ try {
+ udpServer.latch.await();
+ } catch (final InterruptedException ex) {
+ ex.printStackTrace();
+ }
+
+ // @formatter:off
+ final SocketAppender appender = SocketAppender.newBuilder()
+ .withProtocol(Protocol.UDP)
+ .withPort(tcpServer.getLocalPort())
+ .withReconnectDelayMillis(-1)
+ .withName("test")
+ .withImmediateFail(false)
+ .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+ .build();
+ // @formatter:on
+ appender.start();
+
+ // set appender on root and set level to debug
+ logger.addAppender(appender);
+ logger.setAdditive(false);
+ logger.setLevel(Level.DEBUG);
+ logger.debug("This is a udp message");
+ final LogEvent event = udpServer.getQueue().poll(3, TimeUnit.SECONDS);
+ assertNotNull("No event retrieved", event);
+ assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a udp message"));
+ assertTrue("Message not delivered via UDP", udpServer.getCount() > 0);
+ }
+
+ @Test
+ public void testTcpAppenderDeadlock() throws Exception {
+
+ // @formatter:off
+ final SocketAppender appender = SocketAppender.newBuilder()
+ .withHost("localhost")
+ .withPort(DYN_PORT)
+ .withReconnectDelayMillis(100)
+ .withName("test")
+ .withImmediateFail(false)
+ .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+ .build();
+ // @formatter:on
+ appender.start();
+ // set appender on root and set level to debug
+ logger.addAppender(appender);
+ logger.setAdditive(false);
+ logger.setLevel(Level.DEBUG);
+
+ final TcpSocketTestServer tcpSocketServer = new TcpSocketTestServer(DYN_PORT);
+ try {
+ tcpSocketServer.start();
+
+ logger.debug("This message is written because a deadlock never.");
+
+ final LogEvent event = tcpSocketServer.getQueue().poll(3, TimeUnit.SECONDS);
+ assertNotNull("No event retrieved", event);
+ } finally {
+ tcpSocketServer.shutdown();
+ }
+ }
+
+ @Test
+ public void testTcpAppenderNoWait() throws Exception {
+ // @formatter:off
+ final SocketAppender appender = SocketAppender.newBuilder()
+ .withHost("localhost")
+ .withPort(ERROR_PORT)
+ .withReconnectDelayMillis(100)
+ .withName("test")
+ .withImmediateFail(false)
+ .withIgnoreExceptions(false)
+ .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+ .build();
+ // @formatter:on
+ appender.start();
+ // set appender on root and set level to debug
+ logger.addAppender(appender);
+ logger.setAdditive(false);
+ logger.setLevel(Level.DEBUG);
+
+ try {
+ logger.debug("This message is written because a deadlock never.");
+ fail("No Exception was thrown");
+ } catch (final Exception ex) {
+ // TODO: move exception to @Test(expect = Exception.class)
+ // Failure is expected.
+ // ex.printStackTrace();
+ }
+ }
+
+ public static class UdpSocketTestServer extends Thread {
+
+ private final DatagramSocket sock;
+ private boolean shutdown = false;
+ private Thread thread;
+ private final CountDownLatch latch = new CountDownLatch(1);
+ private volatile int count = 0;
+ private final BlockingQueue<LogEvent> queue;
+ private final ObjectMapper objectMapper = new Log4jJsonObjectMapper();
+
+ public UdpSocketTestServer() throws IOException {
+ this.sock = new DatagramSocket(PORT);
+ this.queue = new ArrayBlockingQueue<>(10);
+ }
+
+ public void reset() {
+ queue.clear();
+ count = 0;
+ }
+
+ public void shutdown() {
+ this.shutdown = true;
+ thread.interrupt();
+ try {
+ thread.join(100);
+ } catch (InterruptedException ie) {
+ System.out.println("Unable to stop server");
+ }
+ }
+
+ @Override
+ public void run() {
+ this.thread = Thread.currentThread();
+ final byte[] bytes = new byte[4096];
+ final DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
+ try {
+ while (!shutdown) {
+ latch.countDown();
+ sock.receive(packet);
+ ++count;
+ final LogEvent event = objectMapper.readValue(packet.getData(), Log4jLogEvent.class);
+ queue.add(event);
+ }
+ } catch (final Throwable e) {
+ e.printStackTrace();
+ if (!shutdown) {
+ Throwables.rethrow(e);
+ }
+ }
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public BlockingQueue<LogEvent> getQueue() {
+ return queue;
+ }
+ }
+
+ public static class TcpSocketTestServer extends Thread {
+
+ private final ServerSocket serverSocket;
+ private volatile boolean shutdown = false;
+ private volatile int count = 0;
+ private final BlockingQueue<LogEvent> queue;
+ private final ObjectMapper objectMapper = new Log4jJsonObjectMapper();
+
+ @SuppressWarnings("resource")
+ public TcpSocketTestServer(final int port) throws IOException {
+ this(new ServerSocket(port));
+ }
+
+ public TcpSocketTestServer(final ServerSocket serverSocket) {
+ this.serverSocket = serverSocket;
+ this.queue = new ArrayBlockingQueue<>(10);
+ }
+
+ public int getLocalPort() {
+ return serverSocket.getLocalPort();
+ }
+
+ public void reset() {
+ queue.clear();
+ count = 0;
+ }
+
+ public void shutdown() {
+ this.shutdown = true;
+ interrupt();
+ try {
+ this.join(100);
+ } catch (InterruptedException ie) {
+ System.out.println("Unable to stop server");
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ try (final Socket socket = serverSocket.accept()) {
+ if (socket != null) {
+ final InputStream is = socket.getInputStream();
+ while (!shutdown) {
+ final MappingIterator<LogEvent> mappingIterator = objectMapper.readerFor(Log4jLogEvent.class).readValues(is);
+ while (mappingIterator.hasNextValue()) {
+ queue.add(mappingIterator.nextValue());
+ ++count;
+ }
+ }
+ }
+ }
+ } catch (final EOFException eof) {
+ // Socket is closed.
+ } catch (final Exception e) {
+ if (!shutdown) {
+ Throwables.rethrow(e);
+ }
+ }
+ }
+
+ public BlockingQueue<LogEvent> getQueue() {
+ return queue;
+ }
+
+ public int getCount() {
+ return count;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
new file mode 100644
index 0000000..eea989a
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Tests a "compact" XML file, no extra spaces or end of lines.
+ */
+@Category(Layouts.Xml.class)
+public class XmlCompactFileAppenderTest {
+
+ @BeforeClass
+ public static void beforeClass() {
+ System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+ "XmlCompactFileAppenderTest.xml");
+ }
+
+ @Test
+ public void testFlushAtEndOfBatch() throws Exception {
+ final File file = new File("target", "XmlCompactFileAppenderTest.log");
+ file.delete();
+ final Logger log = LogManager.getLogger("com.foo.Bar");
+ final String logMsg = "Message flushed with immediate flush=false";
+ log.info(logMsg);
+ CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
+
+ String line1;
+ try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
+ line1 = reader.readLine();
+ } finally {
+ file.delete();
+ }
+ assertNotNull("line1", line1);
+ final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg1 + ']', line1.contains(msg1));
+
+ final String msg2 = "<Events xmlns=\"http://logging.apache.org/log4j/2.0/events\">";
+ assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg2 + ']', line1.contains(msg2));
+
+ final String msg3 = "<Event ";
+ assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg3 + ']', line1.contains(msg3));
+
+ final String msg4 = logMsg;
+ assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg4 + ']', line1.contains(msg4));
+
+ final String location = "testFlushAtEndOfBatch";
+ assertTrue("no location", !line1.contains(location));
+
+ assertTrue(line1.indexOf('\r') == -1);
+ assertTrue(line1.indexOf('\n') == -1);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
new file mode 100644
index 0000000..9b4da79
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.xml.sax.SAXException;
+
+/**
+ * Tests XML validation for a "compact" XML file, no extra spaces or end of lines.
+ */
+@Ignore
+@Category(Layouts.Xml.class)
+public class XmlCompactFileAppenderValidationTest {
+
+ private LoggerContext loggerContext;
+
+ @Before
+ public void before() {
+ this.loggerContext = Configurator.initialize(XmlCompactFileAppenderValidationTest.class.getName(),
+ "target/test-classes/XmlCompactFileAppenderValidationTest.xml");
+ }
+
+ @After
+ public void after() {
+ // Just in case, an @Test blew up
+ Configurator.shutdown(this.loggerContext);
+ }
+
+ @Test
+ public void validateXmlSchemaThrowable() throws Exception {
+ final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
+ file.delete();
+ final Logger log = LogManager.getLogger("com.foo.Bar");
+ try {
+ throw new IllegalArgumentException("IAE");
+ } catch (final IllegalArgumentException e) {
+ log.warn("Message 1", e);
+ }
+ Configurator.shutdown(this.loggerContext);
+ this.validateXmlSchema(file);
+ }
+
+ @Test
+ public void validateXmlSchema() throws Exception {
+ final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
+ file.delete();
+ final Logger log = LogManager.getLogger("com.foo.Bar");
+ log.warn("Message 1");
+ log.info("Message 2");
+ log.debug("Message 3");
+ Configurator.shutdown(this.loggerContext);
+ this.validateXmlSchema(file);
+ }
+
+ @Test
+ public void validateXmlNoEvents() throws Exception {
+ final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
+ file.delete();
+ Configurator.shutdown(this.loggerContext);
+ this.validateXmlSchema(file);
+ }
+
+ private void validateXmlSchema(final File file) throws SAXException, IOException {
+ final URL schemaFile = this.getClass().getClassLoader().getResource("Log4j-events.xsd");
+ final Source xmlFile = new StreamSource(file);
+ final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ final Schema schema = schemaFactory.newSchema(schemaFile);
+ final Validator validator = schema.newValidator();
+ validator.validate(xmlFile);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
new file mode 100644
index 0000000..1e048b1
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.xml.sax.SAXException;
+
+/**
+ * Tests XML validation for a "compact" XML file, no extra spaces or end of lines.
+ */
+@Ignore
+@Category(Layouts.Xml.class)
+public class XmlCompactFileAsyncAppenderValidationTest {
+
+ @BeforeClass
+ public static void beforeClass() {
+ System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+ "XmlCompactFileAsyncAppenderValidationTest.xml");
+ }
+
+ @Test
+ public void validateXmlSchemaSimple() throws Exception {
+ final File file = new File("target", "XmlCompactFileAsyncAppenderValidationTest.log.xml");
+ file.delete();
+ final Logger log = LogManager.getLogger("com.foo.Bar");
+ log.warn("Message 1");
+ log.info("Message 2");
+ log.debug("Message 3");
+ CoreLoggerContexts.stopLoggerContext(file); // stop async thread
+ this.validateXmlSchema(file);
+ }
+
+ @Test
+ public void validateXmlSchemaNoEvents() throws Exception {
+ final File file = new File("target", "XmlCompactFileAsyncAppenderValidationTest.log.xml");
+ file.delete();
+ CoreLoggerContexts.stopLoggerContext(file); // stop async thread
+ this.validateXmlSchema(file);
+ }
+
+ private void validateXmlSchema(final File file) throws SAXException, IOException {
+ final URL schemaFile = this.getClass().getClassLoader().getResource("Log4j-events.xsd");
+ final Source xmlFile = new StreamSource(file);
+ final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ final Schema schema = schemaFactory.newSchema(schemaFile);
+ final Validator validator = schema.newValidator();
+ validator.validate(xmlFile);
+ }
+
+}