| /******************************************************************************* |
| * Copyright (c) 2009, 2017 Ericsson |
| * |
| * All rights reserved. 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: |
| * Francois Chouinard - Initial API and implementation |
| * Francois Chouinard - Adapted for TMF Trace Model 1.0 |
| * Alexandre Montplaisir - Port to JUnit4 |
| * Marc-Andre Laperle - Extracted to a common class from TmfCheckpointIndexTest |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.tmf.core.tests.trace.indexer.checkpoint; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.io.File; |
| import java.io.IOException; |
| |
| import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; |
| import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfTraceUpdatedSignal; |
| import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestTrace; |
| import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; |
| import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; |
| import org.eclipse.tracecompass.tmf.core.trace.TmfContext; |
| import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfTraceIndexer; |
| import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.ITmfCheckpoint; |
| import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.ITmfCheckpointIndex; |
| import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.TmfCheckpointIndexer; |
| import org.eclipse.tracecompass.tmf.tests.stubs.trace.TmfEmptyTraceStub; |
| import org.eclipse.tracecompass.tmf.tests.stubs.trace.TmfTraceStub; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| /** |
| * Common code for index testing |
| * |
| * @author Marc-Andre Laperle |
| */ |
| public abstract class AbstractIndexTest { |
| |
| // ------------------------------------------------------------------------ |
| // Variables |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * |
| */ |
| protected static final int BLOCK_SIZE = 100; |
| /** |
| * The expected number of events in the test trace. |
| */ |
| protected static final int NB_EVENTS = 10000; |
| /** |
| * Used to dispose the trace once the desired number of events has been |
| * reached in the trace. This has the wanted side effect of stopping the |
| * indexing once a number of events has been reached. |
| */ |
| protected long fNbEventsLimit; |
| /** |
| * The trace being tested |
| */ |
| protected static TestTrace fTrace = null; |
| private static EmptyTestTrace fEmptyTrace = null; |
| |
| // ------------------------------------------------------------------------ |
| // Housekeeping |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Setup the test |
| */ |
| @Before |
| public void setUp() { |
| fNbEventsLimit = Long.MAX_VALUE; |
| setupTrace(getTracePath()); |
| } |
| |
| /** |
| * Get the trace path |
| * |
| * @return the trace path |
| */ |
| protected String getTracePath() { |
| return TmfTestTrace.A_TEST_10K.getFullPath(); |
| } |
| |
| /** |
| * Tear down the test |
| */ |
| @After |
| public void tearDown() { |
| fTrace.dispose(); |
| fTrace = null; |
| fEmptyTrace.dispose(); |
| fEmptyTrace = null; |
| } |
| |
| interface ITestIndexer extends ITmfTraceIndexer { |
| ITmfCheckpointIndex getCheckpoints(); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Helper classes |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * A test indexer |
| */ |
| protected static class TestIndexer extends TmfCheckpointIndexer implements ITestIndexer { |
| /** |
| * Constructs the test indexer for a normal test trace |
| * |
| * @param testTrace |
| * the test trace |
| */ |
| public TestIndexer(ITmfTrace testTrace) { |
| super(testTrace, BLOCK_SIZE); |
| } |
| |
| @Override |
| public ITmfCheckpointIndex getCheckpoints() { |
| return getTraceIndex(); |
| } |
| } |
| |
| /** |
| * Create the indexer for testing |
| * |
| * @param trace |
| * the trace |
| * @return the indexer for testing |
| */ |
| protected ITestIndexer createTestIndexer(TestTrace trace) { |
| return new TestIndexer(trace); |
| } |
| |
| /** |
| * A test trace |
| */ |
| protected class TestTrace extends TmfTraceStub { |
| /** |
| * |
| * @param path |
| * the path |
| * @param blockSize |
| * the block size |
| * @throws TmfTraceException |
| * when error occurs |
| */ |
| public TestTrace(String path, int blockSize) throws TmfTraceException { |
| super(path, blockSize, false, null); |
| } |
| |
| @Override |
| protected ITmfTraceIndexer createIndexer(int interval) { |
| return createTestIndexer(this); |
| } |
| |
| @Override |
| public ITestIndexer getIndexer() { |
| return (ITestIndexer) super.getIndexer(); |
| } |
| |
| /** |
| * Track the number of events in the trace in order to stop when the |
| * limit has been reached (fNbEventsLimit). |
| * |
| * @param signal |
| * the TmfTraceUpdatedSignal |
| */ |
| @TmfSignalHandler |
| public void testTraceUpdated(final TmfTraceUpdatedSignal signal) { |
| if (getNbEvents() >= fNbEventsLimit) { |
| dispose(); |
| } |
| } |
| } |
| |
| private class EmptyTestTrace extends TmfEmptyTraceStub { |
| public EmptyTestTrace(String path) throws TmfTraceException { |
| super(path); |
| } |
| |
| @Override |
| protected ITmfTraceIndexer createIndexer(int interval) { |
| return new TestIndexer(this); |
| } |
| |
| @Override |
| public ITestIndexer getIndexer() { |
| return (ITestIndexer) super.getIndexer(); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Helper functions |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Creates the trace for the specified path |
| * |
| * @param path |
| * the path |
| * @return the created trace |
| * @throws TmfTraceException |
| * when error occurs |
| */ |
| protected TestTrace createTrace(final String path) throws TmfTraceException { |
| TestTrace trace = new TestTrace(path, BLOCK_SIZE); |
| trace.indexTrace(true); |
| return trace; |
| } |
| |
| private synchronized void setupTrace(final String path) { |
| if (fTrace == null) { |
| try { |
| fTrace = createTrace(path); |
| } catch (final TmfTraceException e) { |
| fail(e.getMessage()); |
| } |
| } |
| |
| if (fEmptyTrace == null) { |
| try { |
| File file = File.createTempFile("empty", "txt"); |
| fEmptyTrace = new EmptyTestTrace(file.getAbsolutePath()); |
| } catch (TmfTraceException | IOException e) { |
| fail(e.getMessage()); |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Verify checkpoints |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Test the content of the index after building the full index |
| */ |
| @Test |
| public void testTmfTraceIndexing() { |
| verifyIndexContent(); |
| } |
| |
| /** |
| * Verify the content of the index |
| */ |
| protected static void verifyIndexContent() { |
| assertEquals(BLOCK_SIZE, fTrace.getCacheSize()); |
| assertEquals(NB_EVENTS, fTrace.getNbEvents()); |
| assertEquals(1, fTrace.getTimeRange().getStartTime().getValue()); |
| assertEquals(NB_EVENTS, fTrace.getTimeRange().getEndTime().getValue()); |
| assertEquals(1, fTrace.getStartTime().getValue()); |
| assertEquals(NB_EVENTS, fTrace.getEndTime().getValue()); |
| |
| ITmfCheckpointIndex checkpoints = fTrace.getIndexer().getCheckpoints(); |
| int pageSize = fTrace.getCacheSize(); |
| assertTrue(checkpoints != null); |
| assertEquals(NB_EVENTS, checkpoints.getNbEvents()); |
| assertEquals(NB_EVENTS / BLOCK_SIZE, checkpoints.size()); |
| |
| // Validate that each checkpoint points to the right event |
| for (int i = 0; i < checkpoints.size(); i++) { |
| ITmfCheckpoint checkpoint = checkpoints.get(i); |
| TmfContext context = new TmfContext(checkpoint.getLocation(), i * pageSize); |
| ITmfEvent event = fTrace.parseEvent(context); |
| assertEquals(context.getRank(), i * pageSize); |
| assertTrue((checkpoint.getTimestamp().compareTo(event.getTimestamp()) == 0)); |
| } |
| } |
| |
| /** |
| * Test that a empty trace has the correct content |
| */ |
| @Test |
| public void testEmptyTmfTraceIndexing() { |
| assertEquals(ITmfTrace.DEFAULT_TRACE_CACHE_SIZE, fEmptyTrace.getCacheSize()); |
| assertEquals(0, fEmptyTrace.getNbEvents()); |
| assertEquals(TmfTimestamp.BIG_BANG, fEmptyTrace.getTimeRange().getStartTime()); |
| assertEquals(TmfTimestamp.BIG_BANG, fEmptyTrace.getTimeRange().getEndTime()); |
| assertEquals(TmfTimestamp.BIG_BANG, fEmptyTrace.getStartTime()); |
| assertEquals(TmfTimestamp.BIG_BANG, fEmptyTrace.getEndTime()); |
| |
| ITmfCheckpointIndex checkpoints = fEmptyTrace.getIndexer().getCheckpoints(); |
| assertTrue(checkpoints != null); |
| assertEquals(0, checkpoints.size()); |
| } |
| } |