1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.conscrypt;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertNull;
21import static org.junit.Assert.assertSame;
22import static org.mockito.Matchers.same;
23import static org.mockito.Mockito.any;
24import static org.mockito.Mockito.mock;
25import static org.mockito.Mockito.verify;
26import static org.mockito.Mockito.when;
27
28import java.security.cert.Certificate;
29import javax.net.ssl.SSLSession;
30import org.junit.Before;
31import org.junit.Test;
32
33public abstract class AbstractSessionContextTest<T extends AbstractSessionContext> {
34    private T context;
35
36    @Before
37    public void setup() {
38        context = newContext();
39    }
40
41    abstract T newContext();
42    abstract int size(T context);
43    private static NativeSslSession[] toArray(NativeSslSession... sessions) {
44        return sessions;
45    }
46
47    abstract NativeSslSession getCachedSession(T context, NativeSslSession s);
48
49    @Test
50    public void testSimpleAddition() {
51        NativeSslSession a = newSession("a");
52        NativeSslSession b = newSession("b");
53
54        context.cacheSession(a);
55        assertSessionContextContents(toArray(a), toArray(b));
56
57        context.cacheSession(b);
58        assertSessionContextContents(toArray(a, b), toArray());
59    }
60
61    @Test
62    public void testTrimToSize() {
63        NativeSslSession a = newSession("a");
64        NativeSslSession b = newSession("b");
65        NativeSslSession c = newSession("c");
66        NativeSslSession d = newSession("d");
67
68        context.cacheSession(a);
69        context.cacheSession(b);
70        context.cacheSession(c);
71        context.cacheSession(d);
72        assertSessionContextContents(toArray(a, b, c, d), toArray());
73
74        context.setSessionCacheSize(2);
75        assertSessionContextContents(toArray(c, d), toArray(a, b));
76    }
77
78    @Test
79    public void testImplicitRemovalOfOldest() {
80        context.setSessionCacheSize(2);
81        NativeSslSession a = newSession("a");
82        NativeSslSession b = newSession("b");
83        NativeSslSession c = newSession("c");
84        NativeSslSession d = newSession("d");
85
86        context.cacheSession(a);
87        assertSessionContextContents(toArray(a), toArray(b, c, d));
88
89        context.cacheSession(b);
90        assertSessionContextContents(toArray(a, b), toArray(c, d));
91
92        context.cacheSession(c);
93        assertSessionContextContents(toArray(b, c), toArray(a, d));
94
95        context.cacheSession(d);
96        assertSessionContextContents(toArray(c, d), toArray(a, b));
97    }
98
99    @Test
100    public void testSerializeSession() throws Exception {
101        Certificate mockCert = mock(Certificate.class);
102        when(mockCert.getEncoded()).thenReturn(new byte[] {0x05, 0x06, 0x07, 0x10});
103
104        byte[] encodedBytes = new byte[] {0x01, 0x02, 0x03};
105        NativeSslSession session = new MockSessionBuilder()
106                .id(new byte[] {0x11, 0x09, 0x03, 0x20})
107                .host("ssl.example.com")
108                .encodedBytes(encodedBytes)
109                .build();
110
111        SSLClientSessionCache mockCache = mock(SSLClientSessionCache.class);
112        ClientSessionContext context = new ClientSessionContext();
113        context.setPersistentCache(mockCache);
114
115        context.cacheSession(session);
116        verify(mockCache).putSessionData(any(SSLSession.class), same(encodedBytes));
117    }
118
119    private void assertSessionContextContents(
120            NativeSslSession[] contains, NativeSslSession[] excludes) {
121        assertEquals(contains.length, size(context));
122
123        for (NativeSslSession s : contains) {
124            assertSame(s.getPeerHost(), s, getCachedSession(context, s));
125        }
126        for (NativeSslSession s : excludes) {
127            assertNull(s.getPeerHost(), getCachedSession(context, s));
128        }
129    }
130
131    private NativeSslSession newSession(String host) {
132        return new MockSessionBuilder().host(host).build();
133    }
134}
135