/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.internal.offheap; import org.apache.geode.OutOfOffHeapMemoryException; import org.apache.geode.StatisticsFactory; import org.apache.geode.distributed.DistributedSystem; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.distributed.internal.DistributionStats; import org.apache.geode.distributed.internal.InternalDistributedSystem; import org.apache.geode.distributed.internal.InternalLocator; import org.apache.geode.internal.statistics.LocalStatisticsFactory; import org.apache.geode.test.junit.categories.UnitTest; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.RestoreSystemProperties; import org.junit.experimental.categories.Category; import static org.junit.Assert.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @Category(UnitTest.class) public class OffHeapStorageJUnitTest { private final static long MEGABYTE = 1024 * 1024; private final static long GIGABYTE = 1024 * 1024 * 1024; @Rule public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(); @Test public void testParseOffHeapMemorySizeNegative() { assertEquals(0, OffHeapStorage.parseOffHeapMemorySize("-1")); } @Test public void testParseOffHeapMemorySizeNull() { assertEquals(0, OffHeapStorage.parseOffHeapMemorySize(null)); } @Test public void testParseOffHeapMemorySizeEmpty() { assertEquals(0, OffHeapStorage.parseOffHeapMemorySize("")); } @Test public void testParseOffHeapMemorySizeBytes() { assertEquals(MEGABYTE, OffHeapStorage.parseOffHeapMemorySize("1")); assertEquals(Integer.MAX_VALUE * MEGABYTE, OffHeapStorage.parseOffHeapMemorySize("" + Integer.MAX_VALUE)); } @Test public void testParseOffHeapMemorySizeKiloBytes() { try { OffHeapStorage.parseOffHeapMemorySize("1k"); fail("Did not receive expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { // Expected } } @Test public void testParseOffHeapMemorySizeMegaBytes() { assertEquals(MEGABYTE, OffHeapStorage.parseOffHeapMemorySize("1m")); assertEquals(Integer.MAX_VALUE * MEGABYTE, OffHeapStorage.parseOffHeapMemorySize("" + Integer.MAX_VALUE + "m")); } @Test public void testParseOffHeapMemorySizeGigaBytes() { assertEquals(GIGABYTE, OffHeapStorage.parseOffHeapMemorySize("1g")); assertEquals(Integer.MAX_VALUE * GIGABYTE, OffHeapStorage.parseOffHeapMemorySize("" + Integer.MAX_VALUE + "g")); } @Test public void testCalcMaxSlabSize() { assertEquals(100, OffHeapStorage.calcMaxSlabSize(100L)); assertEquals(Integer.MAX_VALUE, OffHeapStorage.calcMaxSlabSize(Long.MAX_VALUE)); try { System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE", "99"); assertEquals(99 * 1024 * 1024, OffHeapStorage.calcMaxSlabSize(100L * 1024 * 1024)); assertEquals(88, OffHeapStorage.calcMaxSlabSize(88)); System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE", "88m"); assertEquals(88 * 1024 * 1024, OffHeapStorage.calcMaxSlabSize(100L * 1024 * 1024)); System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE", "77M"); assertEquals(77 * 1024 * 1024, OffHeapStorage.calcMaxSlabSize(100L * 1024 * 1024)); System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE", "1g"); assertEquals(1 * 1024 * 1024 * 1024, OffHeapStorage.calcMaxSlabSize(2L * 1024 * 1024 * 1024)); System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE", "1G"); assertEquals(1L * 1024 * 1024 * 1024, OffHeapStorage.calcMaxSlabSize(2L * 1024 * 1024 * 1024 + 1)); System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE", "foobarG"); try { OffHeapStorage.calcMaxSlabSize(100); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { } System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE", ""); assertEquals(100, OffHeapStorage.calcMaxSlabSize(100L)); assertEquals(Integer.MAX_VALUE, OffHeapStorage.calcMaxSlabSize(Long.MAX_VALUE)); } finally { System.clearProperty(DistributionConfig.GEMFIRE_PREFIX + "OFF_HEAP_SLAB_SIZE"); } } @Test public void createOffHeapStorageReturnsNullIfForceLocator() { System.setProperty(InternalLocator.FORCE_LOCATOR_DM_TYPE, "true"); assertEquals(null, OffHeapStorage.createOffHeapStorage(null, 1, null)); } @Test public void createOffHeapStorageReturnsNullIfMemorySizeIsZero() { assertEquals(null, OffHeapStorage.createOffHeapStorage(null, 0, null)); } @Test public void exceptionIfSlabCountTooSmall() { StatisticsFactory statsFactory = mock(StatisticsFactory.class); try { OffHeapStorage.createOffHeapStorage(statsFactory, OffHeapStorage.MIN_SLAB_SIZE - 1, null); } catch (IllegalArgumentException expected) { expected.getMessage() .equals("The amount of off heap memory must be at least " + OffHeapStorage.MIN_SLAB_SIZE + " but it was set to " + (OffHeapStorage.MIN_SLAB_SIZE - 1)); } } @Test public void exceptionIfDistributedSystemNull() { StatisticsFactory statsFactory = mock(StatisticsFactory.class); try { OffHeapStorage.createOffHeapStorage(statsFactory, OffHeapStorage.MIN_SLAB_SIZE, (DistributedSystem) null); } catch (IllegalArgumentException expected) { expected.getMessage().equals("InternalDistributedSystem is null"); } } @Test public void createOffHeapStorageWorks() { StatisticsFactory localStatsFactory = new LocalStatisticsFactory(null); InternalDistributedSystem ids = mock(InternalDistributedSystem.class); MemoryAllocator ma = OffHeapStorage.createOffHeapStorage(localStatsFactory, OffHeapStorage.MIN_SLAB_SIZE, ids); System.setProperty(MemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY, "true"); ma.close(); } @Test public void testCreateOffHeapStorage() { StatisticsFactory localStatsFactory = new LocalStatisticsFactory(null); OutOfOffHeapMemoryListener ooohml = mock(OutOfOffHeapMemoryListener.class); MemoryAllocator ma = OffHeapStorage.basicCreateOffHeapStorage(localStatsFactory, 1024 * 1024, ooohml); try { OffHeapMemoryStats stats = ma.getStats(); assertNotNull(stats.getStats()); assertEquals(1024 * 1024, stats.getFreeMemory()); assertEquals(1024 * 1024, stats.getMaxMemory()); assertEquals(0, stats.getUsedMemory()); assertEquals(0, stats.getDefragmentations()); assertEquals(0, stats.getDefragmentationsInProgress()); assertEquals(0, stats.getDefragmentationTime()); assertEquals(0, stats.getFragmentation()); assertEquals(1, stats.getFragments()); assertEquals(1024 * 1024, stats.getLargestFragment()); assertEquals(0, stats.getObjects()); assertEquals(0, stats.getReads()); stats.incFreeMemory(100); assertEquals(1024 * 1024 + 100, stats.getFreeMemory()); stats.incFreeMemory(-100); assertEquals(1024 * 1024, stats.getFreeMemory()); stats.incMaxMemory(100); assertEquals(1024 * 1024 + 100, stats.getMaxMemory()); stats.incMaxMemory(-100); assertEquals(1024 * 1024, stats.getMaxMemory()); stats.incUsedMemory(100); assertEquals(100, stats.getUsedMemory()); stats.incUsedMemory(-100); assertEquals(0, stats.getUsedMemory()); stats.incObjects(100); assertEquals(100, stats.getObjects()); stats.incObjects(-100); assertEquals(0, stats.getObjects()); stats.incReads(); assertEquals(1, stats.getReads()); stats.setFragmentation(100); assertEquals(100, stats.getFragmentation()); stats.setFragmentation(0); assertEquals(0, stats.getFragmentation()); stats.setFragments(2); assertEquals(2, stats.getFragments()); stats.setFragments(1); assertEquals(1, stats.getFragments()); stats.setLargestFragment(100); assertEquals(100, stats.getLargestFragment()); stats.setLargestFragment(1024 * 1024); assertEquals(1024 * 1024, stats.getLargestFragment()); boolean originalEnableClockStats = DistributionStats.enableClockStats; DistributionStats.enableClockStats = true; try { long start = stats.startDefragmentation(); assertEquals(1, stats.getDefragmentationsInProgress()); while (DistributionStats.getStatTime() == start) { Thread.yield(); } stats.endDefragmentation(start); assertEquals(1, stats.getDefragmentations()); assertEquals(0, stats.getDefragmentationsInProgress()); assertTrue(stats.getDefragmentationTime() > 0); } finally { DistributionStats.enableClockStats = originalEnableClockStats; } stats.incObjects(100); stats.incUsedMemory(100); stats.setFragmentation(100); OffHeapStorage ohs = (OffHeapStorage) stats; ohs.initialize(new NullOffHeapMemoryStats()); assertEquals(0, stats.getFreeMemory()); assertEquals(0, stats.getMaxMemory()); assertEquals(0, stats.getUsedMemory()); assertEquals(0, stats.getDefragmentations()); assertEquals(0, stats.getDefragmentationsInProgress()); assertEquals(0, stats.getDefragmentationTime()); assertEquals(0, stats.getFragmentation()); assertEquals(0, stats.getFragments()); assertEquals(0, stats.getLargestFragment()); assertEquals(0, stats.getObjects()); assertEquals(0, stats.getReads()); OutOfOffHeapMemoryException ex = null; try { ma.allocate(1024 * 1024 + 1); fail("expected OutOfOffHeapMemoryException"); } catch (OutOfOffHeapMemoryException expected) { ex = expected; } verify(ooohml).outOfOffHeapMemory(ex); try { ma.allocate(1024 * 1024 + 1); fail("expected OutOfOffHeapMemoryException"); } catch (OutOfOffHeapMemoryException expected) { ex = expected; } verify(ooohml).outOfOffHeapMemory(ex); } finally { System.setProperty(MemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY, "true"); try { ma.close(); } finally { System.clearProperty(MemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY); } } } @Test public void testCalcSlabCount() { final long MSS = OffHeapStorage.MIN_SLAB_SIZE; assertEquals(100, OffHeapStorage.calcSlabCount(MSS * 4, MSS * 4 * 100)); assertEquals(100, OffHeapStorage.calcSlabCount(MSS * 4, (MSS * 4 * 100) + (MSS - 1))); assertEquals(101, OffHeapStorage.calcSlabCount(MSS * 4, (MSS * 4 * 100) + MSS)); assertEquals(Integer.MAX_VALUE, OffHeapStorage.calcSlabCount(MSS, MSS * Integer.MAX_VALUE)); assertEquals(Integer.MAX_VALUE, OffHeapStorage.calcSlabCount(MSS, (MSS * Integer.MAX_VALUE) + MSS - 1)); try { OffHeapStorage.calcSlabCount(MSS, (((long) MSS) * Integer.MAX_VALUE) + MSS); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { } } }