Skip to content

Commit abcb003

Browse files
committed
Add new FAT to test tcpOptions inactivityTimeout
1 parent 0dcdc40 commit abcb003

File tree

2 files changed

+252
-1
lines changed

2 files changed

+252
-1
lines changed

Diff for: dev/io.openliberty.transport.http_fat/fat/src/io/openliberty/transport/http_fat/FATSuite.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
@RunWith(Suite.class)
2424
@SuiteClasses({
2525
AccessListsTests.class,
26-
MaxOpenConnectionsTest.class
26+
MaxOpenConnectionsTest.class,
27+
InactivityTimeoutTests.class
2728
})
2829
public class FATSuite {
2930

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 IBM Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License 2.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*******************************************************************************/
10+
package io.openliberty.transport.http_fat;
11+
12+
import static org.junit.Assert.assertNotNull;
13+
14+
import java.io.BufferedReader;
15+
import java.io.InputStreamReader;
16+
import java.io.OutputStream;
17+
import java.net.Socket;
18+
import java.util.logging.Logger;
19+
20+
import org.junit.After;
21+
import org.junit.AfterClass;
22+
import org.junit.Before;
23+
import org.junit.BeforeClass;
24+
import org.junit.Test;
25+
import org.junit.runner.RunWith;
26+
27+
import com.ibm.websphere.simplicity.config.HttpEndpoint;
28+
import com.ibm.websphere.simplicity.config.ServerConfiguration;
29+
30+
import componenttest.annotation.ExpectedFFDC;
31+
import componenttest.annotation.Server;
32+
import componenttest.custom.junit.runner.FATRunner;
33+
import componenttest.custom.junit.runner.Mode;
34+
import componenttest.custom.junit.runner.Mode.TestMode;
35+
import componenttest.topology.impl.LibertyServer;
36+
37+
/**
38+
* Test to ensure that the tcpOptions inactivityTimeout works.
39+
*/
40+
@RunWith(FATRunner.class)
41+
@Mode(TestMode.FULL)
42+
public class InactivityTimeoutTests {
43+
44+
static final Logger LOG = Logger.getLogger(InactivityTimeoutTests.class.getName());
45+
46+
@Server("InactivityTimeout")
47+
public static LibertyServer server;
48+
49+
@BeforeClass
50+
public static void setup() throws Exception {
51+
// Start the server and use the class name so we can find logs easily.
52+
server.startServer(InactivityTimeoutTests.class.getSimpleName() + ".log");
53+
}
54+
55+
/**
56+
* Save the server configuration before each test, this should be the default server
57+
* configuration.
58+
*
59+
* @throws Exception
60+
*/
61+
@Before
62+
public void beforeTest() throws Exception {
63+
server.saveServerConfiguration();
64+
}
65+
66+
@AfterClass
67+
public static void tearDown() throws Exception {
68+
// Stop the server
69+
if (server != null && server.isStarted()) {
70+
//CWWKO0211E: TCP Channel defaultHttpEndpoint has been constructed with an incorrect configuration property value. Name: inactivityTimeout Value: -1 Valid Range: Minimum 0, Maximum 3600000 <br>[4/8/25, 21:04:00:557 EDT] 0000004c com.ibm.ws.channelfw.internal.ChannelFrameworkImpl
71+
//CWWKO0029E: An exception was generated when initializing chain CHAIN-defaultHttpEndpoint because of exception com.ibm.wsspi.channelfw.exception.ChannelException: A TCP Channel has been constructed with incorrect configuration property value, Channel Name: defaultHttpEndpoint name: inactivityTimeout value: -1 minimum Value: 0 maximum Value: 3600000
72+
server.stopServer("CWWKO0211E", "CWWKO0029E");
73+
}
74+
}
75+
76+
/**
77+
* Restore the server configuration to the default state after each test.
78+
*
79+
* @throws Exception
80+
*/
81+
@After
82+
public void afterTest() throws Exception {
83+
// Restore the server to the default state.
84+
server.setMarkToEndOfLog();
85+
server.setTraceMarkToEndOfDefaultTrace();
86+
server.restoreServerConfiguration();
87+
server.waitForConfigUpdateInLogUsingMark(null);
88+
}
89+
90+
/**
91+
* The test will check the default value of inactivityTimeout by searching the trace file.
92+
*
93+
* The default value is 60 seconds will be logged as 60000 miliseconds.
94+
*/
95+
@Test
96+
public void testInactivityTimeout_default() throws Exception {
97+
// Validate that inActivityTimeout default is 60s.
98+
assertNotNull("The default value of inactivityTimeout was not: 60000!", server.waitForStringInTraceUsingMark("inactivityTimeout: 60000"));
99+
}
100+
101+
/**
102+
* The test will set inactivityTimeout to a value of 120s and validate in the trace file that
103+
* the correct value is being used.
104+
*
105+
* The below configuration will be used to set inactivityTimeout to 120s:
106+
* <tcpOptions inactivityTimeout="120s"/>
107+
*
108+
* @throws Exception
109+
*/
110+
@Test
111+
public void testInactivityTimeout_nonDefault() throws Exception {
112+
ServerConfiguration configuration = server.getServerConfiguration();
113+
LOG.info("Server configuration that the test started with: " + configuration);
114+
115+
HttpEndpoint httpEndpoint = configuration.getHttpEndpoints().getById("defaultHttpEndpoint");
116+
httpEndpoint.getTcpOptions().setInactivityTimeout("120s");
117+
118+
server.setMarkToEndOfLog();
119+
server.setTraceMarkToEndOfDefaultTrace();
120+
server.updateServerConfiguration(configuration);
121+
server.waitForConfigUpdateInLogUsingMark(null);
122+
123+
// Validate that inactivityTimeout is set to 120000 (120s).
124+
assertNotNull("The configured value of inactivityTimeout was not 120000!", server.waitForStringInTraceUsingMark("inactivityTimeout: 120000"));
125+
}
126+
127+
/**
128+
* The test will set inactivityTimeout to a value of -1s and validate that an error occurs.
129+
*
130+
* The below configuration will be used to set inactivityTimeout to 120s:
131+
* <tcpOptions inactivityTimeout="-1"/>
132+
*
133+
* ExpectedFFDC:
134+
* >------Start of DE processing------ = [4/8/25, 19:35:17:901 EDT]
135+
* >Exception = com.ibm.wsspi.channelfw.exception.ChannelException
136+
* >Source = com.ibm.ws.tcpchannel.internal.TCPChannelConfiguration
137+
* >probeid = 102
138+
* >Stack Dump = com.ibm.wsspi.channelfw.exception.ChannelException: A TCP Channel has been constructed with incorrect configuration property value, Channel Name:
139+
* defaultHttpEndpoint name: inactivityTimeout value: -1 minimum Value: 0 maximum Value: 3600000
140+
* > at com.ibm.ws.tcpchannel.internal.TCPChannelConfiguration.setValues(TCPChannelConfiguration.java:553)
141+
*
142+
* @throws Exception
143+
*/
144+
@Test
145+
@ExpectedFFDC("com.ibm.wsspi.channelfw.exception.ChannelException")
146+
public void testInactivityTimeout_negative() throws Exception {
147+
ServerConfiguration configuration = server.getServerConfiguration();
148+
LOG.info("Server configuration that the test started with: " + configuration);
149+
150+
HttpEndpoint httpEndpoint = configuration.getHttpEndpoints().getById("defaultHttpEndpoint");
151+
httpEndpoint.getTcpOptions().setInactivityTimeout("-1");
152+
153+
server.setMarkToEndOfLog();
154+
server.setTraceMarkToEndOfDefaultTrace();
155+
server.updateServerConfiguration(configuration);
156+
server.waitForConfigUpdateInLogUsingMark(null);
157+
158+
// Validate error messages due to invalid config.
159+
assertNotNull("CWWKO0211E was not found and should have been!", server.waitForStringInTraceUsingMark("CWWKO0211E"));
160+
assertNotNull("CWWKO0029E was not found and should have been!", server.waitForStringInTraceUsingMark("CWWKO0029E"));
161+
}
162+
163+
/**
164+
* The test will set the inactivitiyTimeout to a value of 10s.
165+
*
166+
* A socket will be opened.
167+
*
168+
* The test will sleep for 15s which is greater then the inactivityTimeout.
169+
*
170+
* The test will then send a request and validate that the response is null since the
171+
* request should fail because the remote side of the Socket has closed due to the
172+
* inactivityTimeout.
173+
*
174+
* @throws Exception
175+
*/
176+
//@Test
177+
public void testInactivityTimeout() throws Exception {
178+
String expectedResponse = "HTTP/1.1 408 Request Timeout";
179+
180+
String address = server.getHostname() + ":" + server.getHttpDefaultPort();
181+
182+
String request = "GET /" + " HTTP/1.1\r\n" +
183+
"Host: " + address + "\r\n" +
184+
"\r\n";
185+
186+
// Set the inactivityTimeout to 10 seconds to make testing quicker than the default 60 second timeout.
187+
ServerConfiguration configuration = server.getServerConfiguration();
188+
LOG.info("Server configuration that the test started with: " + configuration);
189+
190+
HttpEndpoint httpEndpoint = configuration.getHttpEndpoints().getById("defaultHttpEndpoint");
191+
httpEndpoint.getTcpOptions().setInactivityTimeout("10s");
192+
193+
server.setMarkToEndOfLog();
194+
server.setTraceMarkToEndOfDefaultTrace();
195+
server.updateServerConfiguration(configuration);
196+
server.waitForConfigUpdateInLogUsingMark(null);
197+
198+
// Validate that inactivityTimeout is set to 10000 (10s).
199+
assertNotNull("The configured value of inactivityTimeout was not 10000!", server.waitForStringInTraceUsingMark("inactivityTimeout: 10000"));
200+
201+
// Ensure the TCP Channel has started.
202+
// CWWKO0219I: TCP Channel defaultHttpEndpoint has been started and is now listening for requests on host * (IPv4) port 8010.
203+
assertNotNull("The TCP Channel was not started!", server.waitForStringInLogUsingMark("CWWKO0219I"));
204+
205+
LOG.info("Creating a Socket connection.");
206+
try (Socket socket = new Socket(server.getHostname(), server.getHttpDefaultPort())) {
207+
208+
// Sleep for more than the inactivityTimeout.
209+
//Thread.sleep(15000);
210+
// Even without this we get a inactivitiyTimeout
211+
212+
String line;
213+
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
214+
OutputStream os = socket.getOutputStream();
215+
216+
// LOG.info("Read from the Socket.");
217+
// boolean expectedResponseFound = false;
218+
// while ((line = reader.readLine()) != null) {
219+
// LOG.info(line);
220+
// if (line.equals(expectedResponse)) {
221+
// expectedResponseFound = true;
222+
// }
223+
// }
224+
225+
// Maybe sleep here???
226+
227+
//assertTrue("The expected response: " + expectedResponse + " was not found!", expectedResponseFound);
228+
229+
// Sending the request and reading the response should not work since the remote side of the Socket should have closed due to an inactivitiyTimeout!
230+
LOG.info("Sending a request.");
231+
os.write(request.getBytes());
232+
233+
Thread.sleep(15000);
234+
235+
LOG.info("Read the response.");
236+
while ((line = reader.readLine()) != null) {
237+
LOG.info(line);
238+
//if (line.equals(expectedResponse)) {
239+
// expectedResponseFound = true;
240+
// }
241+
}
242+
//assertTrue("There should be no response data since the Socket was closed on the remote side due to an inactivityTimeout: " + response, response == null);
243+
244+
}
245+
}
246+
247+
// TODO: Review the tracing of the above test and validate what is happening.
248+
// Does the test above pass without any wait on the initial socket creation?
249+
250+
}

0 commit comments

Comments
 (0)