5
5
6
6
import java .util .Map ;
7
7
import java .util .Properties ;
8
- import java .util .concurrent .Future ;
9
8
9
+ import java .util .*;
10
+ import java .util .concurrent .Future ;
11
+ import java .util .concurrent .TimeUnit ;
12
+
13
+ import com .netflix .evcache .*;
14
+ import com .netflix .evcache .operation .EVCacheItem ;
15
+ import com .netflix .evcache .operation .EVCacheItemMetaData ;
16
+ import com .netflix .evcache .pool .EVCacheClient ;
17
+ import com .netflix .evcache .pool .ServerGroup ;
18
+ import com .netflix .evcache .util .KeyHasher ;
10
19
import org .slf4j .Logger ;
11
20
import org .slf4j .LoggerFactory ;
12
21
import org .testng .annotations .Test ;
13
22
14
- import com .netflix .evcache .EVCache ;
15
- import com .netflix .evcache .EVCacheGetOperationListener ;
16
23
import com .netflix .evcache .operation .EVCacheOperationFuture ;
17
-
18
24
import rx .schedulers .Schedulers ;
19
25
26
+
27
+ import static org .testng .Assert .*;
28
+
20
29
public class EVCacheTestDI extends DIBase implements EVCacheGetOperationListener <String > {
21
30
private static final Logger log = LoggerFactory .getLogger (EVCacheTestDI .class );
22
31
private int loops = 1 ;
32
+ private Map <String , String > propertiesToSet ;
33
+ private String appName = "EVCACHE_TEST" ;
23
34
24
35
public static void main (String args []) {
25
36
try {
@@ -31,31 +42,32 @@ public static void main(String args[]) {
31
42
}
32
43
33
44
public EVCacheTestDI () {
45
+ propertiesToSet = new HashMap <>();
46
+ propertiesToSet .putIfAbsent (appName + ".us-east-1d.EVCacheClientPool.writeOnly" , "false" );
47
+ propertiesToSet .putIfAbsent (appName + ".EVCacheClientPool.poolSize" , "1" );
48
+ propertiesToSet .putIfAbsent (appName + ".ping.servers" , "false" );
49
+ propertiesToSet .putIfAbsent (appName + ".cid.throw.exception" , "true" );
50
+ propertiesToSet .putIfAbsent (appName + ".EVCacheClientPool.readTimeout" , "500" );
51
+ propertiesToSet .putIfAbsent (appName + ".EVCacheClientPool.bulkReadTimeout" , "500" );
52
+ propertiesToSet .putIfAbsent (appName + ".max.read.queue.length" , "20" );
53
+ propertiesToSet .putIfAbsent ("EVCacheClientPoolManager.log.apps" , appName );
54
+ propertiesToSet .putIfAbsent (appName + ".fallback.zone" , "true" );
55
+ propertiesToSet .putIfAbsent (appName + ".enable.throttling" , "false" );
56
+ propertiesToSet .putIfAbsent (appName + ".throttle.time" , "0" );
57
+ propertiesToSet .putIfAbsent (appName + ".throttle.percent" , "0" );
58
+ propertiesToSet .putIfAbsent (appName + ".log.operation" , "1000" );
59
+ propertiesToSet .putIfAbsent (appName + ".EVCacheClientPool.validate.input.queue" , "true" );
34
60
}
35
61
36
62
protected Properties getProps () {
37
63
Properties props = super .getProps ();
38
- props .setProperty ("EVCACHE_CCS.us-east-1d.EVCacheClientPool.writeOnly" , "false" );
39
- props .setProperty ("EVCACHE_CCS.EVCacheClientPool.poolSize" , "1" );
40
- props .setProperty ("EVCACHE_CCS.ping.servers" , "false" );
41
- props .setProperty ("EVCACHE_CCS.cid.throw.exception" , "true" );
42
- props .setProperty ("EVCACHE_CCS.EVCacheClientPool.readTimeout" , "500" );
43
- props .setProperty ("EVCACHE_CCS.EVCacheClientPool.bulkReadTimeout" , "500" );
44
- props .setProperty ("EVCACHE_CCS.max.read.queue.length" , "20" );
45
- props .setProperty ("EVCacheClientPoolManager.log.apps" , "EVCACHE_CCS" );
46
- props .setProperty ("EVCACHE_CCS.fallback.zone" , "true" );
47
- props .setProperty ("EVCACHE_CCS.enable.throttling" , "false" );
48
- props .setProperty ("EVCACHE_CCS.throttle.time" , "0" );
49
- props .setProperty ("EVCACHE_CCS.throttle.percent" , "0" );
50
- props .setProperty ("EVCACHE_CCS.log.operation" , "1000" );
51
- props .setProperty ("EVCACHE_CCS.EVCacheClientPool.validate.input.queue" , "true" );
52
-
64
+ propertiesToSet .entrySet ().forEach (entry -> props .setProperty (entry .getKey (), entry .getValue ()));
53
65
return props ;
54
66
}
55
67
56
68
@ Test
57
69
public void testEVCache () {
58
- this .evCache = getNewBuilder ().setAppName ("EVCACHE_CCS" ).setCachePrefix ("cid" ).enableRetry ().build ();
70
+ this .evCache = getNewBuilder ().setAppName (appName ).setCachePrefix ("cid" ).enableRetry ().build ();
59
71
assertNotNull (evCache );
60
72
}
61
73
@@ -86,7 +98,7 @@ public void testKeySizeCheck() throws Exception {
86
98
}
87
99
assertTrue (exceptionThrown );
88
100
}
89
-
101
+
90
102
}
91
103
92
104
@ Test (dependsOnMethods = { "testKeySizeCheck" })
@@ -241,6 +253,179 @@ public void testAppendOrAdd() throws Exception {
241
253
}
242
254
}
243
255
256
+ private void refreshEVCache () {
257
+ setupEnv ();
258
+ testEVCache ();
259
+ }
260
+
261
+ @ Test (dependsOnMethods = {"testAppendOrAdd" })
262
+ public void functionalTestsWithAppLevelAndASGLevelHashingScenarios () throws Exception {
263
+ refreshEVCache ();
264
+
265
+ // no hashing
266
+ assertFalse (manager .getEVCacheConfig ().getPropertyRepository ().get (appName + ".hash.key" , Boolean .class ).orElse (false ).get ());
267
+ doFunctionalTests (false );
268
+
269
+ // hashing at app level
270
+ propertiesToSet .put (appName + ".hash.key" , "true" );
271
+ refreshEVCache ();
272
+ assertTrue (manager .getEVCacheConfig ().getPropertyRepository ().get (appName + ".hash.key" , Boolean .class ).orElse (false ).get ());
273
+ doFunctionalTests (true );
274
+ propertiesToSet .remove (appName + ".hash.key" );
275
+
276
+ // hashing at app level due to auto hashing as a consequence of a large key
277
+ propertiesToSet .put (appName + ".auto.hash.keys" , "true" );
278
+ refreshEVCache ();
279
+ assertTrue (manager .getEVCacheConfig ().getPropertyRepository ().get (appName + ".auto.hash.keys" , Boolean .class ).orElse (false ).get ());
280
+ assertFalse (manager .getEVCacheConfig ().getPropertyRepository ().get (appName + ".hash.key" , Boolean .class ).orElse (false ).get ());
281
+ testWithLargeKey ();
282
+ // negative scenario
283
+ propertiesToSet .remove (appName + ".auto.hash.keys" );
284
+ refreshEVCache ();
285
+ assertFalse (manager .getEVCacheConfig ().getPropertyRepository ().get (appName + ".auto.hash.keys" , Boolean .class ).orElse (false ).get ());
286
+ assertFalse (manager .getEVCacheConfig ().getPropertyRepository ().get (appName + ".hash.key" , Boolean .class ).orElse (false ).get ());
287
+ assertThrows (IllegalArgumentException .class , () -> {
288
+ testWithLargeKey ();
289
+ });
290
+
291
+ // hashing at app level by choice AND different hashing at each asg
292
+ Map <String , KeyHasher .HashingAlgorithm > hashingAlgorithmsByServerGroup = new HashMap <>();
293
+ propertiesToSet .put (appName + ".hash.key" , "true" );
294
+ refreshEVCache ();
295
+ assertTrue (manager .getEVCacheConfig ().getPropertyRepository ().get (appName + ".hash.key" , Boolean .class ).orElse (false ).get ());
296
+
297
+ // get server group names, to be used to configure the ASG level hashing properties
298
+ Map <ServerGroup , List <EVCacheClient >> clientsByServerGroup = manager .getEVCacheClientPool (appName ).getAllInstancesByServerGroup ();
299
+ int i = 0 ;
300
+ for (ServerGroup serverGroup : clientsByServerGroup .keySet ()) {
301
+ KeyHasher .HashingAlgorithm hashingAlgorithm = KeyHasher .HashingAlgorithm .values ()[i ++ % KeyHasher .HashingAlgorithm .values ().length ];
302
+ hashingAlgorithmsByServerGroup .put (serverGroup .getName (), hashingAlgorithm );
303
+ propertiesToSet .put (serverGroup .getName () + ".hash.key" , "true" );
304
+ propertiesToSet .put (serverGroup .getName () + ".hash.algo" , hashingAlgorithm .name ());
305
+ }
306
+ refreshEVCache ();
307
+ clientsByServerGroup = manager .getEVCacheClientPool (appName ).getAllInstancesByServerGroup ();
308
+ // validate hashing properties of asgs
309
+ for (ServerGroup serverGroup : clientsByServerGroup .keySet ()) {
310
+ assertEquals (clientsByServerGroup .get (serverGroup ).get (0 ).getHashingAlgorithm (), hashingAlgorithmsByServerGroup .get (serverGroup .getName ()));
311
+ }
312
+ doFunctionalTests (true );
313
+ for (ServerGroup serverGroup : clientsByServerGroup .keySet ()) {
314
+ propertiesToSet .remove (serverGroup .getName ());
315
+ }
316
+ }
317
+
318
+ private void testWithLargeKey () throws Exception {
319
+ StringBuilder sb = new StringBuilder ();
320
+ for (int i = 0 ; i < 100 ; i ++) {
321
+ sb .append (Long .toString (System .currentTimeMillis ()));
322
+ }
323
+ String key = sb .toString ();
324
+ String value = UUID .randomUUID ().toString ();
325
+
326
+ // set
327
+ EVCacheLatch latch = evCache .set (key , value , EVCacheLatch .Policy .ALL );
328
+ latch .await (1000 , TimeUnit .MILLISECONDS );
329
+
330
+ // get
331
+ assertEquals (evCache .get (key ), value );
332
+ }
333
+
334
+ private void doFunctionalTests (boolean isHashingEnabled ) throws Exception {
335
+ String key1 = Long .toString (System .currentTimeMillis ());
336
+ String value1 = UUID .randomUUID ().toString ();
337
+
338
+ // set
339
+ EVCacheLatch latch = evCache .set (key1 , value1 , EVCacheLatch .Policy .ALL );
340
+ latch .await (1000 , TimeUnit .MILLISECONDS );
341
+
342
+ // get
343
+ assertEquals (evCache .get (key1 ), value1 );
344
+
345
+ // replace
346
+ value1 = UUID .randomUUID ().toString ();
347
+ latch = evCache .replace (key1 , value1 , EVCacheLatch .Policy .ALL );
348
+ latch .await (1000 , TimeUnit .MILLISECONDS );
349
+ // get
350
+ assertEquals (evCache .get (key1 ), value1 );
351
+
352
+ // add a key
353
+ String key2 = Long .toString (System .currentTimeMillis ());
354
+ String value2 = UUID .randomUUID ().toString ();
355
+ latch = evCache .add (key2 , value2 , null , 1000 , EVCacheLatch .Policy .ALL );
356
+ latch .await (1000 , TimeUnit .MILLISECONDS );
357
+ // get
358
+ assertEquals (evCache .get (key2 ), value2 );
359
+
360
+ // appendoradd - append case
361
+ String value3 = UUID .randomUUID ().toString ();
362
+ if (isHashingEnabled ) {
363
+ assertThrows (EVCacheException .class , () -> {
364
+ evCache .appendOrAdd (key2 , value3 , null , 1000 , EVCacheLatch .Policy .ALL );
365
+ });
366
+ } else {
367
+ latch = evCache .appendOrAdd (key2 , value3 , null , 1000 , EVCacheLatch .Policy .ALL );
368
+ latch .await (3000 , TimeUnit .MILLISECONDS );
369
+ assertEquals (evCache .get (key2 ), value2 + value3 );
370
+ }
371
+
372
+ // appendoradd - add case
373
+ String key3 = Long .toString (System .currentTimeMillis ());
374
+ String value4 = UUID .randomUUID ().toString ();
375
+ if (isHashingEnabled ) {
376
+ assertThrows (EVCacheException .class , () -> {
377
+ evCache .appendOrAdd (key3 , value4 , null , 1000 , EVCacheLatch .Policy .ALL );
378
+ });
379
+ } else {
380
+ latch = evCache .appendOrAdd (key3 , value4 , null , 1000 , EVCacheLatch .Policy .ALL );
381
+ latch .await (3000 , TimeUnit .MILLISECONDS );
382
+ // get
383
+ assertEquals (evCache .get (key3 ), value4 );
384
+ }
385
+
386
+ // append
387
+ String value5 = UUID .randomUUID ().toString ();
388
+ if (isHashingEnabled ) {
389
+ assertThrows (EVCacheException .class , () -> {
390
+ evCache .append (key3 , value5 , 1000 );
391
+ });
392
+ } else {
393
+ Future <Boolean > futures [] = evCache .append (key3 , value5 , 1000 );
394
+ for (Future future : futures ) {
395
+ assertTrue ((Boolean ) future .get ());
396
+ }
397
+ // get
398
+ assertEquals (evCache .get (key3 ), value4 + value5 );
399
+ }
400
+
401
+ String key4 = Long .toString (System .currentTimeMillis ());
402
+ assertEquals (evCache .incr (key4 , 1 , 10 , 1000 ), 10 );
403
+ assertEquals (evCache .incr (key4 , 10 , 10 , 1000 ), 20 );
404
+
405
+ // decr
406
+ String key5 = Long .toString (System .currentTimeMillis ());
407
+ assertEquals (evCache .decr (key5 , 1 , 10 , 1000 ), 10 );
408
+ assertEquals (evCache .decr (key5 , 20 , 10 , 1000 ), 0 );
409
+
410
+ // delete
411
+ latch = evCache .delete (key1 , EVCacheLatch .Policy .ALL );
412
+ latch .await (1000 , TimeUnit .MILLISECONDS );
413
+ latch = evCache .delete (key2 , EVCacheLatch .Policy .ALL );
414
+ latch .await (1000 , TimeUnit .MILLISECONDS );
415
+ latch = evCache .delete (key3 , EVCacheLatch .Policy .ALL );
416
+ latch .await (1000 , TimeUnit .MILLISECONDS );
417
+ latch = evCache .delete (key4 , EVCacheLatch .Policy .ALL );
418
+ latch .await (1000 , TimeUnit .MILLISECONDS );
419
+ latch = evCache .delete (key5 , EVCacheLatch .Policy .ALL );
420
+ latch .await (1000 , TimeUnit .MILLISECONDS );
421
+
422
+ assertNull (evCache .get (key1 ));
423
+ assertNull (evCache .get (key2 ));
424
+ assertNull (evCache .get (key3 ));
425
+ assertNull (evCache .get (key4 ));
426
+ assertNull (evCache .get (key5 ));
427
+ }
428
+
244
429
public void testAll () {
245
430
try {
246
431
setupEnv ();
0 commit comments