Skip to content

Commit d197dff

Browse files
author
Onkar
committed
Improve test coverage for JsonErrorReportValve, JsonAccessLogValve and HealthCheckValve
1 parent 7557c61 commit d197dff

3 files changed

Lines changed: 288 additions & 0 deletions

File tree

test/org/apache/catalina/valves/TestHealthCheckValve.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,49 @@ public void service(ServletRequest request, ServletResponse response) {
113113
}
114114

115115

116+
@Test
117+
public void testGetSetProperties() {
118+
HealthCheckValve valve = new HealthCheckValve();
119+
120+
// Default path
121+
Assert.assertEquals("/health", valve.getPath());
122+
123+
valve.setPath("/ready");
124+
Assert.assertEquals("/ready", valve.getPath());
125+
126+
// Default checkContainersAvailable
127+
Assert.assertTrue(valve.getCheckContainersAvailable());
128+
129+
valve.setCheckContainersAvailable(false);
130+
Assert.assertFalse(valve.getCheckContainersAvailable());
131+
132+
valve.setCheckContainersAvailable(true);
133+
Assert.assertTrue(valve.getCheckContainersAvailable());
134+
}
135+
136+
137+
@Test
138+
public void testCustomPath() throws Exception {
139+
Tomcat tomcat = getTomcatInstance();
140+
Context ctx = getProgrammaticRootContext();
141+
142+
HealthCheckValve healthCheckValve = new HealthCheckValve();
143+
healthCheckValve.setPath("/ready");
144+
ctx.getParent().getPipeline().addValve(healthCheckValve);
145+
146+
tomcat.start();
147+
148+
ByteChunk result = new ByteChunk();
149+
150+
// Default /health should NOT match
151+
int rc = getUrl("http://localhost:" + getPort() + "/health", result, null);
152+
Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, rc);
153+
154+
result.recycle();
155+
156+
// Custom /ready should match
157+
rc = getUrl("http://localhost:" + getPort() + "/ready", result, null);
158+
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
159+
Assert.assertTrue(result.toString().contains("UP"));
160+
}
116161
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
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.catalina.valves;
18+
19+
import java.nio.charset.StandardCharsets;
20+
21+
import jakarta.servlet.http.HttpServletResponse;
22+
23+
import org.junit.Assert;
24+
import org.junit.Test;
25+
26+
import org.apache.catalina.Context;
27+
import org.apache.catalina.startup.Tomcat;
28+
import org.apache.catalina.startup.TomcatBaseTest;
29+
import org.apache.tomcat.util.buf.ByteChunk;
30+
31+
/**
32+
* Tests for {@link JsonAccessLogValve}.
33+
*/
34+
public class TestJsonAccessLogValve extends TomcatBaseTest {
35+
36+
@Test
37+
public void testDefaultPatternProducesValidJson() throws Exception {
38+
Tomcat tomcat = getTomcatInstance();
39+
Context ctx = getProgrammaticRootContext();
40+
41+
Tomcat.addServlet(ctx, "hello", new HelloWorldServlet());
42+
ctx.addServletMappingDecoded("/", "hello");
43+
44+
JsonAccessLogValve valve = new JsonAccessLogValve();
45+
valve.setDirectory(getTemporaryDirectory().getAbsolutePath());
46+
valve.setPrefix("access_json_test");
47+
valve.setSuffix(".log");
48+
ctx.getParent().getPipeline().addValve(valve);
49+
50+
tomcat.start();
51+
52+
ByteChunk res = new ByteChunk();
53+
res.setCharset(StandardCharsets.UTF_8);
54+
int rc = getUrl("http://localhost:" + getPort() + "/", res, null);
55+
56+
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
57+
Assert.assertEquals(HelloWorldServlet.RESPONSE_TEXT, res.toString());
58+
}
59+
60+
61+
@Test
62+
public void testCommonPatternProducesValidJson() throws Exception {
63+
Tomcat tomcat = getTomcatInstance();
64+
Context ctx = getProgrammaticRootContext();
65+
66+
Tomcat.addServlet(ctx, "hello", new HelloWorldServlet());
67+
ctx.addServletMappingDecoded("/", "hello");
68+
69+
JsonAccessLogValve valve = new JsonAccessLogValve();
70+
valve.setPattern("common");
71+
valve.setDirectory(getTemporaryDirectory().getAbsolutePath());
72+
valve.setPrefix("access_json_common");
73+
valve.setSuffix(".log");
74+
ctx.getParent().getPipeline().addValve(valve);
75+
76+
tomcat.start();
77+
78+
ByteChunk res = new ByteChunk();
79+
res.setCharset(StandardCharsets.UTF_8);
80+
int rc = getUrl("http://localhost:" + getPort() + "/", res, null);
81+
82+
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
83+
}
84+
85+
86+
@Test
87+
public void testCombinedPatternProducesValidJson() throws Exception {
88+
Tomcat tomcat = getTomcatInstance();
89+
Context ctx = getProgrammaticRootContext();
90+
91+
Tomcat.addServlet(ctx, "hello", new HelloWorldServlet());
92+
ctx.addServletMappingDecoded("/", "hello");
93+
94+
JsonAccessLogValve valve = new JsonAccessLogValve();
95+
valve.setPattern("combined");
96+
valve.setDirectory(getTemporaryDirectory().getAbsolutePath());
97+
valve.setPrefix("access_json_combined");
98+
valve.setSuffix(".log");
99+
ctx.getParent().getPipeline().addValve(valve);
100+
101+
tomcat.start();
102+
103+
ByteChunk res = new ByteChunk();
104+
res.setCharset(StandardCharsets.UTF_8);
105+
int rc = getUrl("http://localhost:" + getPort() + "/", res, null);
106+
107+
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
108+
}
109+
110+
111+
@Test
112+
public void testCustomPatternWithRequestHeaders() throws Exception {
113+
Tomcat tomcat = getTomcatInstance();
114+
Context ctx = getProgrammaticRootContext();
115+
116+
Tomcat.addServlet(ctx, "hello", new HelloWorldServlet());
117+
ctx.addServletMappingDecoded("/", "hello");
118+
119+
JsonAccessLogValve valve = new JsonAccessLogValve();
120+
// Pattern includes request header and response header elements
121+
valve.setPattern("%h %s %{User-Agent}i %{Content-Type}o");
122+
valve.setDirectory(getTemporaryDirectory().getAbsolutePath());
123+
valve.setPrefix("access_json_headers");
124+
valve.setSuffix(".log");
125+
ctx.getParent().getPipeline().addValve(valve);
126+
127+
tomcat.start();
128+
129+
ByteChunk res = new ByteChunk();
130+
res.setCharset(StandardCharsets.UTF_8);
131+
int rc = getUrl("http://localhost:" + getPort() + "/", res, null);
132+
133+
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
134+
}
135+
136+
137+
@Test
138+
public void testPatternWithCookiesAndSessionAttributes() throws Exception {
139+
Tomcat tomcat = getTomcatInstance();
140+
Context ctx = getProgrammaticRootContext();
141+
142+
Tomcat.addServlet(ctx, "hello", new HelloWorldServlet());
143+
ctx.addServletMappingDecoded("/", "hello");
144+
145+
JsonAccessLogValve valve = new JsonAccessLogValve();
146+
// Pattern includes cookies, request attributes, and session attributes
147+
valve.setPattern("%h %s %{JSESSIONID}c %{testAttr}r %{testSession}s");
148+
valve.setDirectory(getTemporaryDirectory().getAbsolutePath());
149+
valve.setPrefix("access_json_cookies");
150+
valve.setSuffix(".log");
151+
ctx.getParent().getPipeline().addValve(valve);
152+
153+
tomcat.start();
154+
155+
ByteChunk res = new ByteChunk();
156+
res.setCharset(StandardCharsets.UTF_8);
157+
int rc = getUrl("http://localhost:" + getPort() + "/", res, null);
158+
159+
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
160+
}
161+
162+
163+
@Test
164+
public void testCreateLogElementsOutputFormat() {
165+
JsonAccessLogValve valve = new JsonAccessLogValve();
166+
valve.setPattern("%h %s %b");
167+
168+
// Use createLogElements via the internal API
169+
AbstractAccessLogValve.AccessLogElement[] elements =
170+
valve.createLogElements();
171+
172+
// Verify that elements array is valid and has at least
173+
// opening brace + 3 fields + separators + closing brace
174+
Assert.assertNotNull(elements);
175+
Assert.assertTrue("Should have at least some elements",
176+
elements.length > 0);
177+
}
178+
}

test/org/apache/catalina/valves/TestJsonErrorReportValve.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,4 +409,69 @@ public void service(ServletRequest request, ServletResponse response) {
409409
new IllegalStateException("Root cause"));
410410
}
411411
}
412+
413+
414+
@Test
415+
public void testJsonErrorThrowableWithNullMessage() throws Exception {
416+
Tomcat tomcat = getTomcatInstance();
417+
((StandardHost) tomcat.getHost()).setErrorReportValveClass(JSON_VALVE);
418+
419+
Context ctx = getProgrammaticRootContext();
420+
421+
// Throwable with null message
422+
Tomcat.addServlet(ctx, "nullMsg", new ExceptionServlet(null));
423+
ctx.addServletMappingDecoded("/", "nullMsg");
424+
425+
tomcat.start();
426+
427+
ByteChunk res = new ByteChunk();
428+
res.setCharset(StandardCharsets.UTF_8);
429+
int rc = getUrl("http://localhost:" + getPort(), res, null);
430+
431+
Assert.assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, rc);
432+
433+
String body = res.toString();
434+
JSONParser parser = new JSONParser(body);
435+
LinkedHashMap<String, Object> json = parser.parseObject();
436+
437+
Assert.assertEquals("Exception Report", json.get("type"));
438+
Assert.assertEquals(500, ((Number) json.get("status")).intValue());
439+
// message should be empty since throwable.getMessage() is null
440+
Assert.assertEquals("", json.get("message"));
441+
Assert.assertNotNull(json.get("throwable"));
442+
}
443+
444+
445+
@Test
446+
public void testJsonErrorWithSetPropertyAndGetProperty() {
447+
JsonErrorReportValve valve = new JsonErrorReportValve();
448+
449+
// Inherited from ErrorReportValve
450+
Assert.assertTrue(valve.setProperty("errorCode.404", "/error404.json"));
451+
Assert.assertEquals("/error404.json", valve.getProperty("errorCode.404"));
452+
453+
Assert.assertTrue(valve.setProperty(
454+
"exceptionType.java.lang.NullPointerException", "/npe.json"));
455+
Assert.assertEquals("/npe.json", valve.getProperty(
456+
"exceptionType.java.lang.NullPointerException"));
457+
458+
// Unknown property returns false/null
459+
Assert.assertFalse(valve.setProperty("unknown.key", "value"));
460+
Assert.assertNull(valve.getProperty("unknown.key"));
461+
}
462+
463+
464+
@Test
465+
public void testJsonErrorShowReportShowServerInfoInherited() throws Exception {
466+
JsonErrorReportValve valve = new JsonErrorReportValve();
467+
468+
// These are inherited from ErrorReportValve
469+
Assert.assertTrue(valve.isShowReport());
470+
valve.setShowReport(false);
471+
Assert.assertFalse(valve.isShowReport());
472+
473+
Assert.assertTrue(valve.isShowServerInfo());
474+
valve.setShowServerInfo(false);
475+
Assert.assertFalse(valve.isShowServerInfo());
476+
}
412477
}

0 commit comments

Comments
 (0)