/*
 * 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 static org.apache.geode.internal.offheap.MemoryAllocatorImpl.DummyNonRealTimeStatsUpdater;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;

import org.apache.geode.OutOfOffHeapMemoryException;
import org.apache.geode.cache.CacheClosedException;

public class MemoryAllocatorJUnitTest {

  private long expectedMemoryUsage;
  private boolean memoryUsageEventReceived;

  @Rule
  public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();

  private static int round(int multiple, int v) {
    return ((v + multiple - 1) / multiple) * multiple;
  }

  @Test
  public void testNullGetAllocator() {
    try {
      MemoryAllocatorImpl.getAllocator();
      fail("expected CacheClosedException");
    } catch (CacheClosedException expected) {
    }
  }

  @Test
  public void testConstructor() {
    try {
      MemoryAllocatorImpl.createForUnitTest(null, null, null);
      fail("expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  @Test
  public void testCreate() {
    System.setProperty(MemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY, "false");
    {
      NullOutOfOffHeapMemoryListener listener = new NullOutOfOffHeapMemoryListener();
      NullOffHeapMemoryStats stats = new NullOffHeapMemoryStats();
      try {
        MemoryAllocatorImpl.create(listener, stats, 10, 950, 100, null, size -> {
          throw new OutOfMemoryError("expected");
        }, null, () -> new DummyNonRealTimeStatsUpdater());
      } catch (OutOfMemoryError expected) {
      }
      assertTrue(listener.isClosed());
      assertTrue(stats.isClosed());
    }
    {
      NullOutOfOffHeapMemoryListener listener = new NullOutOfOffHeapMemoryListener();
      NullOffHeapMemoryStats stats = new NullOffHeapMemoryStats();
      int MAX_SLAB_SIZE = 100;
      try {
        SlabFactory factory = new SlabFactory() {
          private int createCount = 0;

          @Override
          public Slab create(int size) {
            createCount++;
            if (createCount == 1) {
              return new SlabImpl(size);
            } else {
              throw new OutOfMemoryError("expected");
            }
          }
        };
        MemoryAllocatorImpl.create(listener, stats, 10, 950, MAX_SLAB_SIZE, null, factory, null,
            () -> new MemoryAllocatorImpl.DummyNonRealTimeStatsUpdater());
      } catch (OutOfMemoryError expected) {
      }
      assertTrue(listener.isClosed());
      assertTrue(stats.isClosed());
    }
    {
      NullOutOfOffHeapMemoryListener listener = new NullOutOfOffHeapMemoryListener();
      NullOffHeapMemoryStats stats = new NullOffHeapMemoryStats();
      SlabFactory factory = SlabImpl::new;
      MemoryAllocator ma =
          MemoryAllocatorImpl.create(listener, stats, 10, 950, 100, null, factory, null,
              () -> new DummyNonRealTimeStatsUpdater());
      try {
        assertFalse(listener.isClosed());
        assertFalse(stats.isClosed());
        ma.close();
        assertTrue(listener.isClosed());
        assertFalse(stats.isClosed());
        listener = new NullOutOfOffHeapMemoryListener();
        NullOffHeapMemoryStats stats2 = new NullOffHeapMemoryStats();
        {
          SlabImpl slab = new SlabImpl(1024);
          try {
            MemoryAllocatorImpl.createForUnitTest(listener, stats2, new SlabImpl[] {slab});
          } catch (IllegalStateException expected) {
            assertTrue("unexpected message: " + expected.getMessage(), expected.getMessage().equals(
                "attempted to reuse existing off-heap memory even though new off-heap memory was allocated"));
          } finally {
            slab.free();
          }
          assertFalse(stats.isClosed());
          assertTrue(listener.isClosed());
          assertTrue(stats2.isClosed());
        }
        listener = new NullOutOfOffHeapMemoryListener();
        stats2 = new NullOffHeapMemoryStats();
        MemoryAllocator ma2 =
            MemoryAllocatorImpl.create(listener, stats2, 10, 950, 100, null, factory, null,
                () -> new DummyNonRealTimeStatsUpdater());
        assertSame(ma, ma2);
        assertTrue(stats.isClosed());
        assertFalse(listener.isClosed());
        assertFalse(stats2.isClosed());
        stats = stats2;
        ma.close();
        assertTrue(listener.isClosed());
        assertFalse(stats.isClosed());
      } finally {
        MemoryAllocatorImpl.freeOffHeapMemory();
      }
      assertTrue(stats.isClosed());
    }
  }

  @Test
  public void testBasics() {
    int BATCH_SIZE = 1;
    int TINY_MULTIPLE = FreeListManager.TINY_MULTIPLE;
    int HUGE_MULTIPLE = FreeListManager.HUGE_MULTIPLE;
    int perObjectOverhead = OffHeapStoredObject.HEADER_SIZE;
    int maxTiny = FreeListManager.MAX_TINY - perObjectOverhead;
    int minHuge = maxTiny + 1;
    int TOTAL_MEM = (maxTiny + perObjectOverhead) * BATCH_SIZE
        /* + (maxBig+perObjectOverhead)*BATCH_SIZE */ + round(TINY_MULTIPLE,
            minHuge + 1 + perObjectOverhead) * BATCH_SIZE
        + (TINY_MULTIPLE + perObjectOverhead)
            * BATCH_SIZE /* + (MIN_BIG_SIZE+perObjectOverhead)*BATCH_SIZE */
        + round(TINY_MULTIPLE, minHuge + perObjectOverhead + 1);
    SlabImpl slab = new SlabImpl(TOTAL_MEM);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      assertEquals(TOTAL_MEM, ma.getFreeMemory());
      assertEquals(TOTAL_MEM, ma.freeList.getFreeFragmentMemory());
      assertEquals(0, ma.freeList.getFreeTinyMemory());
      assertEquals(0, ma.freeList.getFreeHugeMemory());
      StoredObject tinymc = ma.allocate(maxTiny);
      assertEquals(TOTAL_MEM - round(TINY_MULTIPLE, maxTiny + perObjectOverhead),
          ma.getFreeMemory());
      assertEquals(round(TINY_MULTIPLE, maxTiny + perObjectOverhead) * (BATCH_SIZE - 1),
          ma.freeList.getFreeTinyMemory());
      StoredObject hugemc = ma.allocate(minHuge);
      assertEquals(TOTAL_MEM
          - round(TINY_MULTIPLE,
              minHuge + perObjectOverhead)/*-round(BIG_MULTIPLE, maxBig+perObjectOverhead)*/
          - round(TINY_MULTIPLE, maxTiny + perObjectOverhead), ma.getFreeMemory());
      long freeSlab = ma.freeList.getFreeFragmentMemory();
      long oldFreeHugeMemory = ma.freeList.getFreeHugeMemory();
      assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead) * (BATCH_SIZE - 1),
          oldFreeHugeMemory);
      hugemc.release();
      assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead),
          ma.freeList.getFreeHugeMemory() - oldFreeHugeMemory);
      assertEquals(TOTAL_MEM/*-round(BIG_MULTIPLE, maxBig+perObjectOverhead)*/ - round(
          TINY_MULTIPLE, maxTiny + perObjectOverhead), ma.getFreeMemory());
      assertEquals(TOTAL_MEM - round(TINY_MULTIPLE, maxTiny + perObjectOverhead),
          ma.getFreeMemory());
      long oldFreeTinyMemory = ma.freeList.getFreeTinyMemory();
      tinymc.release();
      assertEquals(round(TINY_MULTIPLE, maxTiny + perObjectOverhead),
          ma.freeList.getFreeTinyMemory() - oldFreeTinyMemory);
      assertEquals(TOTAL_MEM, ma.getFreeMemory());
      // now lets reallocate from the free lists
      tinymc = ma.allocate(maxTiny);
      assertEquals(oldFreeTinyMemory, ma.freeList.getFreeTinyMemory());
      assertEquals(TOTAL_MEM - round(TINY_MULTIPLE, maxTiny + perObjectOverhead),
          ma.getFreeMemory());
      hugemc = ma.allocate(minHuge);
      assertEquals(oldFreeHugeMemory, ma.freeList.getFreeHugeMemory());
      assertEquals(TOTAL_MEM
          - round(TINY_MULTIPLE,
              minHuge + perObjectOverhead)/*-round(BIG_MULTIPLE, maxBig+perObjectOverhead)*/
          - round(TINY_MULTIPLE, maxTiny + perObjectOverhead), ma.getFreeMemory());
      hugemc.release();
      assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead),
          ma.freeList.getFreeHugeMemory() - oldFreeHugeMemory);
      assertEquals(TOTAL_MEM/*-round(BIG_MULTIPLE, maxBig+perObjectOverhead)*/ - round(
          TINY_MULTIPLE, maxTiny + perObjectOverhead), ma.getFreeMemory());
      assertEquals(TOTAL_MEM - round(TINY_MULTIPLE, maxTiny + perObjectOverhead),
          ma.getFreeMemory());
      tinymc.release();
      assertEquals(round(TINY_MULTIPLE, maxTiny + perObjectOverhead),
          ma.freeList.getFreeTinyMemory() - oldFreeTinyMemory);
      assertEquals(TOTAL_MEM, ma.getFreeMemory());
      // None of the reallocates should have come from the slab.
      assertEquals(freeSlab, ma.freeList.getFreeFragmentMemory());
      tinymc = ma.allocate(1);
      assertEquals(round(TINY_MULTIPLE, 1 + perObjectOverhead), tinymc.getSize());
      assertEquals(freeSlab - (round(TINY_MULTIPLE, 1 + perObjectOverhead) * BATCH_SIZE),
          ma.freeList.getFreeFragmentMemory());
      freeSlab = ma.freeList.getFreeFragmentMemory();
      tinymc.release();
      assertEquals(
          round(TINY_MULTIPLE, maxTiny + perObjectOverhead)
              + (round(TINY_MULTIPLE, 1 + perObjectOverhead) * BATCH_SIZE),
          ma.freeList.getFreeTinyMemory() - oldFreeTinyMemory);

      hugemc = ma.allocate(minHuge + 1);
      assertEquals(round(TINY_MULTIPLE, minHuge + 1 + perObjectOverhead), hugemc.getSize());
      assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead) * (BATCH_SIZE - 1),
          ma.freeList.getFreeHugeMemory());
      hugemc.release();
      assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead) * BATCH_SIZE,
          ma.freeList.getFreeHugeMemory());
      hugemc = ma.allocate(minHuge);
      assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead) * (BATCH_SIZE - 1),
          ma.freeList.getFreeHugeMemory());
      if (BATCH_SIZE > 1) {
        StoredObject hugemc2 = ma.allocate(minHuge);
        assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead) * (BATCH_SIZE - 2),
            ma.freeList.getFreeHugeMemory());
        hugemc2.release();
        assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead) * (BATCH_SIZE - 1),
            ma.freeList.getFreeHugeMemory());
      }
      hugemc.release();
      assertEquals(round(TINY_MULTIPLE, minHuge + perObjectOverhead) * BATCH_SIZE,
          ma.freeList.getFreeHugeMemory());
      // now that we do defragmentation the following allocate works.
      hugemc = ma.allocate(minHuge + HUGE_MULTIPLE + HUGE_MULTIPLE - 1);
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  @Test
  public void testChunkCreateDirectByteBuffer() {
    SlabImpl slab = new SlabImpl(1024 * 1024);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      ByteBuffer bb = ByteBuffer.allocate(1024);
      for (int i = 0; i < 1024; i++) {
        bb.put((byte) i);
      }
      bb.position(0);
      OffHeapStoredObject c =
          (OffHeapStoredObject) ma.allocateAndInitialize(bb.array(), false, false);
      assertEquals(1024, c.getDataSize());
      if (!Arrays.equals(bb.array(), c.getRawBytes())) {
        fail("arrays are not equal. Expected " + Arrays.toString(bb.array()) + " but found: "
            + Arrays.toString(c.getRawBytes()));
      }
      ByteBuffer dbb = c.createDirectByteBuffer();
      assertEquals(true, dbb.isDirect());
      assertEquals(bb, dbb);
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  @Test
  public void testDebugLog() {
    MemoryAllocatorImpl.debugLog("test debug log", false);
    MemoryAllocatorImpl.debugLog("test debug log", true);
  }

  @Test
  public void testGetLostChunks() {
    SlabImpl slab = new SlabImpl(1024 * 1024);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      assertEquals(Collections.emptyList(), ma.getLostChunks(null));
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  @Test
  public void testFindSlab() {
    final int SLAB_SIZE = 1024 * 1024;
    SlabImpl slab = new SlabImpl(SLAB_SIZE);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      assertEquals(0, ma.findSlab(slab.getMemoryAddress()));
      assertEquals(0, ma.findSlab(slab.getMemoryAddress() + SLAB_SIZE - 1));
      try {
        ma.findSlab(slab.getMemoryAddress() - 1);
        fail("expected IllegalStateException");
      } catch (IllegalStateException expected) {
      }
      try {
        ma.findSlab(slab.getMemoryAddress() + SLAB_SIZE);
        fail("expected IllegalStateException");
      } catch (IllegalStateException expected) {
      }
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  @Test
  public void testValidateAddressAndSize() {
    final int SLAB_SIZE = 1024 * 1024;
    SlabImpl slab = new SlabImpl(SLAB_SIZE);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      try {
        MemoryAllocatorImpl.validateAddress(0L);
        fail("expected IllegalStateException");
      } catch (IllegalStateException expected) {
        assertEquals("Unexpected exception message: " + expected.getMessage(), true,
            expected.getMessage().contains("addr was smaller than expected"));
      }
      try {
        MemoryAllocatorImpl.validateAddress(1L);
        fail("expected IllegalStateException");
      } catch (IllegalStateException expected) {
        assertEquals("Unexpected exception message: " + expected.getMessage(), true, expected
            .getMessage().contains("Valid addresses must be in one of the following ranges:"));
      }
      MemoryAllocatorImpl.validateAddressAndSizeWithinSlab(slab.getMemoryAddress(), SLAB_SIZE,
          false);
      MemoryAllocatorImpl.validateAddressAndSizeWithinSlab(slab.getMemoryAddress(), SLAB_SIZE,
          true);
      MemoryAllocatorImpl.validateAddressAndSizeWithinSlab(slab.getMemoryAddress(), -1, true);
      try {
        MemoryAllocatorImpl.validateAddressAndSizeWithinSlab(slab.getMemoryAddress() - 1, SLAB_SIZE,
            true);
        fail("expected IllegalStateException");
      } catch (IllegalStateException expected) {
        assertEquals("Unexpected exception message: " + expected.getMessage(), true,
            expected.getMessage()
                .equals(" address 0x" + Long.toString(slab.getMemoryAddress() - 1, 16)
                    + " does not address the original slab memory"));
      }
      try {
        MemoryAllocatorImpl.validateAddressAndSizeWithinSlab(slab.getMemoryAddress(), SLAB_SIZE + 1,
            true);
        fail("expected IllegalStateException");
      } catch (IllegalStateException expected) {
        assertEquals("Unexpected exception message: " + expected.getMessage(), true,
            expected.getMessage()
                .equals(" address 0x" + Long.toString(slab.getMemoryAddress() + SLAB_SIZE, 16)
                    + " does not address the original slab memory"));
      }
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  @Test
  public void testMemoryInspection() {
    final int SLAB_SIZE = 1024 * 1024;
    SlabImpl slab = new SlabImpl(SLAB_SIZE);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      MemoryInspector inspector = ma.getMemoryInspector();
      assertNotNull(inspector);
      assertEquals(null, inspector.getFirstBlock());
      assertEquals(Collections.emptyList(), inspector.getSnapshot());
      assertEquals(Collections.emptyList(), inspector.getAllocatedBlocks());
      assertEquals(null, inspector.getBlockAfter(null));
      inspector.createSnapshot();
      // call this twice for code coverage
      inspector.createSnapshot();
      try {
        assertEquals(inspector.getAllBlocks(), inspector.getSnapshot());
        MemoryBlock firstBlock = inspector.getFirstBlock();
        assertNotNull(firstBlock);
        assertEquals(1024 * 1024, firstBlock.getBlockSize());
        assertEquals("N/A", firstBlock.getDataType());
        assertEquals(-1, firstBlock.getFreeListId());
        assertTrue(firstBlock.getAddress() > 0);
        assertNull(firstBlock.getNextBlock());
        assertEquals(0, firstBlock.getRefCount());
        assertEquals(0, firstBlock.getSlabId());
        assertEquals(MemoryBlock.State.UNUSED, firstBlock.getState());
        assertFalse(firstBlock.isCompressed());
        assertFalse(firstBlock.isSerialized());
        assertEquals(null, inspector.getBlockAfter(firstBlock));
      } finally {
        inspector.clearSnapshot();
      }
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  @Test
  public void testClose() {
    System.setProperty(MemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY, "false");
    SlabImpl slab = new SlabImpl(1024 * 1024);
    boolean freeSlab = true;
    SlabImpl[] slabs = new SlabImpl[] {slab};
    try {
      MemoryAllocatorImpl ma = MemoryAllocatorImpl.createForUnitTest(
          new NullOutOfOffHeapMemoryListener(), new NullOffHeapMemoryStats(), slabs);
      ma.close();
      ma.close();
      System.setProperty(MemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY, "true");
      try {
        ma = MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
            new NullOffHeapMemoryStats(), slabs);
        ma.close();
        freeSlab = false;
        ma.close();
      } finally {
        System.clearProperty(MemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY);
      }
    } finally {
      if (freeSlab) {
        MemoryAllocatorImpl.freeOffHeapMemory();
      }
    }

  }

  @Test
  public void testDefragmentation() {
    final int perObjectOverhead = OffHeapStoredObject.HEADER_SIZE;
    final int BIG_ALLOC_SIZE = 150000;
    final int SMALL_ALLOC_SIZE = BIG_ALLOC_SIZE / 2;
    final int TOTAL_MEM = BIG_ALLOC_SIZE;
    SlabImpl slab = new SlabImpl(TOTAL_MEM);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      StoredObject bmc = ma.allocate(BIG_ALLOC_SIZE - perObjectOverhead);
      try {
        StoredObject smc = ma.allocate(SMALL_ALLOC_SIZE - perObjectOverhead);
        fail("Expected out of memory");
      } catch (OutOfOffHeapMemoryException expected) {
      }
      bmc.release();
      assertEquals(TOTAL_MEM, ma.freeList.getFreeMemory());
      StoredObject smc1 = ma.allocate(SMALL_ALLOC_SIZE - perObjectOverhead);
      StoredObject smc2 = ma.allocate(SMALL_ALLOC_SIZE - perObjectOverhead);
      smc2.release();
      assertEquals(TOTAL_MEM - SMALL_ALLOC_SIZE, ma.freeList.getFreeMemory());
      try {
        bmc = ma.allocate(BIG_ALLOC_SIZE - perObjectOverhead);
        fail("Expected out of memory");
      } catch (OutOfOffHeapMemoryException expected) {
      }
      smc1.release();
      assertEquals(TOTAL_MEM, ma.freeList.getFreeMemory());
      bmc = ma.allocate(BIG_ALLOC_SIZE - perObjectOverhead);
      bmc.release();
      assertEquals(TOTAL_MEM, ma.freeList.getFreeMemory());
      ArrayList<StoredObject> mcs = new ArrayList<>();
      for (int i = 0; i < BIG_ALLOC_SIZE / (8 + perObjectOverhead); i++) {
        mcs.add(ma.allocate(8));
      }
      checkMcs(mcs);
      assertEquals(0, ma.freeList.getFreeMemory());
      try {
        ma.allocate(8);
        fail("expected out of memory");
      } catch (OutOfOffHeapMemoryException expected) {
      }
      mcs.remove(0).release(); // frees 8+perObjectOverhead
      assertEquals(8 + perObjectOverhead, ma.freeList.getFreeMemory());
      mcs.remove(0).release(); // frees 8+perObjectOverhead
      assertEquals((8 + perObjectOverhead) * 2, ma.freeList.getFreeMemory());
      ma.allocate(16).release(); // allocates and frees 16+perObjectOverhead; still have
                                 // perObjectOverhead
      assertEquals((8 + perObjectOverhead) * 2, ma.freeList.getFreeMemory());
      mcs.remove(0).release(); // frees 8+perObjectOverhead
      assertEquals((8 + perObjectOverhead) * 3, ma.freeList.getFreeMemory());
      mcs.remove(0).release(); // frees 8+perObjectOverhead
      assertEquals((8 + perObjectOverhead) * 4, ma.freeList.getFreeMemory());
      // At this point I should have 8*4 + perObjectOverhead*4 of free memory
      ma.allocate(8 * 4 + perObjectOverhead * 3).release();
      assertEquals((8 + perObjectOverhead) * 4, ma.freeList.getFreeMemory());
      mcs.remove(0).release(); // frees 8+perObjectOverhead
      assertEquals((8 + perObjectOverhead) * 5, ma.freeList.getFreeMemory());
      // At this point I should have 8*5 + perObjectOverhead*5 of free memory
      try {
        ma.allocate((8 * 5 + perObjectOverhead * 4) + 1);
        fail("expected out of memory");
      } catch (OutOfOffHeapMemoryException expected) {
      }
      mcs.remove(0).release(); // frees 8+perObjectOverhead
      assertEquals((8 + perObjectOverhead) * 6, ma.freeList.getFreeMemory());
      checkMcs(mcs);
      // At this point I should have 8*6 + perObjectOverhead*6 of free memory
      StoredObject mc24 = ma.allocate(24);
      checkMcs(mcs);
      assertEquals((8 + perObjectOverhead) * 6 - (24 + perObjectOverhead),
          ma.freeList.getFreeMemory());
      // At this point I should have 8*3 + perObjectOverhead*5 of free memory
      StoredObject mc16 = ma.allocate(16);
      checkMcs(mcs);
      assertEquals(
          (8 + perObjectOverhead) * 6 - (24 + perObjectOverhead) - (16 + perObjectOverhead),
          ma.freeList.getFreeMemory());
      // At this point I should have 8*1 + perObjectOverhead*4 of free memory
      mcs.add(ma.allocate(8));
      checkMcs(mcs);
      assertEquals((8 + perObjectOverhead) * 6 - (24 + perObjectOverhead) - (16 + perObjectOverhead)
          - (8 + perObjectOverhead), ma.freeList.getFreeMemory());
      // At this point I should have 8*0 + perObjectOverhead*3 of free memory
      StoredObject mcDO = ma.allocate(perObjectOverhead * 2);
      checkMcs(mcs);
      // At this point I should have 8*0 + perObjectOverhead*0 of free memory
      assertEquals(0, ma.freeList.getFreeMemory());
      try {
        ma.allocate(1);
        fail("expected out of memory");
      } catch (OutOfOffHeapMemoryException expected) {
      }
      checkMcs(mcs);
      assertEquals(0, ma.freeList.getFreeMemory());
      mcDO.release();
      assertEquals((perObjectOverhead * 3), ma.freeList.getFreeMemory());
      mcs.remove(mcs.size() - 1).release();
      assertEquals((perObjectOverhead * 3) + (8 + perObjectOverhead), ma.freeList.getFreeMemory());
      mc16.release();
      assertEquals((perObjectOverhead * 3) + (8 + perObjectOverhead) + (16 + perObjectOverhead),
          ma.freeList.getFreeMemory());
      mc24.release();
      assertEquals((perObjectOverhead * 3) + (8 + perObjectOverhead) + (16 + perObjectOverhead)
          + (24 + perObjectOverhead), ma.freeList.getFreeMemory());

      long freeMem = ma.freeList.getFreeMemory();
      for (StoredObject mc : mcs) {
        mc.release();
        assertEquals(freeMem + (8 + perObjectOverhead), ma.freeList.getFreeMemory());
        freeMem += (8 + perObjectOverhead);
      }
      mcs.clear();
      assertEquals(TOTAL_MEM, ma.freeList.getFreeMemory());
      bmc = ma.allocate(BIG_ALLOC_SIZE - perObjectOverhead);
      bmc.release();
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  @Test
  public void testUsageEventListener() {
    final int perObjectOverhead = OffHeapStoredObject.HEADER_SIZE;
    final int SMALL_ALLOC_SIZE = 1000;
    SlabImpl slab = new SlabImpl(3000);
    try {
      MemoryAllocatorImpl ma =
          MemoryAllocatorImpl.createForUnitTest(new NullOutOfOffHeapMemoryListener(),
              new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      MemoryUsageListener listener = bytesUsed -> {
        memoryUsageEventReceived = true;
        assertEquals(expectedMemoryUsage, bytesUsed);
      };
      ma.addMemoryUsageListener(listener);

      expectedMemoryUsage = SMALL_ALLOC_SIZE;
      memoryUsageEventReceived = false;
      StoredObject smc = ma.allocate(SMALL_ALLOC_SIZE - perObjectOverhead);
      assertEquals(true, memoryUsageEventReceived);

      expectedMemoryUsage = SMALL_ALLOC_SIZE * 2;
      memoryUsageEventReceived = false;
      smc = ma.allocate(SMALL_ALLOC_SIZE - perObjectOverhead);
      assertEquals(true, memoryUsageEventReceived);

      MemoryUsageListener unaddedListener = bytesUsed -> {
        throw new IllegalStateException("Should never be called");
      };
      ma.removeMemoryUsageListener(unaddedListener);

      ma.removeMemoryUsageListener(listener);

      ma.removeMemoryUsageListener(unaddedListener);

      expectedMemoryUsage = SMALL_ALLOC_SIZE * 2;
      memoryUsageEventReceived = false;
      smc = ma.allocate(SMALL_ALLOC_SIZE - perObjectOverhead);
      assertEquals(false, memoryUsageEventReceived);

    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }

  private void checkMcs(ArrayList<StoredObject> mcs) {
    for (StoredObject mc : mcs) {
      assertEquals(8 + 8, mc.getSize());
    }
  }

  @Test
  public void testOutOfOffHeapMemory() {
    final int perObjectOverhead = OffHeapStoredObject.HEADER_SIZE;
    final int BIG_ALLOC_SIZE = 150000;
    final int SMALL_ALLOC_SIZE = BIG_ALLOC_SIZE / 2;
    final int TOTAL_MEM = BIG_ALLOC_SIZE;
    final SlabImpl slab = new SlabImpl(TOTAL_MEM);
    final AtomicReference<OutOfOffHeapMemoryException> ooom =
        new AtomicReference<>();
    final OutOfOffHeapMemoryListener oooml = new OutOfOffHeapMemoryListener() {
      @Override
      public void outOfOffHeapMemory(OutOfOffHeapMemoryException cause) {
        ooom.set(cause);
      }

      @Override
      public void close() {}
    };
    try {
      MemoryAllocatorImpl ma = MemoryAllocatorImpl.createForUnitTest(oooml,
          new NullOffHeapMemoryStats(), new SlabImpl[] {slab});
      // make a big allocation
      StoredObject bmc = ma.allocate(BIG_ALLOC_SIZE - perObjectOverhead);
      assertNull(ooom.get());
      // drive the ma to ooom with small allocations
      try {
        StoredObject smc = ma.allocate(SMALL_ALLOC_SIZE - perObjectOverhead);
        fail("Expected out of memory");
      } catch (OutOfOffHeapMemoryException expected) {
      }
      assertNotNull(ooom.get());
      assertTrue(
          ooom.get().getMessage().contains("Out of off-heap memory. Could not allocate size of "));
    } finally {
      MemoryAllocatorImpl.freeOffHeapMemory();
    }
  }
}
