Skip to content

Commit 57f11ae

Browse files
committed
Added test for issue 580
TooTallNate#580
1 parent 2aada42 commit 57f11ae

File tree

3 files changed

+285
-1
lines changed

3 files changed

+285
-1
lines changed

src/test/java/org/java_websocket/issues/AllIssueTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030

3131
@RunWith(Suite.class)
3232
@Suite.SuiteClasses({
33-
org.java_websocket.issues.Issue609Test.class
33+
org.java_websocket.issues.Issue609Test.class,
34+
org.java_websocket.issues.Issue580Test.class
3435
})
3536
/**
3637
* Start all tests for issues
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Copyright (c) 2010-2017 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package org.java_websocket.issues;
27+
28+
import org.java_websocket.WebSocket;
29+
import org.java_websocket.client.WebSocketClient;
30+
import org.java_websocket.framing.CloseFrame;
31+
import org.java_websocket.handshake.ClientHandshake;
32+
import org.java_websocket.handshake.ServerHandshake;
33+
import org.java_websocket.server.WebSocketServer;
34+
import org.java_websocket.util.SocketUtil;
35+
import org.java_websocket.util.ThreadCheck;
36+
import org.junit.Rule;
37+
import org.junit.Test;
38+
39+
import java.net.InetSocketAddress;
40+
import java.net.URI;
41+
import java.util.concurrent.CountDownLatch;
42+
43+
public class Issue580Test {
44+
45+
@Rule
46+
public ThreadCheck zombies = new ThreadCheck();
47+
48+
private void runTestScenario(boolean closeBlocking) throws Exception {
49+
final CountDownLatch countServerDownLatch = new CountDownLatch( 1 );
50+
int port = SocketUtil.getAvailablePort();
51+
WebSocketServer ws = new WebSocketServer( new InetSocketAddress( port ) ) {
52+
@Override
53+
public void onOpen( WebSocket conn, ClientHandshake handshake ) {
54+
55+
}
56+
57+
@Override
58+
public void onClose( WebSocket conn, int code, String reason, boolean remote ) {
59+
60+
}
61+
62+
@Override
63+
public void onMessage( WebSocket conn, String message ) {
64+
65+
}
66+
67+
@Override
68+
public void onError( WebSocket conn, Exception ex ) {
69+
70+
}
71+
72+
@Override
73+
public void onStart() {
74+
countServerDownLatch.countDown();
75+
}
76+
};
77+
ws.start();
78+
countServerDownLatch.await();
79+
WebSocketClient clt = new WebSocketClient( new URI( "ws://localhost:" + port ) ) {
80+
@Override
81+
public void onOpen( ServerHandshake handshakedata ) {
82+
83+
}
84+
85+
@Override
86+
public void onMessage( String message ) {
87+
88+
}
89+
90+
@Override
91+
public void onClose( int code, String reason, boolean remote ) {
92+
93+
}
94+
95+
@Override
96+
public void onError( Exception ex ) {
97+
98+
}
99+
};
100+
clt.connectBlocking();
101+
clt.send("test");
102+
if (closeBlocking) {
103+
clt.closeBlocking();
104+
}
105+
ws.stop();
106+
Thread.sleep( 100 );
107+
}
108+
109+
@Test
110+
public void runNoCloseBlockingTestScenario0() throws Exception {
111+
runTestScenario(false);
112+
}
113+
@Test
114+
public void runNoCloseBlockingTestScenario1() throws Exception {
115+
runTestScenario(false);
116+
}
117+
@Test
118+
public void runNoCloseBlockingTestScenario2() throws Exception {
119+
runTestScenario(false);
120+
}
121+
@Test
122+
public void runNoCloseBlockingTestScenario3() throws Exception {
123+
runTestScenario(false);
124+
}
125+
@Test
126+
public void runNoCloseBlockingTestScenario4() throws Exception {
127+
runTestScenario(false);
128+
}
129+
@Test
130+
public void runNoCloseBlockingTestScenario5() throws Exception {
131+
runTestScenario(false);
132+
}
133+
@Test
134+
public void runNoCloseBlockingTestScenario6() throws Exception {
135+
runTestScenario(false);
136+
}
137+
@Test
138+
public void runNoCloseBlockingTestScenario7() throws Exception {
139+
runTestScenario(false);
140+
}
141+
@Test
142+
public void runNoCloseBlockingTestScenario8() throws Exception {
143+
runTestScenario(false);
144+
}
145+
@Test
146+
public void runNoCloseBlockingTestScenario9() throws Exception {
147+
runTestScenario(false);
148+
}
149+
150+
@Test
151+
public void runCloseBlockingTestScenario0() throws Exception {
152+
runTestScenario(true);
153+
}
154+
@Test
155+
public void runCloseBlockingTestScenario1() throws Exception {
156+
runTestScenario(true);
157+
}
158+
@Test
159+
public void runCloseBlockingTestScenario2() throws Exception {
160+
runTestScenario(true);
161+
}
162+
@Test
163+
public void runCloseBlockingTestScenario3() throws Exception {
164+
runTestScenario(true);
165+
}
166+
@Test
167+
public void runCloseBlockingTestScenario4() throws Exception {
168+
runTestScenario(true);
169+
}
170+
@Test
171+
public void runCloseBlockingTestScenario5() throws Exception {
172+
runTestScenario(true);
173+
}
174+
@Test
175+
public void runCloseBlockingTestScenario6() throws Exception {
176+
runTestScenario(true);
177+
}
178+
@Test
179+
public void runCloseBlockingTestScenario7() throws Exception {
180+
runTestScenario(true);
181+
}
182+
@Test
183+
public void runCloseBlockingTestScenario8() throws Exception {
184+
runTestScenario(true);
185+
}
186+
@Test
187+
public void runCloseBlockingTestScenario9() throws Exception {
188+
runTestScenario(true);
189+
}
190+
191+
}
192+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2010-2017 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package org.java_websocket.util;
27+
import java.util.HashMap;
28+
import java.util.Map;
29+
import java.util.concurrent.locks.LockSupport;
30+
31+
import org.junit.Assert;
32+
import org.junit.rules.ExternalResource;
33+
/**
34+
* Makes test fail if new threads are still alive after tear-down.
35+
*/
36+
public class ThreadCheck extends ExternalResource {
37+
private Map<Long,Thread> map = new HashMap<Long,Thread>();
38+
39+
@Override protected void before() throws Throwable {
40+
map = getThreadMap();
41+
}
42+
43+
@Override protected void after() {
44+
long time = System.currentTimeMillis();
45+
do {
46+
LockSupport.parkNanos( 10000000 );
47+
} while ( checkZombies( true ) && System.currentTimeMillis() - time < 1000 );
48+
49+
checkZombies( false );
50+
}
51+
52+
private boolean checkZombies( boolean testOnly ) {
53+
Map<Long,Thread> newMap = getThreadMap();
54+
55+
int zombies = 0;
56+
for( Thread t : newMap.values() ) {
57+
Thread prev = map.get( t.getId() );
58+
if( prev == null ) {
59+
zombies++;
60+
if( testOnly )
61+
return true;
62+
63+
StringBuilder b = new StringBuilder( 4096 );
64+
appendStack( t, b.append( "\n" ).append( t.getName() ) );
65+
System.err.println( b );
66+
}
67+
}
68+
if( zombies > 0 && ! testOnly )
69+
Assert.fail( "Found " + zombies + " zombie thread(s) " );
70+
71+
return zombies > 0;
72+
}
73+
74+
private Map<Long,Thread> getThreadMap() {
75+
Map<Long,Thread> map = new HashMap<Long,Thread>();
76+
Thread[] threads = new Thread[ Thread.activeCount() * 2 ];
77+
int actualNb = Thread.enumerate( threads );
78+
for( int i = 0; i < actualNb; i++ ) {
79+
map.put( threads[ i ].getId(), threads[ i ] );
80+
}
81+
return map;
82+
}
83+
84+
private static void appendStack( Thread th, StringBuilder s ) {
85+
StackTraceElement[] st = th.getStackTrace();
86+
for( int i = 0; i < st.length; i++ ) {
87+
s.append( "\n at " );
88+
s.append( st[ i ] );
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)