1+ // Licensed to the Apache Software Foundation (ASF) under one
2+ // or more contributor license agreements. See the NOTICE file
3+ // distributed with this work for additional information
4+ // regarding copyright ownership. The ASF licenses this file
5+ // to you under the Apache License, Version 2.0 (the
6+ // "License"); you may not use this file except in compliance
7+ // with 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,
12+ // software distributed under the License is distributed on an
13+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+ // KIND, either express or implied. See the License for the
15+ // specific language governing permissions and limitations
16+ // under the License.
17+
18+ package org .apache .cloudstack .utils .cache ;
19+
20+ import static org .junit .Assert .assertEquals ;
21+
22+ import java .util .function .Function ;
23+
24+ import org .junit .Assert ;
25+ import org .junit .Before ;
26+ import org .junit .Test ;
27+ import org .junit .runner .RunWith ;
28+ import org .mockito .Mockito ;
29+ import org .mockito .junit .MockitoJUnitRunner ;
30+
31+ @ RunWith (MockitoJUnitRunner .class )
32+ public class LazyCacheTest {
33+ private final long expireSeconds = 1 ;
34+ private final String cacheValuePrefix = "ComputedValueFor:" ;
35+ private LazyCache <String , String > cache ;
36+ private Function <String , String > mockLoader ;
37+
38+ @ Before
39+ public void setUp () {
40+ mockLoader = Mockito .mock (Function .class );
41+ Mockito .when (mockLoader .apply (Mockito .anyString ())).thenAnswer (invocation -> cacheValuePrefix + invocation .getArgument (0 ));
42+ cache = new LazyCache <>(4 , expireSeconds , mockLoader );
43+ }
44+
45+ @ Test
46+ public void testCacheMissAndLoader () {
47+ String key = "key1" ;
48+ String value = cache .get (key );
49+ assertEquals (cacheValuePrefix + key , value );
50+ Mockito .verify (mockLoader ).apply (key );
51+ }
52+
53+ @ Test
54+ public void testLoaderNotCalledIfPresent () {
55+ String key = "key2" ;
56+ cache .get (key );
57+ try {
58+ Thread .sleep ((long )(0.9 * expireSeconds * 1000 ));
59+ } catch (InterruptedException ie ) {
60+ Assert .fail (String .format ("Exception occurred: %s" , ie .getMessage ()));
61+ }
62+ cache .get (key );
63+ Mockito .verify (mockLoader , Mockito .times (1 )).apply (key );
64+ }
65+
66+ @ Test
67+ public void testCacheExpiration () {
68+ String key = "key3" ;
69+ cache .get (key );
70+ try {
71+ Thread .sleep ((long )(1.1 * expireSeconds * 1000 ));
72+ } catch (InterruptedException ie ) {
73+ Assert .fail (String .format ("Exception occurred: %s" , ie .getMessage ()));
74+ }
75+ cache .get (key );
76+ Mockito .verify (mockLoader , Mockito .times (2 )).apply (key );
77+ }
78+
79+ @ Test
80+ public void testInvalidateKey () {
81+ String key = "key4" ;
82+ cache .get (key );
83+ cache .invalidate (key );
84+ cache .get (key );
85+ Mockito .verify (mockLoader , Mockito .times (2 )).apply (key );
86+ }
87+
88+ @ Test
89+ public void testClearCache () {
90+ String key1 = "key5" ;
91+ String key2 = "key6" ;
92+ cache .get (key1 );
93+ cache .get (key2 );
94+ cache .clear ();
95+ cache .get (key1 );
96+ Mockito .verify (mockLoader , Mockito .times (2 )).apply (key1 );
97+ Mockito .verify (mockLoader , Mockito .times (1 )).apply (key2 );
98+ }
99+
100+ @ Test
101+ public void testMaximumSize () {
102+ String key = "key7" ;
103+ cache .get (key );
104+ for (int i = 0 ; i < 4 ; i ++) {
105+ cache .get (String .format ("newkey-%d" , i ));
106+ }
107+ try {
108+ Thread .sleep (100 );
109+ } catch (InterruptedException ie ) {
110+ Assert .fail (String .format ("Exception occurred: %s" , ie .getMessage ()));
111+ }
112+ cache .get (key );
113+ Mockito .verify (mockLoader , Mockito .times (2 )).apply (key );
114+ }
115+ }
0 commit comments