/*******************************************************************************
 * Copyright (c) 2005, 2016 QNX Software Systems and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     QNX Software Systems - initial API and implementation
 *     Andrew Ferguson (Symbian)
 *     Markus Schorn (Wind River Systems)
 *******************************************************************************/
package org.eclipse.jdt.core.tests.nd;

import org.eclipse.jdt.core.tests.nd.util.BaseTestCase;
import org.eclipse.jdt.internal.core.nd.Nd;
import org.eclipse.jdt.internal.core.nd.db.Database;

import junit.framework.Test;

/**
 * Tests for the {@link Database} class.
 */
public class LargeBlockTest extends BaseTestCase {
	private Nd nd;
	protected Database db;

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		String testName = getName();
		this.nd = DatabaseTestUtil.createWithoutNodeRegistry(testName);
		this.db = this.nd.getDB();
		this.db.setExclusiveLock();
		this.db.flush();
	}

	public static Test suite() {
		return BaseTestCase.suite(LargeBlockTest.class);
	}

	@Override
	protected void tearDown() throws Exception {
		DatabaseTestUtil.deleteDatabase(this.db);
		this.db = null;
	}

	private long mallocChunks(int chunks) {
		return malloc(Database.getBytesThatFitInChunks(chunks));
	}

	private long malloc(long bytes) {
		return this.db.malloc(bytes, Database.POOL_MISC);
	}

	private void free(long address) {
		this.db.free(address, Database.POOL_MISC);
	}

	/**
	 * Allocate the maximum number of bytes that can fit in 3 chunks and verify
	 * that it doesn't overflow.
	 */
	public void testAllocationThatFillsMultipleChunksDoesntOverflow() throws Exception {
		int chunkCount = this.db.getChunkCount();

		int numChunks = 5;
		mallocChunks(numChunks);

		assertEquals("The database should not allocate more (or less) memory than is needed", numChunks + chunkCount,
				this.db.getChunkCount());
	}

	/**
	 * Allocates a few blocks, frees them, then allocates more blocks. Verifies
	 * that the database reuses the chunks from the first allocation when it
	 * tries to allocate the larger block later.
	 */
	public void testLastChunkIsReused() throws Exception {
		int chunkCount = this.db.getChunkCount();

		int numChunks = 10;
		long temporaryBlockAddress = mallocChunks(3);
		free(temporaryBlockAddress);
		mallocChunks(numChunks);

		assertEquals("If the last chunk is free, it should be resized if necessary when a new chunk is requested",
				numChunks + chunkCount, this.db.getChunkCount());
	}

	/**
	 * Tests that if there is a single large free block available, that block
	 * will be split and reused if necessary to satisfy a number of smaller
	 * requests.
	 *
	 * @throws Exception
	 */
	public void testLargeAllocationIsSplitAndReused() throws Exception {
		long tempAddress = malloc(Database.getBytesThatFitInChunks(10));
		// Use some space at the end of the database to prevent the allocator
		// from using the end of the database, where stuff can be easily resized
		mallocChunks(1);
		free(tempAddress);

		// Keep track of how much memory we are currently using, so we can
		// ensure that any further allocations come from the freed block rather
		// than the end of the database.
		int chunkCount = this.db.getChunkCount();

		long firstAllocation = mallocChunks(7);

		assertEquals("The freed chunk should be reused (there should be 10 chunks available)", chunkCount,
				this.db.getChunkCount());

		long secondAllocation = mallocChunks(1);

		assertEquals("The freed chunk should be reused (there should be 3 chunks available)", chunkCount,
				this.db.getChunkCount());

		long thirdAllocation = mallocChunks(2);

		assertEquals("The freed chunk should be reused (there should be exactly 2 chunks available)", chunkCount,
				this.db.getChunkCount());
		assertTrue(
				"Allocations should happen from the start of the database if it makes no difference to fragmentation",
				secondAllocation > firstAllocation);
		assertTrue("Free space should have been kept next to the largest block for as long as possible",
				secondAllocation > thirdAllocation);

		// Do another allocation when there are no free chunks
		mallocChunks(1);

		assertEquals("New chunks should be allocated when the database is out of free blocks", chunkCount + 1,
				this.db.getChunkCount());
	}

	/**
	 * Verifies that if a block is freed and the previous block is also free,
	 * the two free blocks will be combined into a single larger block.
	 */
	public void testFreeBlockMergesWithPrevious() throws Exception {
		long firstBlock = mallocChunks(1);
		long secondBlock = mallocChunks(1);
		mallocChunks(1);

		free(firstBlock);
		free(secondBlock);

		int chunkCount = this.db.getChunkCount();

		mallocChunks(2);
		assertEquals("The merged block should have been used", chunkCount, this.db.getChunkCount());
	}

	/**
	 * Verifies that if a block is freed and the next block is also free, the
	 * two free blocks will be combined into a single larger block.
	 */
	public void testFreeBlockMergesWithNext() throws Exception {
		long firstBlock = mallocChunks(1);
		long secondBlock = mallocChunks(1);
		mallocChunks(1);

		free(secondBlock);
		free(firstBlock);

		int chunkCount = this.db.getChunkCount();

		mallocChunks(2);
		assertEquals("The merged block should have been used", chunkCount, this.db.getChunkCount());
	}

	/**
	 * Verifies that if a block is freed and the blocks on both sides are also
	 * free, the three free blocks will be combined into a single larger block.
	 */
	public void testFreeBlockMergesWithBothNextAndPrevious() throws Exception {
		long firstBlock = mallocChunks(1);
		long secondBlock = mallocChunks(1);
		long thirdBlock = mallocChunks(1);
		mallocChunks(1);

		free(firstBlock);
		free(thirdBlock);
		free(secondBlock);

		int chunkCount = this.db.getChunkCount();

		mallocChunks(3);
		assertEquals("The merged block should have been used", chunkCount, this.db.getChunkCount());
	}

	/**
	 * Tests removal of a chunk from the free space trie when there are
	 * duplicate free space nodes with the same size and the node being removed
	 * isn't the one with the embedded trie node.
	 */
	public void testRemoveFreeSpaceNodeFromDuplicateList() throws Exception {
		long chunk1 = mallocChunks(1);
		mallocChunks(1);
		long chunk3 = mallocChunks(1);
		long chunk4 = mallocChunks(1);
		mallocChunks(1);

		int chunkCount = this.db.getChunkCount();

		free(chunk1);
		free(chunk3);
		// At this point chunks 1 and 3 should be in the same linked list. Chunk
		// 1 contains the embedded trie.

		free(chunk4);
		// Should merge with chunk3, causing it to be removed from the list

		// Verify that we can allocate the merged chunk 3+4
		mallocChunks(2);

		assertEquals("Chunks 3 and 4 should have been merged", chunkCount, this.db.getChunkCount());
	}

	/**
	 * Tests removal of a chunk from the free space trie when the node being
	 * removed was part of the embedded trie and it has a non-empty list of
	 * other nodes of the same size.
	 */
	public void testRemoveFreeSpaceNodeFromTrieWithDuplicates() throws Exception {
		long chunk1 = mallocChunks(1);
		mallocChunks(1);
		long chunk3 = mallocChunks(1);
		long chunk4 = mallocChunks(1);
		mallocChunks(1);

		int chunkCount = this.db.getChunkCount();

		free(chunk3);
		free(chunk1);
		// At this point chunks 1 and 3 should be in the same linked list. Chunk
		// 3 contains the embedded trie.

		free(chunk4);
		// Should merge with chunk3, causing it to be removed from the list

		// Verify that we can allocate the merged chunk 3+4
		mallocChunks(2);

		assertEquals("Chunks 3 and 4 should have been merged", chunkCount, this.db.getChunkCount());
	}

	/**
	 * Tests reusing a chunk from the free space trie when it contains
	 * duplicates.
	 */
	public void testReuseDeallocatedChunksWithMultipleFreeSpaceNodesOfTheSameSize() throws Exception {
		long chunk1 = mallocChunks(2);
		mallocChunks(1);
		long chunk3 = mallocChunks(2);
		mallocChunks(1);
		long chunk5 = mallocChunks(2);
		mallocChunks(1);

		int chunkCount = this.db.getChunkCount();

		free(chunk1);
		free(chunk3);
		free(chunk5);

		mallocChunks(2);

		assertEquals("A chunk should have been reused", chunkCount, this.db.getChunkCount());
	}

	public void testEndOfFreeBlockIsUsedIfThePreviousBlockIsLargerThanTheNextBlock() throws Exception {
		long prevChunk = mallocChunks(4);
		long middleChunk = mallocChunks(4);
		long nextChunk = mallocChunks(2);

		free(middleChunk);
		// This should be taken from the end of "middleChunk", since that's closer to the smaller neighbor
		long smallChunk1 = mallocChunks(1);
		// This should also be taken from the end of the remaining portion of "middleChunk"
		long smallChunk2 = mallocChunks(1);

		assertTrue("The small chunks should have been allocated from space after 'prevChunk'",
				prevChunk < smallChunk2);
		assertTrue("The small chunks should have been allocated from the end of the free block",
				smallChunk2 < smallChunk1);
		assertTrue("The small chunks should have been allocated from space before 'nextChunk'",
				smallChunk1 < nextChunk);
	}

	/**
	 * Tests various corner cases in the trie map.
	 */
	public void testTriesOfVariousSize() throws Exception {
		long chunk1 = mallocChunks(1);
		mallocChunks(1);
		long chunk2 = mallocChunks(2);
		mallocChunks(1);
		long chunk3 = mallocChunks(3);
		mallocChunks(1);
		long chunk4 = mallocChunks(5);
		mallocChunks(1);
		long chunk5 = mallocChunks(6);
		mallocChunks(1);
		long chunk6 = mallocChunks(6);
		mallocChunks(1);
		long chunk7 = mallocChunks(10);
		mallocChunks(1);
		long chunk8 = mallocChunks(20);
		mallocChunks(1);

		int chunkCount = this.db.getChunkCount();

		free(chunk7);
		free(chunk4);
		free(chunk1);
		free(chunk3);
		free(chunk8);
		free(chunk5);
		free(chunk2);
		free(chunk6);

		mallocChunks(4);
		mallocChunks(10);

		assertEquals("A chunk should have been reused", chunkCount, this.db.getChunkCount());
	}

	/**
	 * Tests that if there are multiple free blocks of different sizes and of
	 * exactly one of the requested size, that one is always selected.
	 */
	public void testBestBlockIsAlwaysSelected() throws Exception {
		int[] sizes = { 11, 2, 6, 1, 9, 10, 7, 8, 12, 20, 15, 3 };
		long[] pointers = new long[sizes.length];

		for (int idx = 0; idx < sizes.length; idx++) {
			pointers[idx] = mallocChunks(sizes[idx]);
			mallocChunks(1);
		}

		int chunkCount = this.db.getChunkCount();

		for (int idx = 0; idx < pointers.length; idx++) {
			free(pointers[idx]);
		}

		for (int idx = 0; idx < sizes.length; idx++) {
			long nextPointer = mallocChunks(sizes[idx]);
			assertEquals("Returned wrong pointer for malloc of " + sizes[idx] + " chunks", pointers[idx], nextPointer);
			assertEquals("A chunk should have been reused", chunkCount, this.db.getChunkCount());
		}
	}

	/**
	 * Tests removals from the large chunk sibling list. Ensures that such removals don't interfere with
	 * the trie itself.
	 */
	public void testUnlinkedBlockNotInTrieGetsRelinked() throws Exception {
		long rootChunk = mallocChunks(1);
		mallocChunks(1);
		long unusedChunk = mallocChunks(1);
		mallocChunks(1);
		long chunkToBeMerged = mallocChunks(1);
		long chunkThatWillCauseMerging = mallocChunks(1);
		mallocChunks(1);
		long followingChunkInFreeSpaceList = mallocChunks(1);
		mallocChunks(1);
		long chunkOfSize2 = mallocChunks(2);
		mallocChunks(1);

		int chunkCount = this.db.getChunkCount();

		free(rootChunk);
		free(unusedChunk);
		free(chunkToBeMerged);
		free(followingChunkInFreeSpaceList);
		free(chunkOfSize2);

		// At this point, the free space trie looks like this:
		//
		// size 1: rootChunk -> unusedChunk -> chunkToBeMerged -> followingChunkInFreeSpaceList
		//                   -> size 2: chunkOfSize2
		//
		// By freeing chunkThatWillCauseMerging, chunkToBeMerged will be removed from the
		// list of size 1 and inserted into the list of size 2. This test verifies that the
		// code won't mess with the root pointer by inserting unusedChunk or chunk into the root

		// This call will corrupt the database if we don't do the removal correctly
		free(chunkThatWillCauseMerging);

		// Now reallocate the original chunks to ensure they can all be found in the list
		long firstDoubleChunk = mallocChunks(2);
		long secondDoubleChunk = mallocChunks(2);

		mallocChunks(1);
		mallocChunks(1);
		mallocChunks(1);

		assertEquals("A chunk should have been reused", chunkCount, this.db.getChunkCount());
		assertNotSame("Both new chunks should have been unique", firstDoubleChunk, secondDoubleChunk);
		assertNotSame("The first chunk should not be null", 0, firstDoubleChunk);
		assertNotSame("The second chunk should not be null", 0, secondDoubleChunk);
		this.db.validateFreeSpace();
	}
}
