Skip to content

Commit 2da582b

Browse files
csutherlclaude
andcommitted
Add SSL context tests and stress test categorization
Added TestSSLContext with 15 tests for context creation in different modes, protocol-specific contexts, options management, verification levels, session cache configuration, and cipher suites. Added StressTest marker interface for categorizing performance tests separately from regular CI runs. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 0630110 commit 2da582b

2 files changed

Lines changed: 324 additions & 0 deletions

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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.tomcat.jni;
18+
19+
/**
20+
* Marker interface for stress tests.
21+
*
22+
* Tests annotated with @Category(StressTest.class) are stress/performance
23+
* tests that create many objects in loops to verify memory management and
24+
* detect leaks. These tests:
25+
*
26+
* - May run slower than regular unit tests
27+
* - Are useful for detecting memory leaks
28+
* - Should not run in standard CI builds by default
29+
*
30+
* To run only stress tests:
31+
* ant test -Dtest.categories=StressTest
32+
*
33+
* To exclude stress tests:
34+
* ant test -Dtest.exclude.categories=StressTest
35+
*/
36+
public interface StressTest {
37+
// Marker interface - no methods
38+
}
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
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.tomcat.jni;
18+
19+
import org.junit.After;
20+
import org.junit.Assert;
21+
import org.junit.Before;
22+
import org.junit.Test;
23+
import org.junit.experimental.categories.Category;
24+
25+
/**
26+
* Tests for SSLContext creation and configuration.
27+
*/
28+
public class TestSSLContext extends BaseTest {
29+
30+
private long pool;
31+
32+
@Before
33+
public void setup() {
34+
requireLibrary();
35+
pool = Pool.create(0);
36+
}
37+
38+
@After
39+
public void destroyPool() {
40+
if (pool != 0) {
41+
Pool.destroy(pool);
42+
}
43+
}
44+
45+
@Test
46+
public void testCreateServerContext() throws Exception {
47+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
48+
Assert.assertNotEquals("Server context should be created", 0, ctx);
49+
50+
int result = SSLContext.free(ctx);
51+
Assert.assertEquals("Context should be freed successfully", 0, result);
52+
}
53+
54+
@Test
55+
public void testCreateClientContext() throws Exception {
56+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_CLIENT);
57+
Assert.assertNotEquals("Client context should be created", 0, ctx);
58+
59+
int result = SSLContext.free(ctx);
60+
Assert.assertEquals("Context should be freed successfully", 0, result);
61+
}
62+
63+
@Test
64+
public void testCreateCombinedContext() throws Exception {
65+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_COMBINED);
66+
Assert.assertNotEquals("Combined context should be created", 0, ctx);
67+
68+
int result = SSLContext.free(ctx);
69+
Assert.assertEquals("Context should be freed successfully", 0, result);
70+
}
71+
72+
@Test
73+
public void testCreateContextTLSv13Only() throws Exception {
74+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_TLSV1_3, SSL.SSL_MODE_SERVER);
75+
Assert.assertNotEquals("TLSv1.3-only context should be created", 0, ctx);
76+
77+
SSLContext.free(ctx);
78+
}
79+
80+
@Test
81+
public void testCreateContextTLSv12Only() throws Exception {
82+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_TLSV1_2, SSL.SSL_MODE_SERVER);
83+
Assert.assertNotEquals("TLSv1.2-only context should be created", 0, ctx);
84+
85+
SSLContext.free(ctx);
86+
}
87+
88+
@Test
89+
public void testCreateMultipleContexts() throws Exception {
90+
// Create multiple contexts from same pool
91+
long ctx1 = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
92+
long ctx2 = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_CLIENT);
93+
94+
Assert.assertNotEquals("Context 1 should be created", 0, ctx1);
95+
Assert.assertNotEquals("Context 2 should be created", 0, ctx2);
96+
Assert.assertNotEquals("Contexts should be different", ctx1, ctx2);
97+
98+
SSLContext.free(ctx1);
99+
SSLContext.free(ctx2);
100+
}
101+
102+
@Test
103+
public void testSetAndGetOptions() throws Exception {
104+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
105+
106+
// Set some options
107+
SSLContext.setOptions(ctx, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3);
108+
109+
// Get options back
110+
int options = SSLContext.getOptions(ctx);
111+
112+
// Verify the options we set are present
113+
Assert.assertTrue("SSL_OP_NO_SSLv2 should be set",
114+
(options & SSL.SSL_OP_NO_SSLv2) != 0);
115+
Assert.assertTrue("SSL_OP_NO_SSLv3 should be set",
116+
(options & SSL.SSL_OP_NO_SSLv3) != 0);
117+
118+
SSLContext.free(ctx);
119+
}
120+
121+
@Test
122+
public void testClearOptions() throws Exception {
123+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
124+
125+
// Set an option
126+
SSLContext.setOptions(ctx, SSL.SSL_OP_NO_COMPRESSION);
127+
128+
// Verify it's set
129+
int options = SSLContext.getOptions(ctx);
130+
Assert.assertTrue("Option should be set",
131+
(options & SSL.SSL_OP_NO_COMPRESSION) != 0);
132+
133+
// Clear it
134+
SSLContext.clearOptions(ctx, SSL.SSL_OP_NO_COMPRESSION);
135+
136+
// Verify it's cleared
137+
options = SSLContext.getOptions(ctx);
138+
Assert.assertTrue("Option should be cleared",
139+
(options & SSL.SSL_OP_NO_COMPRESSION) == 0);
140+
141+
SSLContext.free(ctx);
142+
}
143+
144+
@Test
145+
public void testSetVerifyLevel() throws Exception {
146+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
147+
148+
// Set different verification levels - these should not throw
149+
SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_NONE, 0);
150+
SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_OPTIONAL, 10);
151+
SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_REQUIRE, 10);
152+
153+
SSLContext.free(ctx);
154+
}
155+
156+
@Test
157+
public void testSessionCacheSize() throws Exception {
158+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
159+
160+
// Set cache size
161+
long newSize = SSLContext.setSessionCacheSize(ctx, 1024);
162+
Assert.assertTrue("Session cache size should be set", newSize > 0);
163+
164+
// Get cache size
165+
long size = SSLContext.getSessionCacheSize(ctx);
166+
Assert.assertTrue("Session cache size should be retrievable", size > 0);
167+
168+
SSLContext.free(ctx);
169+
}
170+
171+
@Test
172+
public void testSessionCacheTimeout() throws Exception {
173+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
174+
175+
// Set cache timeout (in seconds)
176+
long newTimeout = SSLContext.setSessionCacheTimeout(ctx, 300);
177+
Assert.assertTrue("Session cache timeout should be set", newTimeout > 0);
178+
179+
// Get cache timeout
180+
long timeout = SSLContext.getSessionCacheTimeout(ctx);
181+
Assert.assertTrue("Session cache timeout should be retrievable", timeout > 0);
182+
183+
SSLContext.free(ctx);
184+
}
185+
186+
@Test
187+
public void testSessionCacheMode() throws Exception {
188+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
189+
190+
// Set cache mode
191+
long prevMode = SSLContext.setSessionCacheMode(ctx, SSL.SSL_SESS_CACHE_SERVER);
192+
Assert.assertTrue("Previous mode should be returned", prevMode >= 0);
193+
194+
// Get cache mode
195+
long mode = SSLContext.getSessionCacheMode(ctx);
196+
Assert.assertEquals("Cache mode should be SERVER", SSL.SSL_SESS_CACHE_SERVER, mode);
197+
198+
// Turn off caching
199+
SSLContext.setSessionCacheMode(ctx, SSL.SSL_SESS_CACHE_OFF);
200+
mode = SSLContext.getSessionCacheMode(ctx);
201+
Assert.assertEquals("Cache mode should be OFF", SSL.SSL_SESS_CACHE_OFF, mode);
202+
203+
SSLContext.free(ctx);
204+
}
205+
206+
@Test
207+
public void testSessionStatistics() throws Exception {
208+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
209+
210+
// Get session statistics - these should all return without error
211+
// Initial values should be 0
212+
long accepts = SSLContext.sessionAccept(ctx);
213+
Assert.assertTrue("Session accepts should be non-negative", accepts >= 0);
214+
215+
long acceptsGood = SSLContext.sessionAcceptGood(ctx);
216+
Assert.assertTrue("Session accepts good should be non-negative", acceptsGood >= 0);
217+
218+
long hits = SSLContext.sessionHits(ctx);
219+
Assert.assertTrue("Session hits should be non-negative", hits >= 0);
220+
221+
long misses = SSLContext.sessionMisses(ctx);
222+
Assert.assertTrue("Session misses should be non-negative", misses >= 0);
223+
224+
long timeouts = SSLContext.sessionTimeouts(ctx);
225+
Assert.assertTrue("Session timeouts should be non-negative", timeouts >= 0);
226+
227+
long number = SSLContext.sessionNumber(ctx);
228+
Assert.assertTrue("Session number should be non-negative", number >= 0);
229+
230+
SSLContext.free(ctx);
231+
}
232+
233+
@Test
234+
public void testSetSessionIdContext() throws Exception {
235+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
236+
237+
// Set session ID context
238+
byte[] sidCtx = "test-server".getBytes();
239+
boolean result = SSLContext.setSessionIdContext(ctx, sidCtx);
240+
Assert.assertTrue("Session ID context should be set successfully", result);
241+
242+
// Test with default context
243+
result = SSLContext.setSessionIdContext(ctx, SSLContext.DEFAULT_SESSION_ID_CONTEXT);
244+
Assert.assertTrue("Default session ID context should be set successfully", result);
245+
246+
SSLContext.free(ctx);
247+
}
248+
249+
@Test
250+
public void testMultipleCipherOperations() throws Exception {
251+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
252+
253+
// Get default ciphers
254+
String[] ciphers = SSLContext.getCiphers(ctx);
255+
Assert.assertNotNull("Ciphers should not be null", ciphers);
256+
Assert.assertTrue("Should have at least one cipher", ciphers.length > 0);
257+
258+
// Set a specific cipher suite
259+
boolean result = SSLContext.setCipherSuite(ctx, "HIGH:!aNULL:!MD5");
260+
Assert.assertTrue("Cipher suite should be set successfully", result);
261+
262+
// Get ciphers again
263+
ciphers = SSLContext.getCiphers(ctx);
264+
Assert.assertNotNull("Ciphers should not be null after setting", ciphers);
265+
Assert.assertTrue("Should still have ciphers", ciphers.length > 0);
266+
267+
SSLContext.free(ctx);
268+
}
269+
270+
@Test
271+
@Category(StressTest.class)
272+
public void testLifecycleUnderLoad() throws Exception {
273+
// Stress test: create and destroy many contexts
274+
for (int i = 0; i < 100; i++) {
275+
long ctx = SSLContext.make(pool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
276+
Assert.assertNotEquals("Context " + i + " should be created", 0, ctx);
277+
278+
// Perform some operations
279+
SSLContext.setOptions(ctx, SSL.SSL_OP_NO_SSLv2);
280+
SSLContext.setSessionCacheSize(ctx, 1024);
281+
282+
int result = SSLContext.free(ctx);
283+
Assert.assertEquals("Context " + i + " should be freed", 0, result);
284+
}
285+
}
286+
}

0 commit comments

Comments
 (0)