ctf: support event-header-less traces
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Mon, 23 Nov 2015 23:40:40 +0000 (18:40 -0500)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Tue, 24 Nov 2015 19:00:53 +0000 (14:00 -0500)
This fixes a regression caused by overly zealous @NonNull annotations
coupled with many warnings hiding a problem. The trace reader can now
read traces without an event header again.

Change-Id: Ida701b45cd0438cfd2000443a7a725e31d96669b
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/61090
Reviewed-by: Hudson CI
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Patrick Tasse <patrick.tasse@gmail.com>
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFPacketReaderTest.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/TestAll.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStream.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInputReader.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFPacketReader.java

diff --git a/ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFPacketReaderTest.java b/ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFPacketReaderTest.java
new file mode 100644 (file)
index 0000000..197cd5e
--- /dev/null
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2015 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:
+ *     Matthew Khouzam - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.ctf.core.tests.trace;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.ctf.core.CTFException;
+import org.eclipse.tracecompass.ctf.core.CTFStrings;
+import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
+import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
+import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFPacketReader;
+import org.eclipse.tracecompass.internal.ctf.core.trace.StreamInputPacketIndexEntry;
+import org.junit.Test;
+
+/**
+ * Unit tests for ctf packet reader: this tests creation and reading.
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class CTFPacketReaderTest {
+
+    private static final StructDeclaration EMPTY_STRUCT = new StructDeclaration(8);
+
+    private static @NonNull BitBuffer createBitBuffer(byte[] bytes) {
+        // TODO: annotate ByteBuffer.wrap
+        ByteBuffer bb = NonNullUtils.checkNotNull(ByteBuffer.wrap(bytes));
+        return new BitBuffer(bb);
+    }
+
+    /**
+     * Test a packet with fields and a header (a normal packet)
+     *
+     * @throws CTFException
+     *             won't happen
+     */
+    @Test
+    public void testPacket() throws CTFException {
+        // step 1: create in memory CTF trace
+        byte[] bytes = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xff, (byte) 0xff, (byte) 0xa5 };
+        BitBuffer input = createBitBuffer(bytes);
+        // step 2, create the packet context
+        ICTFPacketDescriptor packetContext = new StreamInputPacketIndexEntry(0, EMPTY_STRUCT.createDefinition(null, ILexicalScope.TRACE, new BitBuffer()), 8, 0, 0);
+        // step 3 create the event header
+        StructDeclaration eventHeaderDeclaration = new StructDeclaration(8);
+        eventHeaderDeclaration.addField("timestamp", IntegerDeclaration.INT_8_DECL);
+        // step 4 create an event declaration, and only one!
+        final EventDeclaration eventDec = new EventDeclaration();
+        eventDec.setName("Hello");
+        StructDeclaration fields = new StructDeclaration(8);
+        fields.addField("field1", IntegerDeclaration.UINT_16L_DECL);
+        fields.addField("field2", IntegerDeclaration.UINT_8_DECL);
+        eventDec.setFields(fields);
+        eventDec.setLogLevel(4);
+        List<@Nullable IEventDeclaration> declarations = Collections.singletonList(eventDec);
+        // step 5: give this event a context
+        CTFTrace trace = new CTFTrace();
+        CTFPacketReader cpr = new CTFPacketReader(input, packetContext, declarations, eventHeaderDeclaration, null, null, trace);
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        EventDefinition event = cpr.readNextEvent();
+        assertEquals(0L, event.getTimestamp());
+        assertEquals(0L, ((IntegerDefinition) event.getFields().getDefinition("field1")).getValue());
+        assertEquals(0L, ((IntegerDefinition) event.getFields().getDefinition("field2")).getValue());
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        event = cpr.readNextEvent();
+        assertEquals(1L, event.getTimestamp());
+        assertEquals(65535L, ((IntegerDefinition) event.getFields().getDefinition("field1")).getValue());
+        assertEquals(0xa5, ((IntegerDefinition) event.getFields().getDefinition("field2")).getValue());
+        assertFalse(cpr.hasMoreEvents());
+    }
+
+    /**
+     * Test a packet with fields, a context and a header (a mostly normal
+     * packet)
+     *
+     * @throws CTFException
+     *             won't happen
+     */
+    @Test
+    public void testPacketWithContext() throws CTFException {
+        // step 1: create in memory CTF trace
+        byte[] bytes = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xff, (byte) 0xff, (byte) 0xa5 };
+        BitBuffer input = createBitBuffer(bytes);
+        // step 2, create the packet context
+        ICTFPacketDescriptor packetContext = new StreamInputPacketIndexEntry(0, EMPTY_STRUCT.createDefinition(null, ILexicalScope.TRACE, new BitBuffer()), 8, 0, 0);
+        // step 3 create the event header
+        StructDeclaration eventHeaderDeclaration = new StructDeclaration(8);
+        eventHeaderDeclaration.addField("timestamp", IntegerDeclaration.INT_8_DECL);
+        // step 4 create an event declaration, and only one!
+        final EventDeclaration eventDec = new EventDeclaration();
+        eventDec.setName("Hello");
+        StructDeclaration context = new StructDeclaration(8);
+        context.addField("field1", IntegerDeclaration.UINT_16L_DECL);
+        StructDeclaration fields = new StructDeclaration(8);
+        fields.addField("field2", IntegerDeclaration.UINT_8_DECL);
+        eventDec.setContext(context);
+        eventDec.setFields(fields);
+        eventDec.setLogLevel(5);// I guess?
+        List<@Nullable IEventDeclaration> declarations = Collections.singletonList(eventDec);
+        // step 5: give this event a context
+        CTFTrace trace = new CTFTrace();
+        CTFPacketReader cpr = new CTFPacketReader(input, packetContext, declarations, eventHeaderDeclaration, null, null, trace);
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        EventDefinition event = cpr.readNextEvent();
+        assertEquals(0L, event.getTimestamp());
+        assertEquals(0L, ((IntegerDefinition) event.getContext().getDefinition("field1")).getValue());
+        assertEquals(0L, ((IntegerDefinition) event.getFields().getDefinition("field2")).getValue());
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        event = cpr.readNextEvent();
+        assertEquals(1L, event.getTimestamp());
+        assertEquals(65535L, ((IntegerDefinition) event.getContext().getDefinition("field1")).getValue());
+        assertEquals(0xa5, ((IntegerDefinition) event.getFields().getDefinition("field2")).getValue());
+        assertFalse(cpr.hasMoreEvents());
+    }
+
+    /**
+     * Test a packet with fields and no header (a odd but acceptable packet)
+     *
+     * @throws CTFException
+     *             won't happen
+     */
+    @Test
+    public void testPacketNoHeader() throws CTFException {
+        // step 1: create in memory CTF trace
+        byte[] bytes = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xff, (byte) 0xff, (byte) 0xa5 };
+        BitBuffer input = createBitBuffer(bytes);
+        // step 2, create the packet context
+        ICTFPacketDescriptor packetContext = new StreamInputPacketIndexEntry(0, new StructDeclaration(8).createDefinition(null, ILexicalScope.TRACE, new BitBuffer()), 8, 0, 0);
+        // step 3 create the event header
+        // step 4 create an event declaration, and only one!
+        final EventDeclaration eventDec = new EventDeclaration();
+        eventDec.setName("Hello");
+        StructDeclaration fields = new StructDeclaration(8);
+        fields.addField("timestamp", IntegerDeclaration.INT_8_DECL);
+        fields.addField("field1", IntegerDeclaration.UINT_16L_DECL);
+        fields.addField("field2", IntegerDeclaration.UINT_8_DECL);
+        eventDec.setFields(fields);
+        List<@Nullable IEventDeclaration> declarations = Collections.singletonList(eventDec);
+        // step 5: give this event a context
+        CTFTrace trace = new CTFTrace();
+        CTFPacketReader cpr = new CTFPacketReader(input, packetContext, declarations, null, null, null, trace);
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        EventDefinition event = cpr.readNextEvent();
+        assertEquals(0L, event.getTimestamp());
+        assertEquals(0L, ((IntegerDefinition) event.getFields().getDefinition("field1")).getValue());
+        assertEquals(0L, ((IntegerDefinition) event.getFields().getDefinition("field2")).getValue());
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        event = cpr.readNextEvent();
+        assertEquals(1L, event.getTimestamp());
+        assertEquals(65535L, ((IntegerDefinition) event.getFields().getDefinition("field1")).getValue());
+        assertEquals(0xa5, ((IntegerDefinition) event.getFields().getDefinition("field2")).getValue());
+        assertFalse(cpr.hasMoreEvents());
+    }
+
+    /**
+     * Test a packet with fields and no header (a odd but acceptable packet)
+     *
+     * @throws CTFException
+     *             won't happen
+     */
+    @Test
+    public void testPacketWithPacketContextAndLostEvents() throws CTFException {
+        // step 1: create in memory CTF trace
+        byte[] bytes = { (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x5a };
+        BitBuffer input = createBitBuffer(bytes);
+        // step 2, create the packet context
+        final StructDeclaration packetHeader = new StructDeclaration(8);
+        packetHeader.addField(CTFStrings.EVENTS_DISCARDED, IntegerDeclaration.UINT_16L_DECL);
+        ICTFPacketDescriptor packetContext = new StreamInputPacketIndexEntry(0, packetHeader.createDefinition(null, ILexicalScope.TRACE, input), 8, 0, 16);
+        // step 4 create an event declaration, and only one!
+        final EventDeclaration eventDec = new EventDeclaration();
+        eventDec.setName("Hello");
+        StructDeclaration fields = new StructDeclaration(8);
+        fields.addField("timestamp", IntegerDeclaration.UINT_16L_DECL);
+        fields.addField("field", IntegerDeclaration.UINT_8_DECL);
+        eventDec.setFields(fields);
+        List<@Nullable IEventDeclaration> declarations = Collections.singletonList(eventDec);
+        // step 5: give this event a context
+        CTFTrace trace = new CTFTrace();
+        CTFPacketReader cpr = new CTFPacketReader(input, packetContext, declarations, null, null, null, trace);
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        EventDefinition event = cpr.readNextEvent();
+        assertEquals(0L, event.getTimestamp());
+        assertEquals(event.getDeclaration().getName(), CTFStrings.LOST_EVENT_NAME);
+        assertEquals(512L, ((IntegerDefinition) event.getFields().getDefinition(CTFStrings.LOST_EVENTS_FIELD)).getValue());
+        assertTrue(cpr.hasMoreEvents());
+        event = cpr.readNextEvent();
+        assertEquals(0L, event.getTimestamp());
+        assertEquals(1L, ((IntegerDefinition) event.getFields().getDefinition("field")).getValue());
+        assertNotNull(cpr);
+        assertTrue(cpr.hasMoreEvents());
+        event = cpr.readNextEvent();
+        assertEquals(256L, event.getTimestamp());
+        assertEquals(0x5a, ((IntegerDefinition) event.getFields().getDefinition("field")).getValue());
+        assertFalse(cpr.hasMoreEvents());
+    }
+
+}
index 8e6d5fb431ec3c3115071b25ac280f04ac1faac3..599047c4582bbfa50d068b437cfb5a649c01951e 100644 (file)
@@ -24,6 +24,7 @@ import org.junit.runners.Suite;
  */
 @RunWith(Suite.class)
 @Suite.SuiteClasses({
+    CTFPacketReaderTest.class,
     CTFTraceReaderTest.class,
     CTFTraceTest.class,
     CTFTraceGrowingTest.class,
index dd94b0bfb3860b67031da74e55c38236ebd0292a..00b25372afd20f7bdf30312e597ea94adb99a46f 100644 (file)
@@ -228,7 +228,7 @@ public class CTFStream {
      * @return The event declarations for this stream
      * @since 2.0
      */
-    public @NonNull List<IEventDeclaration> getEventDeclarations() {
+    public @NonNull List<@Nullable IEventDeclaration> getEventDeclarations() {
         return NonNullUtils.checkNotNull(Collections.unmodifiableList(fEvents));
     }
 
index 251a0ccfa02b29d0cb3faa9640109f0d611efeed..e74f4ae33715082dd1eace0669381cc502b83e53 100644 (file)
@@ -12,8 +12,6 @@
 
 package org.eclipse.tracecompass.ctf.core.trace;
 
-import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
-
 import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -31,7 +29,6 @@ import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.internal.ctf.core.Activator;
 import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
 import org.eclipse.tracecompass.internal.ctf.core.trace.CTFPacketReader;
@@ -143,8 +140,7 @@ public class CTFStreamInputReader implements AutoCloseable {
             bitBuffer.position(packet.getPayloadStartBits());
             IDeclaration eventHeaderDeclaration = getStreamInput().getStream().getEventHeaderDeclaration();
             CTFTrace trace = getStreamInput().getStream().getTrace();
-            StructDefinition packetHeaderDef = checkNotNull(trace.getPacketHeaderDef());
-            ctfPacketReader = new CTFPacketReader(bitBuffer, packet, getEventDeclarations(), eventHeaderDeclaration, getStreamEventContextDecl(), packetHeaderDef, trace);
+            ctfPacketReader = new CTFPacketReader(bitBuffer, packet, getEventDeclarations(), eventHeaderDeclaration, getStreamEventContextDecl(), trace.getPacketHeaderDef(), trace);
         }
         return ctfPacketReader;
     }
@@ -255,7 +251,7 @@ public class CTFStreamInputReader implements AutoCloseable {
      * @return Unmodifiable set with the event definitions
      * @since 2.0
      */
-    public List<IEventDeclaration> getEventDeclarations() {
+    public List<@Nullable IEventDeclaration> getEventDeclarations() {
         return fStreamInput.getStream().getEventDeclarations();
     }
 
index b66233bf3a3776fcab7dfb6b437e55d2b13b4149..940490a80ee0f66c6c1257e56df5cebc93e0d8cf 100644 (file)
@@ -62,7 +62,7 @@ public final class CTFPacketReader implements IPacketReader, IDefinitionScope {
 
     private final BitBuffer fInput;
     private final ICTFPacketDescriptor fPacketContext;
-    private final List<IEventDeclaration> fDeclarations;
+    private final List<@Nullable IEventDeclaration> fDeclarations;
     private boolean fHasLost;
     private long fLastTimestamp;
     private @Nullable final IDeclaration fStreamEventHeaderDecl;
@@ -94,7 +94,7 @@ public final class CTFPacketReader implements IPacketReader, IDefinitionScope {
      * @param packetScope
      *            the scope of the packetHeader
      */
-    public CTFPacketReader(BitBuffer input, ICTFPacketDescriptor packetContext, List<IEventDeclaration> declarations, @Nullable IDeclaration eventHeaderDeclaration, @Nullable StructDeclaration streamContext, ICompositeDefinition packetHeader,
+    public CTFPacketReader(BitBuffer input, ICTFPacketDescriptor packetContext, List<@Nullable IEventDeclaration> declarations, @Nullable IDeclaration eventHeaderDeclaration, @Nullable StructDeclaration streamContext, @Nullable ICompositeDefinition packetHeader,
             IDefinitionScope packetScope) {
         fInput = input;
         fPacketContext = packetContext;
This page took 0.029979 seconds and 5 git commands to generate.