/******************************************************************************* * Copyright (c) 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: * Matthew Khouzam - Initial API and implementation *******************************************************************************/ package org.eclipse.tracecompass.ctf.core.tests.types; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import org.eclipse.tracecompass.ctf.core.CTFException; import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer; import org.eclipse.tracecompass.ctf.core.event.types.Encoding; import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration; import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration; 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.StringDeclaration; import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration; import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration; import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderCompactDeclaration; import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition; import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderLargeDeclaration; import org.junit.Before; import org.junit.Test; /** * Event header declaration tests * * @author Matthew Khouzam * */ public class EventHeaderDeclarationTest { private static final int ID = 2222; private static final int TIMESTAMP = 1000; private static final int VALID_LARGE = 1; private static final int VALID_COMPACT = 0; private final List<StructDeclaration> declarations = new ArrayList<>(); /** * Setup */ @Before public void init() { declarations.clear(); /** * do not reflow * * <pre> * struct event_header_compact { * enum : uint5_t { compact = 0 ... 30, extended = 31 } id; * variant <id> { * struct { * uint27_clock_monotonic_t timestamp; * } compact; * struct { * uint32_t id; * uint64_clock_monotonic_t timestamp; * } extended; * } v; * } align(8); * </pre> */ StructDeclaration base = new StructDeclaration(8); EnumDeclaration enumDec = new EnumDeclaration(IntegerDeclaration.createDeclaration(5, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); enumDec.add(0, 30, "compact"); enumDec.add(31, 31, "extended"); base.addField("id", enumDec); VariantDeclaration variantV = new VariantDeclaration(); StructDeclaration compact = new StructDeclaration(1); compact.addField("timestamp", IntegerDeclaration.createDeclaration(27, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); variantV.addField("compact", compact); StructDeclaration large = new StructDeclaration(1); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", IntegerDeclaration.UINT_64B_DECL); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); /** * Do not reflow * * <pre> * struct event_header_large { * enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id; * variant <id> { * struct { * uint32_clock_monotonic_t timestamp; * } compact; * struct { * uint32_t id; * uint64_clock_monotonic_t timestamp; * } extended; * } v; * } align(8); * </pre> */ base = new StructDeclaration(8); enumDec = new EnumDeclaration(IntegerDeclaration.createDeclaration(16, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); enumDec.add(0, 65534, "compact"); enumDec.add(65535, 65535, "extended"); base.addField("id", enumDec); variantV = new VariantDeclaration(); compact = new StructDeclaration(8); compact.addField("timestamp", IntegerDeclaration.UINT_32B_DECL); variantV.addField("compact", compact); large = new StructDeclaration(8); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", IntegerDeclaration.UINT_64B_DECL); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad - misnamed enum base = new StructDeclaration(8); enumDec = new EnumDeclaration(IntegerDeclaration.createDeclaration(5, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); enumDec.add(0, 30, "compact"); enumDec.add(31, 31, "large"); base.addField("id", enumDec); variantV = new VariantDeclaration(); compact = new StructDeclaration(1); compact.addField("timestamp", IntegerDeclaration.createDeclaration(27, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); variantV.addField("compact", compact); large = new StructDeclaration(1); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", IntegerDeclaration.UINT_64B_DECL); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad - missing enum base = new StructDeclaration(8); enumDec = new EnumDeclaration(IntegerDeclaration.createDeclaration(5, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); enumDec.add(0, 30, "compact"); base.addField("id", enumDec); variantV = new VariantDeclaration(); compact = new StructDeclaration(1); compact.addField("timestamp", IntegerDeclaration.createDeclaration(27, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); variantV.addField("compact", compact); large = new StructDeclaration(1); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", IntegerDeclaration.UINT_64B_DECL); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad - int 5 alignment 8 bit base = new StructDeclaration(8); enumDec = new EnumDeclaration(IntegerDeclaration.createDeclaration(5, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 8)); enumDec.add(0, 30, "compact"); enumDec.add(31, 31, "extended"); base.addField("id", enumDec); variantV = new VariantDeclaration(); compact = new StructDeclaration(1); compact.addField("timestamp", IntegerDeclaration.createDeclaration(27, false, 10, ByteOrder.BIG_ENDIAN, Encoding.NONE, "", 1)); variantV.addField("compact", compact); large = new StructDeclaration(1); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", IntegerDeclaration.UINT_64B_DECL); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad - well, sounds nice though base = new StructDeclaration(8); base.addField("potato salad", new FloatDeclaration(8, 8, ByteOrder.BIG_ENDIAN, 8)); base.addField("bbq ribs", new FloatDeclaration(8, 8, ByteOrder.BIG_ENDIAN, 8)); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.UINT_16B_DECL)); base.addField("v", new FloatDeclaration(8, 8, ByteOrder.BIG_ENDIAN, 8)); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.UINT_5B_DECL)); base.addField("v", new FloatDeclaration(8, 8, ByteOrder.BIG_ENDIAN, 8)); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.UINT_5B_DECL)); variantV = new VariantDeclaration(); compact = new StructDeclaration(8); compact.addField("timestamp", IntegerDeclaration.UINT_27B_DECL); variantV.addField("compact1", compact); large = new StructDeclaration(8); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", IntegerDeclaration.UINT_64B_DECL); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.UINT_5B_DECL)); variantV = new VariantDeclaration(); compact = new StructDeclaration(8); compact.addField("timestamp", IntegerDeclaration.UINT_27B_DECL); variantV.addField("compact", compact); large = new StructDeclaration(8); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp1", IntegerDeclaration.UINT_64B_DECL); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.UINT_5B_DECL)); variantV = new VariantDeclaration(); compact = new StructDeclaration(8); compact.addField("timestamp", IntegerDeclaration.UINT_27B_DECL); variantV.addField("compact", compact); large = new StructDeclaration(8); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", StringDeclaration.getStringDeclaration(Encoding.UTF8)); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.UINT_5B_DECL)); variantV = new VariantDeclaration(); compact = new StructDeclaration(8); compact.addField("timestamp", IntegerDeclaration.UINT_27B_DECL); variantV.addField("compact", compact); variantV.addField("surprise!", compact); large = new StructDeclaration(8); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", StringDeclaration.getStringDeclaration(Encoding.UTF8)); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.UINT_16B_DECL)); variantV = new VariantDeclaration(); compact = new StructDeclaration(8); compact.addField("timestamp", IntegerDeclaration.UINT_27B_DECL); variantV.addField("compact", compact); variantV.addField("surprise!", compact); large = new StructDeclaration(8); large.addField("id", IntegerDeclaration.UINT_32B_DECL); large.addField("timestamp", StringDeclaration.getStringDeclaration(Encoding.UTF8)); variantV.addField("extended", large); base.addField("v", variantV); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new FloatDeclaration(8, 8, ByteOrder.BIG_ENDIAN, 8)); base.addField("v", new FloatDeclaration(8, 8, ByteOrder.BIG_ENDIAN, 8)); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", IntegerDeclaration.INT_32B_DECL); base.addField("timestamp", IntegerDeclaration.INT_32B_DECL); declarations.add(base); // bad base = new StructDeclaration(8); base.addField("id", new EnumDeclaration(IntegerDeclaration.INT_8_DECL)); base.addField("timestamp", IntegerDeclaration.INT_32B_DECL); declarations.add(base); } /** * Validate a compact declaration */ @Test public void validateCompact() { assertEquals(true, EventHeaderCompactDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN).isCompactEventHeader(declarations.get(VALID_COMPACT))); } /** * Fail if it validates */ @Test public void validateCompactFail() { for (int i = 0; i < declarations.size(); i++) { if (i == VALID_COMPACT) { continue; } assertEquals(false, EventHeaderCompactDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN).isCompactEventHeader(declarations.get(i))); } } /** * Validate a large declaration */ @Test public void validateLarge() { assertEquals(true, EventHeaderLargeDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN).isLargeEventHeader(declarations.get(VALID_LARGE))); } /** * Fail if it validates */ @Test public void validateLargeFail() { for (int i = 0; i < declarations.size(); i++) { if (i == VALID_LARGE) { continue; } assertEquals(false, EventHeaderLargeDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN).isLargeEventHeader(declarations.get(i))); } } /** * Test an compact compact header * * @throws CTFException * if {@link BitBuffer} is null */ @Test public void testCompactCompact() throws CTFException { ByteBuffer buffer = ByteBuffer.allocate(16); buffer.putInt(0x80000042); byte[] validCompact1 = buffer.array(); EventHeaderCompactDeclaration decl = EventHeaderCompactDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN); final ByteBuffer input = ByteBuffer.wrap(validCompact1); assertNotNull(input); EventHeaderDefinition def = decl.createDefinition(null, "bla", new BitBuffer(input)); assertNotNull(def); assertEquals(16, def.getId()); assertEquals(0x42, def.getTimestamp()); } /** * Test an extended compact header * * @throws CTFException * if {@link BitBuffer} is null */ @Test public void testCompactExtended() throws CTFException { ByteBuffer buffer = ByteBuffer.allocate(16); buffer.put((byte) 0xFF); buffer.putInt(ID); buffer.putLong(TIMESTAMP); byte[] validCompact2 = buffer.array(); EventHeaderCompactDeclaration decl = EventHeaderCompactDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN); final ByteBuffer input = ByteBuffer.wrap(validCompact2); assertNotNull(input); EventHeaderDefinition def = decl.createDefinition(null, "bla", new BitBuffer(input)); assertNotNull(def); assertEquals(ID, def.getId()); assertEquals(TIMESTAMP, def.getTimestamp()); } /** * Test an compact large header * * @throws CTFException * if {@link BitBuffer} is null */ @Test public void testLargeCompact() throws CTFException { ByteBuffer buffer = ByteBuffer.allocate(16); buffer.putShort((short) ID); buffer.putInt(TIMESTAMP); byte[] validLarge1 = buffer.array(); EventHeaderLargeDeclaration decl = EventHeaderLargeDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN); final ByteBuffer input = ByteBuffer.wrap(validLarge1); assertNotNull(input); EventHeaderDefinition def = decl.createDefinition(null, "bla", new BitBuffer(input)); assertNotNull(def); assertEquals(ID, def.getId()); assertEquals(TIMESTAMP, def.getTimestamp()); assertEquals(ID, ((IntegerDefinition) def.getDefinition("id")).getValue()); assertEquals(TIMESTAMP, ((IntegerDefinition) def.getDefinition("timestamp")).getValue()); } /** * Test an large large header * * @throws CTFException * if {@link BitBuffer} is null */ @Test public void testLargeExtended() throws CTFException { ByteBuffer buffer = ByteBuffer.allocate(16); buffer.putShort((short) -1); buffer.putInt(ID); buffer.putLong(TIMESTAMP); byte[] validLarge2 = buffer.array(); EventHeaderLargeDeclaration decl = EventHeaderLargeDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN); final ByteBuffer input = ByteBuffer.wrap(validLarge2); assertNotNull(input); EventHeaderDefinition def = decl.createDefinition(null, "bla", new BitBuffer(input)); assertNotNull(def); assertEquals(ID, def.getId()); assertEquals(TIMESTAMP, def.getTimestamp()); assertEquals(ID, ((IntegerDefinition) def.getDefinition("id")).getValue()); assertEquals(TIMESTAMP, ((IntegerDefinition) def.getDefinition("timestamp")).getValue()); } /** * Test maximum sizes, make sure they don't change unannounced */ @Test public void testMaxSizes() { assertEquals(112, (EventHeaderLargeDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN)).getMaximumSize()); assertEquals(104, (EventHeaderCompactDeclaration.getEventHeader(ByteOrder.BIG_ENDIAN)).getMaximumSize()); } }