blob: 5effb0345f3579477fcaaeaaddbc869fdaa1aa6c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 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:
* 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());
}
}