Skip to content

Commit 2e4605e

Browse files
committed
Create io.openliberty.checkpoint_fat_wsoc
1 parent 87eea94 commit 2e4605e

File tree

20 files changed

+1007
-0
lines changed

20 files changed

+1007
-0
lines changed

Diff for: dev/io.openliberty.checkpoint_fat_wsoc/.classpath

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="src" path="fat/src"/>
4+
<classpathentry kind="src" path="test-applications/basic.war/src"/>
5+
<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
6+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
7+
<attributes>
8+
<attribute name="module" value="true"/>
9+
</attributes>
10+
</classpathentry>
11+
<classpathentry kind="output" path="bin"/>
12+
</classpath>

Diff for: dev/io.openliberty.checkpoint_fat_wsoc/.project

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>io.openliberty.checkpoint_fat_wsoc</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.eclipse.jdt.core.javabuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
<buildCommand>
14+
<name>bndtools.core.bndbuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
18+
</buildSpec>
19+
<natures>
20+
<nature>org.eclipse.jdt.core.javanature</nature>
21+
<nature>bndtools.core.bndnature</nature>
22+
</natures>
23+
</projectDescription>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
compileErrorAction=build
2+
eclipse.preferences.version=1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#Ant properties
2+
#Automatically generated by the ant prepare.settings.files task
3+
eclipse.preferences.version=1
4+
encoding/<project>=UTF-8

Diff for: dev/io.openliberty.checkpoint_fat_wsoc/.settings/org.eclipse.jdt.core.prefs

+294
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
eclipse.preferences.version=1
2+
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
3+
org.eclipse.jdt.ui.ignorelowercasenames=true
4+
org.eclipse.jdt.ui.importorder=java;javax;org;com;
5+
org.eclipse.jdt.ui.javadoc=true
6+
org.eclipse.jdt.ui.ondemandthreshold=99
7+
org.eclipse.jdt.ui.staticondemandthreshold=99
8+
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/** */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
9+
sp_cleanup.add_default_serial_version_id=true
10+
sp_cleanup.add_generated_serial_version_id=false
11+
sp_cleanup.add_missing_annotations=true
12+
sp_cleanup.add_missing_deprecated_annotations=true
13+
sp_cleanup.add_missing_methods=false
14+
sp_cleanup.add_missing_nls_tags=false
15+
sp_cleanup.add_missing_override_annotations=true
16+
sp_cleanup.add_missing_override_annotations_interface_methods=true
17+
sp_cleanup.add_serial_version_id=false
18+
sp_cleanup.always_use_blocks=true
19+
sp_cleanup.always_use_parentheses_in_expressions=false
20+
sp_cleanup.always_use_this_for_non_static_field_access=false
21+
sp_cleanup.always_use_this_for_non_static_method_access=false
22+
sp_cleanup.convert_to_enhanced_for_loop=false
23+
sp_cleanup.correct_indentation=false
24+
sp_cleanup.format_source_code=true
25+
sp_cleanup.format_source_code_changes_only=false
26+
sp_cleanup.make_local_variable_final=false
27+
sp_cleanup.make_parameters_final=false
28+
sp_cleanup.make_private_fields_final=false
29+
sp_cleanup.make_type_abstract_if_missing_method=false
30+
sp_cleanup.make_variable_declarations_final=true
31+
sp_cleanup.never_use_blocks=false
32+
sp_cleanup.never_use_parentheses_in_expressions=true
33+
sp_cleanup.on_save_use_additional_actions=true
34+
sp_cleanup.organize_imports=true
35+
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
36+
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
37+
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
38+
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
39+
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
40+
sp_cleanup.remove_private_constructors=true
41+
sp_cleanup.remove_trailing_whitespaces=true
42+
sp_cleanup.remove_trailing_whitespaces_all=true
43+
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
44+
sp_cleanup.remove_unnecessary_casts=true
45+
sp_cleanup.remove_unnecessary_nls_tags=true
46+
sp_cleanup.remove_unused_imports=true
47+
sp_cleanup.remove_unused_local_variables=false
48+
sp_cleanup.remove_unused_private_fields=true
49+
sp_cleanup.remove_unused_private_members=false
50+
sp_cleanup.remove_unused_private_methods=true
51+
sp_cleanup.remove_unused_private_types=true
52+
sp_cleanup.sort_members=false
53+
sp_cleanup.sort_members_all=false
54+
sp_cleanup.use_blocks=false
55+
sp_cleanup.use_blocks_only_for_return_and_throw=false
56+
sp_cleanup.use_parentheses_in_expressions=false
57+
sp_cleanup.use_this_for_non_static_field_access=false
58+
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
59+
sp_cleanup.use_this_for_non_static_method_access=false
60+
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

Diff for: dev/io.openliberty.checkpoint_fat_wsoc/bnd.bnd

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
-include= ~../cnf/resources/bnd/bundle.props
11+
bVersion=1.0
12+
13+
src: \
14+
fat/src,\
15+
test-applications/basic.war/src
16+
17+
fat.project: true
18+
19+
tested.features: \
20+
checkpoint,\
21+
servlet-5.0,\
22+
servlet-6.0,\
23+
servlet-6.1,\
24+
websocket-2.0,\
25+
websocket-2.1,\
26+
websocket-2.2
27+
28+
29+
-buildpath: \
30+
org.asynchttpclient:async-http-client;version=2.12.3,\
31+
io.openliberty.io.netty;version=latest,\
32+
com.ibm.websphere.appserver.api.wsoc;version=latest,\
33+
com.ibm.websphere.javaee.servlet.4.0;version=latest,\
34+
com.ibm.ws.wsoc.1.1;version=latest,\
35+
com.ibm.websphere.javaee.websocket.1.0;version=latest

Diff for: dev/io.openliberty.checkpoint_fat_wsoc/build.gradle

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
11+
dependencies {
12+
requiredLibs "org.asynchttpclient:async-http-client:2.12.3",
13+
"org.asynchttpclient:async-http-client-netty-utils:2.12.3",
14+
"com.typesafe.netty:netty-reactive-streams:2.0.4",
15+
"org.reactivestreams:reactive-streams:1.0.4",
16+
'junit:junit:4.12',
17+
project(":io.openliberty.io.netty")
18+
}
19+
addRequiredLibraries.dependsOn addJakartaTransformer
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
# YML metadata file made use of by the Cognitive Ecosystem.
3+
# Reference Cognitive Metadata is available at: https://github.com/OpenLiberty/open-liberty/tree/integration/dev/build.example_fat/cognitiveMetadata.yml
4+
# description: Uncomment this field and add a description to give some notes about this bucket.
5+
# triageNotes: Uncomment this field if there are some short notes you would like Pipeline Monitors to see when triaging this bucket.
6+
functionalArea: InstantOn
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
2+
/*******************************************************************************
3+
* Copyright (c) 2025 IBM Corporation and others.
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
package io.openliberty.checkpoint.fat;
12+
13+
import static org.junit.Assert.assertNotNull;
14+
import static org.junit.Assert.assertTrue;
15+
16+
import java.lang.StringBuilder;
17+
import java.util.Arrays;
18+
import java.util.concurrent.CountDownLatch;
19+
import java.util.concurrent.TimeUnit;
20+
import java.util.logging.Logger;
21+
22+
import org.asynchttpclient.Dsl;
23+
import org.asynchttpclient.ws.WebSocket;
24+
import org.asynchttpclient.ws.WebSocketListener;
25+
import org.asynchttpclient.ws.WebSocketUpgradeHandler;
26+
import org.junit.AfterClass;
27+
import org.junit.Before;
28+
import org.junit.BeforeClass;
29+
import org.junit.Test;
30+
import org.junit.runner.RunWith;
31+
32+
import com.ibm.websphere.simplicity.ShrinkHelper;
33+
34+
import componenttest.annotation.CheckpointTest;
35+
import componenttest.annotation.Server;
36+
import componenttest.custom.junit.runner.FATRunner;
37+
import componenttest.topology.impl.LibertyServer;
38+
import io.openliberty.checkpoint.spi.CheckpointPhase;
39+
40+
/**
41+
* Basic WebSockets tests to ensure the behavior works as expected after a checkpoint restore.
42+
*/
43+
@RunWith(FATRunner.class)
44+
@CheckpointTest
45+
public class BasicTest {
46+
47+
@Server("basicWsocServer")
48+
public static LibertyServer server;
49+
50+
private static final Logger LOG = Logger.getLogger(BasicTest.class.getName());
51+
52+
private static final String APP_NAME = "basic";
53+
54+
private static Boolean IS_EXPECTED_RESULT = false;
55+
56+
private static CountDownLatch latch; // Used to address timing issues between when the message is recived and when the assert is checked
57+
58+
@BeforeClass
59+
public static void setUp() throws Exception {
60+
61+
// Build the war app and add the dependencies
62+
ShrinkHelper.defaultDropinApp(server, APP_NAME + ".war", "io.openliberty.wsoc.basic");
63+
64+
server.setCheckpoint(CheckpointPhase.AFTER_APP_START, true, null);
65+
server.setCheckpoint(CheckpointPhase.AFTER_APP_START, false,
66+
server -> {
67+
assertNotNull("'SRVE0169I: Loading Web Module: " + APP_NAME + "' message not found in log before rerstore",
68+
server.waitForStringInLogUsingMark("SRVE0169I: .*" + APP_NAME, 0));
69+
assertNotNull("'CWWKZ0001I: Application " + APP_NAME + " started' message not found in log.",
70+
server.waitForStringInLogUsingMark("CWWKZ0001I: .*" + APP_NAME, 0));
71+
});
72+
server.startServer();
73+
server.checkpointRestore();
74+
}
75+
76+
@AfterClass
77+
public static void tearDown() throws Exception {
78+
79+
if (server != null && server.isStarted()) {
80+
server.stopServer();
81+
}
82+
83+
}
84+
85+
@Before
86+
public void resetResult() throws Exception {
87+
IS_EXPECTED_RESULT = false;
88+
latch = null;
89+
}
90+
91+
private WebSocketUpgradeHandler createWebSocketUpgradeHandler(Object expectedResult) {
92+
93+
latch = new CountDownLatch(1); // forces the asserts in each test to be checked once the message is recieved (via countdown / await)
94+
95+
WebSocketUpgradeHandler.Builder upgradeHandlerBuilder = new WebSocketUpgradeHandler.Builder();
96+
WebSocketUpgradeHandler wsHandler = upgradeHandlerBuilder
97+
.addWebSocketListener(new WebSocketListener() {
98+
@Override
99+
public void onOpen(WebSocket websocket) {
100+
// WebSocket connection opened
101+
LOG.info("Opened Websocket");
102+
}
103+
104+
@Override
105+
public void onClose(WebSocket websocket, int code, String reason) {
106+
// WebSocket connection closed
107+
LOG.info("Closed Websocket");
108+
}
109+
110+
@Override
111+
public void onError(Throwable t) {
112+
// WebSocket connection error
113+
LOG.info("Session Error Occurred: " + t);
114+
}
115+
116+
@Override
117+
public void onBinaryFrame(byte[] payload, boolean finalFragment, int rsv) {
118+
// Log message
119+
StringBuilder sb = new StringBuilder();
120+
for (byte b : payload) {
121+
sb.append((char) b);
122+
}
123+
LOG.info("Debugging binary message: " + sb.toString());
124+
IS_EXPECTED_RESULT = Arrays.equals(payload, (byte[]) expectedResult);
125+
latch.countDown();
126+
}
127+
128+
@Override
129+
public void onTextFrame(String payload, boolean finalFragment, int rsv) {
130+
// Log message
131+
LOG.info("Debugging text message: " + payload);
132+
IS_EXPECTED_RESULT = expectedResult.equals(payload);
133+
latch.countDown();
134+
}
135+
})
136+
.build();
137+
return wsHandler;
138+
}
139+
140+
/*
141+
* Tested the PathParam annotation
142+
*/
143+
@Test
144+
public void testAnnotatedByteArray() throws Exception {
145+
Object expectedResult = "test message".getBytes();
146+
147+
WebSocketUpgradeHandler wsHandler = createWebSocketUpgradeHandler(expectedResult);
148+
149+
WebSocket webSocketClient = Dsl.asyncHttpClient()
150+
.prepareGet("ws://" +
151+
server.getHostname() + ":" +
152+
server.getHttpDefaultPort() + "/" +
153+
APP_NAME +
154+
"/annotatedByteArray/true")
155+
.setRequestTimeout(5000)
156+
.execute(wsHandler)
157+
.get();
158+
159+
if (webSocketClient.isOpen()) {
160+
LOG.info("sending message");
161+
webSocketClient.sendBinaryFrame("test message".getBytes());
162+
}
163+
latch.await(3L, TimeUnit.SECONDS);
164+
webSocketClient.sendCloseFrame();
165+
assertTrue("Results do not match! ", IS_EXPECTED_RESULT);
166+
}
167+
168+
/*
169+
* Verifies the decoder annotation is picked up
170+
*/
171+
@Test
172+
public void testDecoder() throws Exception {
173+
Object expectedResult = "[class io.openliberty.wsoc.basic.BinaryStreamDecoder]";
174+
175+
WebSocketUpgradeHandler wsHandler = createWebSocketUpgradeHandler(expectedResult);
176+
WebSocket webSocketClient = Dsl.asyncHttpClient()
177+
.prepareGet("ws://" +
178+
server.getHostname() + ":" +
179+
server.getHttpDefaultPort() + "/" +
180+
APP_NAME +
181+
"/defaults")
182+
.setRequestTimeout(5000)
183+
.execute(wsHandler)
184+
.get();
185+
186+
if (webSocketClient.isOpen()) {
187+
LOG.info("sending message");
188+
webSocketClient.sendTextFrame("decoders");
189+
}
190+
latch.await(3L, TimeUnit.SECONDS);
191+
webSocketClient.sendCloseFrame();
192+
assertTrue("Results do not match! ", IS_EXPECTED_RESULT);
193+
}
194+
195+
/*
196+
* Verifies the WsWsocServerContainer#doUprade works (deprecated in 2.1)
197+
*/
198+
@Test
199+
public void testUpgrade() throws Exception {
200+
Object expectedResult = "got your message hello world";
201+
202+
WebSocketUpgradeHandler wsHandler = createWebSocketUpgradeHandler(expectedResult);
203+
WebSocket webSocketClient = Dsl.asyncHttpClient()
204+
.prepareGet("ws://" +
205+
server.getHostname() + ":" +
206+
server.getHttpDefaultPort() + "/" +
207+
APP_NAME +
208+
"/upgradeEcho")
209+
.setRequestTimeout(5000)
210+
.execute(wsHandler)
211+
.get();
212+
213+
if (webSocketClient.isOpen()) {
214+
LOG.info("sending message");
215+
webSocketClient.sendTextFrame("hello world");
216+
}
217+
latch.await(3L, TimeUnit.SECONDS);
218+
webSocketClient.sendCloseFrame();
219+
assertTrue("Results do not match! ", IS_EXPECTED_RESULT);
220+
}
221+
222+
}

0 commit comments

Comments
 (0)