Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5bf37e4
ctf: add missing types
MatthewKhouzam Dec 4, 2025
273739a
ctf: make an alias cache to auto-expand ctf2 aliases
MatthewKhouzam Dec 4, 2025
e6256d2
ctf: fix variants can have integer selectors
MatthewKhouzam Dec 4, 2025
fb01bcc
ctf: introduce Dynamic Length String datatype
MatthewKhouzam Dec 5, 2025
de071c5
ctf: add static string type
MatthewKhouzam Dec 5, 2025
efdbe7d
ctf: add static-length-array
MatthewKhouzam Dec 5, 2025
b7d9bc4
ctf: fix if type is not declared explicity, but as a subfield
MatthewKhouzam Dec 5, 2025
832e94c
ctf: add struct support
MatthewKhouzam Dec 5, 2025
20b35b5
ctf: add Dynamic Length Arrays
MatthewKhouzam Dec 5, 2025
d0914cd
ctf: Use declared length as size for BlobDefinitions
MatthewKhouzam Dec 11, 2025
69eff31
ctf: Allow structs to have ctf2 data
MatthewKhouzam Dec 11, 2025
78931c5
ctf: Fix SWTBot Test to have the correct error message to check
MatthewKhouzam Dec 15, 2025
d99c272
ctf: allow declaration scopes to check if the declaration is overlapping
MatthewKhouzam Dec 11, 2025
5da2df8
ctf: support int tags in variants
MatthewKhouzam Dec 11, 2025
80fe55d
ctf: loosen struct check to silently accept null fields
MatthewKhouzam Dec 11, 2025
50035a1
ctf: Attempt to correct scoped lookups
MatthewKhouzam Dec 11, 2025
6139d4a
ctf: lazy load mappings and use a tree
MatthewKhouzam Dec 12, 2025
9d678d0
ctf: fix bug of identifier being incorrect in declarationscope
MatthewKhouzam Dec 12, 2025
c99b993
ctf: make integerDeclaration#equals count mappings
MatthewKhouzam Dec 12, 2025
6550818
ctf: correctly parse integer size
MatthewKhouzam Dec 12, 2025
3c372e1
ctf: simplify integer declaration
MatthewKhouzam Dec 12, 2025
c64b45a
ctf: Make ctf2 trace have environment
MatthewKhouzam Dec 12, 2025
c16de88
ctf: add support for string2s in tmf
MatthewKhouzam Dec 12, 2025
dd789fd
ctf: add float support for ctf2
MatthewKhouzam Dec 12, 2025
61e3a27
ctf: add double float support for ctf2
MatthewKhouzam Dec 12, 2025
e687b36
ctf: Add unit tests
MatthewKhouzam Dec 12, 2025
1b08688
ctf: make CTF1 parsing more rigid
MatthewKhouzam Dec 12, 2025
89429cf
ctf: improve integerdeclaration
MatthewKhouzam Dec 12, 2025
8f5cacf
ctf: Update alignment parser to support CTF2
MatthewKhouzam Jan 12, 2026
3aaab3c
common.test: Loosen testing of logger
MatthewKhouzam Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ Export-Package: org.eclipse.tracecompass.common.core.tests;x-friends:="org.eclip
Import-Package: com.google.common.base,
com.google.common.collect,
com.google.common.primitives,
com.google.gson,
org.eclipse.tracecompass.traceeventlogger
Automatic-Module-Name: org.eclipse.tracecompass.common.core.tests

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Export-Package: org.eclipse.tracecompass.ctf.core.tests;x-friends:="org.eclipse.
org.eclipse.tracecompass.ctf.core.tests.trace;x-internal:=true,
org.eclipse.tracecompass.ctf.core.tests.types;x-internal:=true
Import-Package: com.google.common.collect,
com.google.gson,
org.antlr.runtime;version="3.2.0",
org.apache.commons.io,
org.eclipse.test.performance,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright (c) 2025 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
*******************************************************************************/

package org.eclipse.tracecompass.ctf.core.tests.types;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonStructureFieldMemberMetadataNode;
import org.junit.Test;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

/**
* Integration test class for CTF2 parsing functionality
*/
public class CTF2IntegrationTest {

/**
* Test parsing integer with mappings for enumeration-like behavior
*
* @throws Exception if parsing fails
*/
@Test
public void testIntegerWithMappings() throws Exception {
CTFTrace trace = new CTFTrace();

JsonObject fieldClass = new JsonObject();
fieldClass.add("type", new JsonPrimitive("fixed-length-unsigned-integer"));
fieldClass.add("length", new JsonPrimitive(8));
fieldClass.add("byte-order", new JsonPrimitive("le"));

// Add mappings for enumeration-like behavior
JsonObject mappings = new JsonObject();
JsonArray range1 = new JsonArray();
range1.add(new JsonPrimitive(0));
range1.add(new JsonPrimitive(0));
JsonArray ranges1 = new JsonArray();
ranges1.add(range1);
mappings.add("ZERO", ranges1);

JsonArray range2 = new JsonArray();
range2.add(new JsonPrimitive(1));
range2.add(new JsonPrimitive(1));
JsonArray ranges2 = new JsonArray();
ranges2.add(range2);
mappings.add("ONE", ranges2);

fieldClass.add("mappings", mappings);

JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "fixed-length-unsigned-integer", "test", "int_field", fieldClass);

IntegerDeclaration result = org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer.IntegerDeclarationParser.INSTANCE.parse(node,
new org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer.IntegerDeclarationParser.Param(trace));

assertNotNull(result);
assertEquals(8, result.getLength());
assertNotNull(result.getMappings());
assertEquals(2, result.getMappings().size());
assertTrue(result.getMappings().containsKey("ZERO"));
assertTrue(result.getMappings().containsKey("ONE"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*******************************************************************************
* Copyright (c) 2025 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
*******************************************************************************/

package org.eclipse.tracecompass.ctf.core.tests.types;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.nio.ByteOrder;

import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonStructureFieldMemberMetadataNode;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.floatingpoint.FloatDeclarationParser;
import org.junit.Test;

import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

/**
* Test class for FloatDeclarationParser CTF2 support
*/
public class FloatDeclarationParserTest {

/**
* Test parsing 32-bit floating point from CTF2 JSON
*
* @throws Exception if parsing fails
*/
@Test
public void testCTF2Float32Parsing() throws Exception {
CTFTrace trace = new CTFTrace();

JsonObject fieldClass = new JsonObject();
fieldClass.add("length", new JsonPrimitive(32));
fieldClass.add("byte-order", new JsonPrimitive("le"));

JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "test", "test", "float_field", fieldClass);

FloatDeclaration result = FloatDeclarationParser.INSTANCE.parse(node,
new FloatDeclarationParser.Param(trace));

assertNotNull(result);
assertEquals(8, result.getExponent());
assertEquals(24, result.getMantissa());
assertEquals(ByteOrder.LITTLE_ENDIAN, result.getByteOrder());
}

/**
* Test parsing 64-bit floating point from CTF2 JSON
*
* @throws Exception if parsing fails
*/
@Test
public void testCTF2Float64Parsing() throws Exception {
CTFTrace trace = new CTFTrace();

JsonObject fieldClass = new JsonObject();
fieldClass.add("length", new JsonPrimitive(64));
fieldClass.add("byte-order", new JsonPrimitive("be"));
fieldClass.add("alignment", new JsonPrimitive(8));

JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "test", "test", "double_field", fieldClass);

FloatDeclaration result = FloatDeclarationParser.INSTANCE.parse(node,
new FloatDeclarationParser.Param(trace));

assertNotNull(result);
assertEquals(11, result.getExponent());
assertEquals(53, result.getMantissa());
assertEquals(ByteOrder.BIG_ENDIAN, result.getByteOrder());
assertEquals(8, result.getAlignment());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2025 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
*******************************************************************************/

package org.eclipse.tracecompass.ctf.core.tests.types;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonTraceMetadataNode;
import org.junit.Test;

import com.google.gson.JsonObject;

/**
* Test class for JsonTraceMetadataNode environment parsing
*/
public class JsonTraceMetadataNodeTest {

/**
* Test parsing environment object from CTF2 JSON
*
* @throws Exception if parsing fails
*/
@Test
public void testEnvironmentParsing() throws Exception {
JsonTraceMetadataNode node = new JsonTraceMetadataNode(null, "trace-class", "test");

JsonObject environment = new JsonObject();
environment.addProperty("hostname", "test-host");
environment.addProperty("domain", "kernel");
environment.addProperty("tracer_name", "lttng-modules");

// Simulate Gson deserialization by setting the field directly
java.lang.reflect.Field envField = JsonTraceMetadataNode.class.getDeclaredField("fEnvironment");
envField.setAccessible(true);
envField.set(node, environment);

node.initialize();

assertNotNull(node.getEnvironment());
assertEquals("test-host", node.getEnvironment().get("hostname").getAsString());
assertEquals("kernel", node.getEnvironment().get("domain").getAsString());
assertEquals("lttng-modules", node.getEnvironment().get("tracer_name").getAsString());
}

/**
* Test UID and packet header parsing
*
* @throws Exception if parsing fails
*/
Comment on lines +53 to +57
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Stale Javadoc: mentions "packet header" but method only tests UID.

The method was correctly renamed from testUidAndPacketHeader to testUidParsing, but the Javadoc comment still references "packet header parsing." Update the Javadoc to match the actual test scope.

📝 Suggested fix
     /**
-     * Test UID and packet header parsing
+     * Test UID parsing
      *
      * `@throws` Exception if parsing fails
      */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Test UID and packet header parsing
*
* @throws Exception if parsing fails
*/
/**
* Test UID parsing
*
* `@throws` Exception if parsing fails
*/
🤖 Prompt for AI Agents
In
`@ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/types/JsonTraceMetadataNodeTest.java`
around lines 53 - 57, Update the stale Javadoc on the test method so it matches
the renamed method testUidParsing: replace the description that mentions "packet
header parsing" with a short comment stating the method only tests UID parsing
and keep the `@throws` tag as is; locate the Javadoc immediately above the
testUidParsing method in JsonTraceMetadataNodeTest and edit the summary line
accordingly.

@Test
public void testUidParsing() throws Exception {
JsonTraceMetadataNode node = new JsonTraceMetadataNode(null, "trace-class", "test");

// Simulate Gson deserialization
java.lang.reflect.Field uidField = JsonTraceMetadataNode.class.getDeclaredField("fUid");
uidField.setAccessible(true);
uidField.set(node, "test-uid-123");

node.initialize();

assertEquals("test-uid-123", node.getUid());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*******************************************************************************
* Copyright (c) 2025 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
*******************************************************************************/

package org.eclipse.tracecompass.ctf.core.tests.types;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonStructureFieldMemberMetadataNode;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeAliasParser;
import org.junit.Test;

import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

/**
* Test class for TypeAliasParser CTF2 field type support
*/
public class TypeAliasParserTest {

/**
* Test parsing fixed-length floating point field class
*
* @throws Exception if parsing fails
*/
@Test
public void testFixedLengthFloatingPointParsing() throws Exception {
CTFTrace trace = new CTFTrace();
DeclarationScope scope = new DeclarationScope(null, "test");

JsonObject fieldClass = new JsonObject();
fieldClass.add("type", new JsonPrimitive("fixed-length-floating-point-number"));
fieldClass.add("length", new JsonPrimitive(32));
fieldClass.add("byte-order", new JsonPrimitive("le"));

JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "fixed-length-floating-point-number", "test", "float_field", fieldClass);

IDeclaration result = TypeAliasParser.INSTANCE.parse(node,
new TypeAliasParser.Param(trace, scope));

assertNotNull(result);
assertTrue(result instanceof FloatDeclaration);

FloatDeclaration floatDecl = (FloatDeclaration) result;
assertTrue(floatDecl.getExponent() > 0);
assertTrue(floatDecl.getMantissa() > 0);
}

/**
* Test parsing static-length string field class
*
* @throws Exception if parsing fails
*/
@Test
public void testStaticLengthStringParsing() throws Exception {
CTFTrace trace = new CTFTrace();
DeclarationScope scope = new DeclarationScope(null, "test");

JsonObject fieldClass = new JsonObject();
fieldClass.add("type", new JsonPrimitive("static-length-string"));
fieldClass.add("length", new JsonPrimitive(16));
fieldClass.add("encoding", new JsonPrimitive("utf-8"));

JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "static-length-string", "test", "string_field", fieldClass);

IDeclaration result = TypeAliasParser.INSTANCE.parse(node,
new TypeAliasParser.Param(trace, scope));

assertNotNull(result);
}

/**
* Test parsing dynamic-length string field class
*
* @throws Exception if parsing fails
*/
@Test
public void testDynamicLengthStringParsing() throws Exception {
// Test that the parser doesn't throw an exception for dynamic length strings
// The actual parsing logic may not be fully implemented yet
CTFTrace trace = new CTFTrace();
DeclarationScope scope = new DeclarationScope(null, "test");

JsonObject fieldClass = new JsonObject();
fieldClass.add("type", new JsonPrimitive("dynamic-length-string"));
fieldClass.add("encoding", new JsonPrimitive("utf-8"));

JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "dynamic-length-string", "test", "dyn_string_field", fieldClass);

IDeclaration result = TypeAliasParser.INSTANCE.parse(node,
new TypeAliasParser.Param(trace, scope));
// If we get here without exception, the basic parsing works
assertNotNull(result);

Comment on lines +88 to +105
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Dynamic-length string test is missing length-field-location (CI failure).

The current test triggers the failure: “Dynamic-length string requires length-field-location property”. Add a minimal length-field-location so the parser can proceed (or assert the failure explicitly).

🛠️ Proposed fix
         JsonObject fieldClass = new JsonObject();
         fieldClass.add("type", new JsonPrimitive("dynamic-length-string"));
         fieldClass.add("encoding", new JsonPrimitive("utf-8"));
+        JsonObject lengthFieldLocation = new JsonObject();
+        lengthFieldLocation.add("path", new JsonPrimitive("len")); // or a JsonArray path if required
+        fieldClass.add("length-field-location", lengthFieldLocation);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Test
public void testDynamicLengthStringParsing() throws Exception {
// Test that the parser doesn't throw an exception for dynamic length strings
// The actual parsing logic may not be fully implemented yet
CTFTrace trace = new CTFTrace();
DeclarationScope scope = new DeclarationScope(null, "test");
JsonObject fieldClass = new JsonObject();
fieldClass.add("type", new JsonPrimitive("dynamic-length-string"));
fieldClass.add("encoding", new JsonPrimitive("utf-8"));
JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "dynamic-length-string", "test", "dyn_string_field", fieldClass);
IDeclaration result = TypeAliasParser.INSTANCE.parse(node,
new TypeAliasParser.Param(trace, scope));
// If we get here without exception, the basic parsing works
assertNotNull(result);
`@Test`
public void testDynamicLengthStringParsing() throws Exception {
// Test that the parser doesn't throw an exception for dynamic length strings
// The actual parsing logic may not be fully implemented yet
CTFTrace trace = new CTFTrace();
DeclarationScope scope = new DeclarationScope(null, "test");
JsonObject fieldClass = new JsonObject();
fieldClass.add("type", new JsonPrimitive("dynamic-length-string"));
fieldClass.add("encoding", new JsonPrimitive("utf-8"));
JsonObject lengthFieldLocation = new JsonObject();
lengthFieldLocation.add("path", new JsonPrimitive("len")); // or a JsonArray path if required
fieldClass.add("length-field-location", lengthFieldLocation);
JsonStructureFieldMemberMetadataNode node = new JsonStructureFieldMemberMetadataNode(null, "dynamic-length-string", "test", "dyn_string_field", fieldClass);
IDeclaration result = TypeAliasParser.INSTANCE.parse(node,
new TypeAliasParser.Param(trace, scope));
// If we get here without exception, the basic parsing works
assertNotNull(result);
🤖 Prompt for AI Agents
In
`@ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/types/TypeAliasParserTest.java`
around lines 88 - 105, The test testDynamicLengthStringParsing currently builds
fieldClass without the required length-field-location property causing the
parser error; update the JsonObject fieldClass (used when constructing
JsonStructureFieldMemberMetadataNode) to include a minimal valid
"length-field-location" entry (e.g., a simple JsonPrimitive value acceptable to
the parser such as "previous-field" or whichever minimal location token your
parser expects) before calling TypeAliasParser.INSTANCE.parse so the parser can
proceed and the assertNotNull can run.

}
}
2 changes: 1 addition & 1 deletion ctf/org.eclipse.tracecompass.ctf.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-Vendor: %Bundle-Vendor
Bundle-Version: 5.0.2.qualifier
Bundle-Version: 5.1.0.qualifier
Bundle-Localization: plugin
Bundle-SymbolicName: org.eclipse.tracecompass.ctf.core;singleton:=true
Bundle-ActivationPolicy: lazy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

Expand Down Expand Up @@ -171,8 +172,13 @@ public void setName(String name) {
public void registerType(String name, IDeclaration declaration)
throws ParseException {
/* Check if the type has been defined in the current scope */
if (fTypes.containsKey(name)) {
throw new ParseException("Type has already been defined:" + name); //$NON-NLS-1$
if (name == null || name.isEmpty()) {
// don't register anonymous types
return;
}
IDeclaration originalDeclaration = fTypes.get(name);
if (originalDeclaration != null && !Objects.equals(declaration, originalDeclaration)) {
throw new ParseException("Type has already been defined: " + name); //$NON-NLS-1$
}

/* Add it to the register. */
Expand All @@ -191,10 +197,10 @@ public void registerType(String name, IDeclaration declaration)
*/
public void registerIdentifier(String name, IDeclaration declaration) throws ParseException {
/* Check if the type has been defined in the current scope */
if (fIdentifiers.containsKey(name)) {
IDeclaration iDeclaration = fIdentifiers.get(name);
if (iDeclaration != null && !Objects.equals(iDeclaration, declaration)) {
throw new ParseException("Identifier has already been defined:" + name); //$NON-NLS-1$
}

/* Add it to the register. */
fIdentifiers.put(name, declaration);
}
Expand Down
Loading
Loading