Skip to content

Commit d1699da

Browse files
authored
Merge branch 'main' into dependabot/maven/main/org.apache.commons-commons-lang3-3.18.0
2 parents f6f4831 + 3871c4c commit d1699da

File tree

22 files changed

+854
-674
lines changed

22 files changed

+854
-674
lines changed

BUILDING.adoc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,59 @@ Try removing all _"Override compiler parameters per-module"_ entries in _"Settin
144144
=== Compilation in IntelliJ IDEA fails with `java: package org.apache.logging.log4j.plugins.test.validation.plugins does not exist`
145145
146146
We don't know how to fix this.
147+
148+
[#development-api-compatibility]
149+
=== Fixing API compatibility check failures
150+
151+
Log4j uses the
152+
https://github.com/bndtools/bnd/tree/master/maven-plugins/bnd-baseline-maven-plugin[BND Baseline Maven Plugin]
153+
to enforce its
154+
https://semver.org/[semantic versioning policy].
155+
Following the
156+
https://bnd.bndtools.org/chapters/170-versioning.html#best-practices[OSGi versioning best practices], both Log4j artifacts and packages are versioned.
157+
If you modify Log4j's public API, a BND Baseline error like the following will occur:
158+
159+
[source]
160+
----
161+
Name Type Delta New Old Suggest If Prov.
162+
org.apache.logging.foo PACKAGE UNCHANGED 2.1.0 2.1.0 ok -
163+
* org.apache.logging.foo.bar PACKAGE MINOR 2.3.4 2.3.4 2.4.0 -
164+
MINOR PACKAGE org.apache.logging.foo.bar
165+
...
166+
----
167+
168+
The solution of the error depends on the change kind (`Delta`):
169+
170+
[#development-api-compatibility-micro]
171+
`MICRO`::
172+
+
173+
For patch level changes modify the `package-info.java` file of the `org.apache.logging.foo.bar` package and update the `@Version` annotation to the number suggested by BND: increment just the patch number.
174+
+
175+
[source,java]
176+
----
177+
@Version("2.3.5")
178+
package org.apache.logging.foo.bar;
179+
----
180+
181+
[#development-api-compatibility-minor]
182+
`MINOR`::
183+
+
184+
Changes of type `MINOR` require more work:
185+
+
186+
--
187+
* Make sure that the current Log4j version is a minor upgrade over the last released version.
188+
If that is not the case (e.g., it is `2.34.5-SNAPSHOT`) modify the `<revision>` property in the main POM file (e.g., change it to `2.35.0-SNAPSHOT`).
189+
* Make sure to add a
190+
https://logging.apache.org/log4j/tools/log4j-changelog.html#changelog-entry-file[changelog entry]
191+
of type `added`, `changed` or `deprecated` to your PR.
192+
* As in the
193+
<<development-api-compatibility-micro,`MICRO` case>>
194+
modify the `package-info.java` file of the package and update the `@Version` annotation to the **next Log4j version** (`2.35.0` in the example) and **not** the minimal version number suggested by BND.
195+
The purpose of this policy is to have an alignment between package versions and the last Log4j version, where an API change occurred.
196+
--
197+
198+
[#development-api-compatibility-major]
199+
`MAJOR`::
200+
+
201+
Changes of type `MAJOR` (i.e. breaking changes) are not accepted in the `2.x` branch.
202+
If you believe it is not a breaking change (e.g., you removed a class **documented** as private), the development team will guide you on how to solve it.

log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,11 @@ public void testShutdownTimeout(final LoggerContext context) {
151151
context.getLogger("Logger").info("This is a test");
152152
context.stop();
153153
}
154+
155+
@Test
156+
@LoggerContextSource("log4j-asynch-location.xml")
157+
public void testRequiresLocation(final LoggerContext context) {
158+
final AsyncAppender appender = context.getConfiguration().getAppender("Async");
159+
assertTrue(appender.requiresLocation());
160+
}
154161
}

log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/FailoverAppenderTest.java

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertNotNull;
21+
import static org.junit.jupiter.api.Assertions.assertTrue;
2122

2223
import java.util.List;
2324
import org.apache.logging.log4j.Logger;
@@ -27,61 +28,52 @@
2728
import org.apache.logging.log4j.core.test.appender.ListAppender;
2829
import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
2930
import org.apache.logging.log4j.core.test.junit.Named;
30-
import org.junit.jupiter.api.AfterEach;
31-
import org.junit.jupiter.api.Tag;
3231
import org.junit.jupiter.api.Test;
3332

34-
@LoggerContextSource("log4j-failover.xml")
35-
@Tag("sleepy")
3633
public class FailoverAppenderTest {
37-
private final ListAppender app;
38-
private final FailOnceAppender foApp;
39-
private final Logger logger;
40-
private final Logger onceLogger;
41-
42-
public FailoverAppenderTest(
43-
final LoggerContext context,
44-
@Named("List") final ListAppender app,
45-
@Named("Once") final FailOnceAppender foApp) {
46-
this.app = app;
47-
this.foApp = foApp;
48-
logger = context.getLogger("LoggerTest");
49-
onceLogger = context.getLogger("Once");
50-
}
51-
52-
@AfterEach
53-
public void tearDown() throws Exception {
54-
app.clear();
55-
}
5634

5735
@Test
58-
public void testFailover() {
36+
@LoggerContextSource("log4j-failover.xml")
37+
void testFailover(final LoggerContext context, @Named("List") final ListAppender app) {
38+
final Logger logger = context.getLogger("LoggerTest");
5939
logger.error("This is a test");
6040
List<LogEvent> events = app.getEvents();
6141
assertNotNull(events);
62-
assertEquals(events.size(), 1, "Incorrect number of events. Should be 1 is " + events.size());
42+
assertEquals(1, events.size(), "Incorrect number of events. Should be 1 is " + events.size());
6343
app.clear();
6444
logger.error("This is a test");
6545
events = app.getEvents();
6646
assertNotNull(events);
67-
assertEquals(events.size(), 1, "Incorrect number of events. Should be 1 is " + events.size());
47+
assertEquals(1, events.size(), "Incorrect number of events. Should be 1 is " + events.size());
6848
}
6949

7050
@Test
71-
@Tag("sleepy")
72-
public void testRecovery() throws Exception {
51+
@LoggerContextSource("log4j-failover.xml")
52+
void testRecovery(
53+
final LoggerContext context,
54+
@Named("List") final ListAppender app,
55+
@Named("Once") final FailOnceAppender foApp)
56+
throws Exception {
57+
final Logger onceLogger = context.getLogger("Once");
7358
onceLogger.error("Fail once");
7459
onceLogger.error("Fail again");
7560
List<LogEvent> events = app.getEvents();
7661
assertNotNull(events);
77-
assertEquals(events.size(), 2, "Incorrect number of events. Should be 2 is " + events.size());
62+
assertEquals(2, events.size(), "Incorrect number of events. Should be 2 is " + events.size());
7863
app.clear();
7964
Thread.sleep(1100);
8065
onceLogger.error("Fail after recovery interval");
8166
onceLogger.error("Second log message");
8267
events = app.getEvents();
83-
assertEquals(events.size(), 0, "Did not recover");
68+
assertEquals(0, events.size(), "Did not recover");
8469
events = foApp.drainEvents();
85-
assertEquals(events.size(), 2, "Incorrect number of events in primary appender");
70+
assertEquals(2, events.size(), "Incorrect number of events in primary appender");
71+
}
72+
73+
@Test
74+
@LoggerContextSource("log4j-failover-location.xml")
75+
void testRequiresLocation(final LoggerContext context) {
76+
final FailoverAppender appender = context.getConfiguration().getAppender("Failover");
77+
assertTrue(appender.requiresLocation());
8678
}
8779
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.log4j.core.appender;
18+
19+
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
20+
import static org.junit.jupiter.api.Assertions.assertNotNull;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
22+
23+
import java.net.MalformedURLException;
24+
import java.net.URL;
25+
import org.apache.logging.log4j.Level;
26+
import org.apache.logging.log4j.core.Layout;
27+
import org.apache.logging.log4j.core.config.Configuration;
28+
import org.apache.logging.log4j.core.config.DefaultConfiguration;
29+
import org.apache.logging.log4j.core.config.Property;
30+
import org.apache.logging.log4j.core.layout.PatternLayout;
31+
import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
32+
import org.apache.logging.log4j.test.ListStatusListener;
33+
import org.apache.logging.log4j.test.junit.UsingStatusListener;
34+
import org.junit.jupiter.api.Test;
35+
36+
class HttpAppenderBuilderTest {
37+
38+
private HttpAppender.Builder<?> getBuilder() {
39+
Configuration mockConfig = new DefaultConfiguration();
40+
return HttpAppender.newBuilder().setConfiguration(mockConfig).setName("TestHttpAppender"); // Name is required
41+
}
42+
43+
@Test
44+
@UsingStatusListener
45+
void testBuilderWithoutUrl(final ListStatusListener listener) throws Exception {
46+
HttpAppender appender = HttpAppender.newBuilder()
47+
.setConfiguration(new DefaultConfiguration())
48+
.setName("TestAppender")
49+
.setLayout(PatternLayout.createDefaultLayout()) // Providing a layout here
50+
.build();
51+
52+
assertThat(listener.findStatusData(Level.ERROR))
53+
.anyMatch(statusData ->
54+
statusData.getMessage().getFormattedMessage().contains("HttpAppender requires URL to be set."));
55+
}
56+
57+
@Test
58+
@UsingStatusListener
59+
void testBuilderWithUrlAndWithoutLayout(final ListStatusListener listener) throws Exception {
60+
HttpAppender appender = HttpAppender.newBuilder()
61+
.setConfiguration(new DefaultConfiguration())
62+
.setName("TestAppender")
63+
.setUrl(new URL("http://localhost:8080/logs"))
64+
.build();
65+
66+
assertThat(listener.findStatusData(Level.ERROR)).anyMatch(statusData -> statusData
67+
.getMessage()
68+
.getFormattedMessage()
69+
.contains("HttpAppender requires a layout to be set."));
70+
}
71+
72+
@Test
73+
void testBuilderWithValidConfiguration() throws Exception {
74+
URL url = new URL("http://example.com");
75+
Layout layout = PatternLayout.createDefaultLayout();
76+
77+
HttpAppender.Builder<?> builder = getBuilder().setUrl(url).setLayout(layout);
78+
79+
HttpAppender appender = builder.build();
80+
assertNotNull(appender, "HttpAppender should be created with valid configuration.");
81+
}
82+
83+
@Test
84+
void testBuilderWithCustomMethod() throws Exception {
85+
URL url = new URL("http://example.com");
86+
Layout layout = PatternLayout.createDefaultLayout();
87+
String customMethod = "PUT";
88+
89+
HttpAppender.Builder<?> builder =
90+
getBuilder().setUrl(url).setLayout(layout).setMethod(customMethod);
91+
92+
HttpAppender appender = builder.build();
93+
assertNotNull(appender, "HttpAppender should be created with a custom HTTP method.");
94+
}
95+
96+
@Test
97+
void testBuilderWithHeaders() throws Exception {
98+
URL url = new URL("http://example.com");
99+
Layout layout = PatternLayout.createDefaultLayout();
100+
Property[] headers = new Property[] {
101+
Property.createProperty("Header1", "Value1"), Property.createProperty("Header2", "Value2")
102+
};
103+
104+
HttpAppender.Builder<?> builder =
105+
getBuilder().setUrl(url).setLayout(layout).setHeaders(headers);
106+
107+
HttpAppender appender = builder.build();
108+
assertNotNull(appender, "HttpAppender should be created with headers.");
109+
}
110+
111+
@Test
112+
void testBuilderWithSslConfiguration() throws Exception {
113+
URL url = new URL("https://example.com");
114+
Layout layout = PatternLayout.createDefaultLayout();
115+
116+
// Use real SslConfiguration instead of Mockito mock
117+
SslConfiguration sslConfig = SslConfiguration.createSSLConfiguration(null, null, null, false);
118+
119+
HttpAppender.Builder<?> builder =
120+
getBuilder().setUrl(url).setLayout(layout).setSslConfiguration(sslConfig);
121+
122+
HttpAppender appender = builder.build();
123+
assertNotNull(appender, "HttpAppender should be created with SSL configuration.");
124+
}
125+
126+
@Test
127+
void testBuilderWithInvalidUrl() {
128+
assertThrows(MalformedURLException.class, () -> new URL("invalid-url"));
129+
}
130+
}

log4j-core-test/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)