[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 <[email protected]> Authored: Mon Feb 19 19:09:06 2018 -0700 Committer: Gary Gregory <[email protected]> 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); + } + +}
