/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.monitor.impl; import com.eclipsesource.json.JsonObject; import com.hazelcast.test.HazelcastParallelClassRunner; import com.hazelcast.test.HazelcastTestSupport; import com.hazelcast.test.annotation.ParallelTest; import com.hazelcast.test.annotation.QuickTest; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import java.io.FileNotFoundException; import java.util.concurrent.CountDownLatch; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @RunWith(HazelcastParallelClassRunner.class) @Category({QuickTest.class, ParallelTest.class}) public class NearCacheStatsImplTest extends HazelcastTestSupport { private NearCacheStatsImpl nearCacheStats; @Before public void setUp() { nearCacheStats = new NearCacheStatsImpl(); nearCacheStats.setOwnedEntryCount(501); nearCacheStats.incrementOwnedEntryCount(); nearCacheStats.decrementOwnedEntryCount(); nearCacheStats.decrementOwnedEntryCount(); nearCacheStats.setOwnedEntryMemoryCost(1024); nearCacheStats.incrementOwnedEntryMemoryCost(512); nearCacheStats.decrementOwnedEntryMemoryCost(256); nearCacheStats.setHits(600); nearCacheStats.incrementHits(); nearCacheStats.incrementHits(); nearCacheStats.setMisses(304); nearCacheStats.incrementMisses(); nearCacheStats.incrementEvictions(); nearCacheStats.incrementEvictions(); nearCacheStats.incrementEvictions(); nearCacheStats.incrementEvictions(); nearCacheStats.incrementExpirations(); nearCacheStats.incrementExpirations(); nearCacheStats.incrementExpirations(); nearCacheStats.addPersistence(200, 300, 400); } @Test public void testDefaultConstructor() { assertNearCacheStats(nearCacheStats, 1, 200, 300, 400, false); } @Test public void testCopyConstructor() { NearCacheStatsImpl copy = new NearCacheStatsImpl(nearCacheStats); assertNearCacheStats(copy, 1, 200, 300, 400, false); } @Test public void testSerialization() { NearCacheStatsImpl deserialized = serializeAndDeserializeNearCacheStats(nearCacheStats); assertNearCacheStats(deserialized, 1, 200, 300, 400, false); } @Test public void testSerialization_withPersistenceFailure() { Throwable throwable = new FileNotFoundException("expected exception"); nearCacheStats.addPersistenceFailure(throwable); NearCacheStatsImpl deserialized = serializeAndDeserializeNearCacheStats(nearCacheStats); assertNearCacheStats(deserialized, 2, 0, 0, 0, true); String lastPersistenceFailure = deserialized.getLastPersistenceFailure(); assertContains(lastPersistenceFailure, throwable.getClass().getSimpleName()); assertContains(lastPersistenceFailure, "expected exception"); } @Test public void testGetRatio_NaN() { NearCacheStatsImpl nearCacheStats = new NearCacheStatsImpl(); assertEquals(Double.NaN, nearCacheStats.getRatio(), 0.0001); } @Test public void testGetRatio_POSITIVE_INFINITY() { NearCacheStatsImpl nearCacheStats = new NearCacheStatsImpl(); nearCacheStats.setHits(1); assertEquals(Double.POSITIVE_INFINITY, nearCacheStats.getRatio(), 0.0001); } @Test public void testGetRatio_100() { NearCacheStatsImpl nearCacheStats = new NearCacheStatsImpl(); nearCacheStats.setHits(1); nearCacheStats.setMisses(1); assertEquals(100d, nearCacheStats.getRatio(), 0.0001); } @Test public void testConcurrentModification() { int incThreads = 40; int decThreads = 10; int countPerThread = 500; CountDownLatch startLatch = new CountDownLatch(1); NearCacheStatsImpl nearCacheStats = new NearCacheStatsImpl(); Thread[] threads = new Thread[incThreads + decThreads]; for (int i = 0; i < incThreads; i++) { threads[i] = new StatsModifierThread(startLatch, nearCacheStats, true, countPerThread); threads[i].start(); } for (int i = incThreads; i < incThreads + decThreads; i++) { threads[i] = new StatsModifierThread(startLatch, nearCacheStats, false, countPerThread); threads[i].start(); } startLatch.countDown(); assertJoinable(threads); System.out.println(nearCacheStats); int incCount = incThreads * countPerThread; int decCount = decThreads * countPerThread; int totalCount = incCount - decCount; assertEquals(totalCount, nearCacheStats.getOwnedEntryCount()); assertEquals(totalCount * 23, nearCacheStats.getOwnedEntryMemoryCost()); assertEquals(incCount, nearCacheStats.getHits()); assertEquals(decCount, nearCacheStats.getMisses()); assertEquals(incCount, nearCacheStats.getEvictions()); assertEquals(incCount, nearCacheStats.getExpirations()); } private static NearCacheStatsImpl serializeAndDeserializeNearCacheStats(NearCacheStatsImpl original) { JsonObject serialized = original.toJson(); NearCacheStatsImpl deserialized = new NearCacheStatsImpl(); deserialized.fromJson(serialized); return deserialized; } private static void assertNearCacheStats(NearCacheStatsImpl stats, long expectedPersistenceCount, long expectedDuration, long expectedWrittenBytes, long expectedKeyCount, boolean expectedFailure) { assertTrue(stats.getCreationTime() > 0); assertEquals(500, stats.getOwnedEntryCount()); assertEquals(1280, stats.getOwnedEntryMemoryCost()); assertEquals(602, stats.getHits()); assertEquals(305, stats.getMisses()); assertEquals(4, stats.getEvictions()); assertEquals(3, stats.getExpirations()); assertEquals(expectedPersistenceCount, stats.getPersistenceCount()); assertTrue(stats.getLastPersistenceTime() > 0); assertEquals(expectedDuration, stats.getLastPersistenceDuration()); assertEquals(expectedWrittenBytes, stats.getLastPersistenceWrittenBytes()); assertEquals(expectedKeyCount, stats.getLastPersistenceKeyCount()); if (expectedFailure) { assertFalse(stats.getLastPersistenceFailure().isEmpty()); } else { assertTrue(stats.getLastPersistenceFailure().isEmpty()); } assertNotNull(stats.toString()); } private static class StatsModifierThread extends Thread { private final CountDownLatch startLatch; private final NearCacheStatsImpl nearCacheStats; private final boolean increment; private final int count; private StatsModifierThread(CountDownLatch startLatch, NearCacheStatsImpl nearCacheStats, boolean increment, int count) { this.startLatch = startLatch; this.nearCacheStats = nearCacheStats; this.increment = increment; this.count = count; } @Override public void run() { assertOpenEventually(startLatch); for (int i = 0; i < count; i++) { if (increment) { nearCacheStats.incrementOwnedEntryCount(); nearCacheStats.incrementOwnedEntryMemoryCost(23); nearCacheStats.incrementHits(); nearCacheStats.incrementEvictions(); nearCacheStats.incrementExpirations(); } else { nearCacheStats.decrementOwnedEntryCount(); nearCacheStats.decrementOwnedEntryMemoryCost(23); nearCacheStats.incrementMisses(); } } } } }