/******************************************************************************* * Copyright (c) 2013, 2014 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Marc-Andre Laperle - Initial API and implementation *******************************************************************************/ package org.eclipse.tracecompass.tmf.core.tests.trace.indexer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.Random; import org.eclipse.tracecompass.internal.tmf.core.trace.indexer.ICheckpointCollection; import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.TmfCheckpoint; import org.eclipse.tracecompass.tmf.core.trace.location.TmfLongLocation; import org.eclipse.tracecompass.tmf.tests.stubs.trace.TmfTraceStub; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Common code for ICheckpointCollection test classes * * @author Marc-Andre Laperle */ public abstract class AbstractCheckpointCollectionTest { private static final String INDEX_FILE_NAME = "checkpoint.idx"; //$NON-NLS-1$ /** * The number of checkpoints to be inserted in insert tests */ protected static final int CHECKPOINTS_INSERT_NUM = 50000; /** * The collection being tested */ protected ICheckpointCollection fCheckpointCollection = null; private TmfTraceStub fTrace; private File fFile = new File(INDEX_FILE_NAME); /** * Setup the test. Make sure the index is deleted. */ @Before public void setUp() { fTrace = new TmfTraceStub(); if (fFile.exists()) { fFile.delete(); } fCheckpointCollection = createCollection(); } /** * Tear down the test. Make sure the index is deleted. */ @After public void tearDown() { fTrace.dispose(); fTrace = null; if (fCheckpointCollection != null) { fCheckpointCollection.dispose(); } if (fFile.exists()) { fFile.delete(); } } /** * Get the trace being tested. * * @return the trace being tested. */ public ITmfTrace getTrace() { return fTrace; } /** * Returns whether or not the collection is persisted to disk * * @return true if the collection is persisted to disk, false otherwise */ public boolean isPersistableCollection() { return false; } /** * Get the file used for the index being tested. * * @return the file used for the index being tested. */ public File getFile() { return fFile; } /** * Test constructing a new checkpoint collection */ @Test public void testConstructor() { if (isPersistableCollection()) { assertTrue(fFile.exists()); } assertTrue(fCheckpointCollection.isCreatedFromScratch()); } /** * Test constructing a new checkpoint collection, existing file */ @Test public void testConstructorExistingFile() { if (isPersistableCollection()) { assertTrue(fFile.exists()); fCheckpointCollection.dispose(); fCheckpointCollection = createCollection(); assertFalse(fCheckpointCollection.isCreatedFromScratch()); } } /** * Test that a new checkpoint collection is considered created from scratch * and vice versa */ @Test public void testIsCreatedFromScratch() { assertTrue(fCheckpointCollection.isCreatedFromScratch()); if (isPersistableCollection()) { fCheckpointCollection.dispose(); fCheckpointCollection = createCollection(); assertFalse(fCheckpointCollection.isCreatedFromScratch()); } } /** * Test setTimeRange, getTimeRange */ @Test public void testSetGetTimeRange() { if (isPersistableCollection()) { TmfTimeRange timeRange = new TmfTimeRange(TmfTimestamp.fromSeconds(0), TmfTimestamp.fromSeconds(100)); fCheckpointCollection.setTimeRange(timeRange); assertEquals(timeRange, fCheckpointCollection.getTimeRange()); } } /** * Create a collection for the test * * @return the collection */ abstract protected ICheckpointCollection createCollection(); /** * Test setNbEvents, getNbEvents */ @Test public void testSetGetNbEvents() { if (isPersistableCollection()) { int expected = 12345; fCheckpointCollection.setNbEvents(expected); assertEquals(expected, fCheckpointCollection.getNbEvents()); } } /** * Test get size */ @Test public void testGetSize() { assertEquals(0, fCheckpointCollection.size()); int expected = CHECKPOINTS_INSERT_NUM; for (int i = 0; i < expected; ++i) { fCheckpointCollection.insert(new TmfCheckpoint(TmfTimestamp.fromSeconds(i), new TmfLongLocation(i), i)); } assertEquals(expected, fCheckpointCollection.size()); } /** * Test delete */ @Test public void testDelete() { if (isPersistableCollection()) { assertTrue(fFile.exists()); fCheckpointCollection.delete(); assertFalse(fFile.exists()); } } /** * Test version change * * @throws IOException * can throw this */ @Test public void testVersionChange() throws IOException { fCheckpointCollection.dispose(); try (RandomAccessFile f = new RandomAccessFile(fFile, "rw");) { f.writeInt(-1); } fCheckpointCollection = createCollection(); assertTrue(fCheckpointCollection.isCreatedFromScratch()); } /** * Test version change * * @throws IOException * can throw this */ @Test public void testDeleteWhenInvalidBug479675() throws IOException { insertAlot(); try (RandomAccessFile f = new RandomAccessFile(fFile, "rw");) { f.writeInt(-1); } fCheckpointCollection = createCollection(); if (isPersistableCollection()) { ICheckpointCollection old = fCheckpointCollection; try { fCheckpointCollection = createCollection(); assertEquals(0, fCheckpointCollection.size()); } finally { old.dispose(); } } assertTrue(fCheckpointCollection.isCreatedFromScratch()); } /** * Test a single insertion */ @Test public void testInsert() { TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(12345), new TmfLongLocation(123456L), 0); fCheckpointCollection.insert(checkpoint); long found = fCheckpointCollection.binarySearch(checkpoint); assertEquals(0, found); assertEquals(1, fCheckpointCollection.size()); } /** * Generate many checkpoints and insert them in the collection * * @return the list of generated checkpoints */ protected ArrayList<Integer> insertAlot() { for (int i = 0; i < CHECKPOINTS_INSERT_NUM; i++) { TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(12345 + i), new TmfLongLocation(123456L + i), i); fCheckpointCollection.insert(checkpoint); } assertEquals(CHECKPOINTS_INSERT_NUM, fCheckpointCollection.size()); if (isPersistableCollection()) { fCheckpointCollection.dispose(); } boolean random = true; ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < CHECKPOINTS_INSERT_NUM; i++) { if (random) { Random rand = new Random(); list.add(rand.nextInt(CHECKPOINTS_INSERT_NUM)); } else { list.add(i); } } return list; } /** * Test many checkpoint insertions. Make sure they can be found after * re-opening the file */ @Test public void testInsertAlot() { ArrayList<Integer> list = insertAlot(); if (isPersistableCollection()) { fCheckpointCollection = createCollection(); } assertEquals(CHECKPOINTS_INSERT_NUM, fCheckpointCollection.size()); for (int i = 0; i < CHECKPOINTS_INSERT_NUM; i++) { Integer randomCheckpoint = list.get(i); TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(12345 + randomCheckpoint), new TmfLongLocation(123456L + randomCheckpoint), 0); long found = fCheckpointCollection.binarySearch(checkpoint); assertEquals(randomCheckpoint.intValue(), found); } assertEquals(CHECKPOINTS_INSERT_NUM, fCheckpointCollection.size()); } /** * Test many checkpoint insertions using the same timestamp. Make sure they * can be found after re-opening the file */ @Test public void testInsertSameTimestamp() { for (int i = 0; i < CHECKPOINTS_INSERT_NUM; i++) { TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(12345), new TmfLongLocation(123456L + i), i); fCheckpointCollection.insert(checkpoint); } assertEquals(CHECKPOINTS_INSERT_NUM, fCheckpointCollection.size()); if (isPersistableCollection()) { fCheckpointCollection.dispose(); } boolean random = true; ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < CHECKPOINTS_INSERT_NUM; i++) { if (random) { Random rand = new Random(); list.add(rand.nextInt(CHECKPOINTS_INSERT_NUM)); } else { list.add(i); } } if (isPersistableCollection()) { fCheckpointCollection = createCollection(); } assertEquals(CHECKPOINTS_INSERT_NUM, fCheckpointCollection.size()); for (int i = 0; i < CHECKPOINTS_INSERT_NUM; i++) { Integer randomCheckpoint = list.get(i); TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(12345), new TmfLongLocation(123456L + randomCheckpoint), 0); long found = fCheckpointCollection.binarySearch(checkpoint); assertEquals(randomCheckpoint.intValue(), found); } } /** * Tests that binarySearch find the correct checkpoint when the time stamp * is between checkpoints */ @Test public void testBinarySearchFindInBetween() { for (long i = 0; i < CHECKPOINTS_INSERT_NUM; i++) { TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(2 * i), new TmfLongLocation(2 * i), i); fCheckpointCollection.insert(checkpoint); } assertEquals(CHECKPOINTS_INSERT_NUM, fCheckpointCollection.size()); TmfCheckpoint searchedCheckpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(123), new TmfLongLocation(123L), 123); int expectedInsertionPoint = 61; int expectedRank = -(expectedInsertionPoint + 2); long rank = fCheckpointCollection.binarySearch(searchedCheckpoint); assertEquals(expectedRank, rank); } /** * Tests that binarySearch finds the correct checkpoint when searching for a * checkpoint with a null location. It should return the previous checkpoint * from the first checkpoint that matches the timestamp. */ @Test public void testBinarySearchInBetweenSameTimestamp() { int checkpointNum = 0; for (; checkpointNum < CHECKPOINTS_INSERT_NUM / 2; checkpointNum++) { TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(0), new TmfLongLocation(checkpointNum), checkpointNum); fCheckpointCollection.insert(checkpoint); } for (; checkpointNum < CHECKPOINTS_INSERT_NUM; checkpointNum++) { TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(1), new TmfLongLocation(checkpointNum), checkpointNum); fCheckpointCollection.insert(checkpoint); } assertEquals(CHECKPOINTS_INSERT_NUM, fCheckpointCollection.size()); final TmfCheckpoint searchedCheckpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(1), null, 0); long found = fCheckpointCollection.binarySearch(searchedCheckpoint); int expectedInsertionPoint = CHECKPOINTS_INSERT_NUM / 2 - 1; int expectedRank = -(expectedInsertionPoint + 2); assertEquals(expectedRank, found); } /** * Test checkpoint insertions after reopening the file. */ @Test public void testInsertAfterReopen() { if (!isPersistableCollection()) { return; } fCheckpointCollection.insert(new TmfCheckpoint(TmfTimestamp.fromSeconds(12345), new TmfLongLocation(123456L), 0)); assertEquals(1, fCheckpointCollection.size()); fCheckpointCollection.dispose(); fCheckpointCollection = createCollection(); assertEquals(1, fCheckpointCollection.size()); TmfCheckpoint checkpoint = new TmfCheckpoint(TmfTimestamp.fromSeconds(12345), new TmfLongLocation(123456L), 0); long found = fCheckpointCollection.binarySearch(checkpoint); assertEquals(0, found); fCheckpointCollection.insert(new TmfCheckpoint(TmfTimestamp.fromSeconds(12345 + 1), new TmfLongLocation(123456L + 1), 1)); assertEquals(2, fCheckpointCollection.size()); fCheckpointCollection.dispose(); fCheckpointCollection = createCollection(); assertEquals(2, fCheckpointCollection.size()); } /** * Test that a checkpoint can be inserted after reopening an empty index. */ @Test public void testInsertAfterEmptyReopen() { fCheckpointCollection.dispose(); fCheckpointCollection = createCollection(); fCheckpointCollection.insert(new TmfCheckpoint(TmfTimestamp.fromSeconds(12345), new TmfLongLocation(123456L), 0)); assertEquals(1, fCheckpointCollection.size()); } }