From ad05b94cbe2fc69364f0130ec8732c342dd02f28 Mon Sep 17 00:00:00 2001 From: fatadel Date: Thu, 3 Sep 2026 14:06:23 +0200 Subject: [PATCH 1/2] Add optional segments to marker label templates Marker label templates currently interpolate surrounding text even when a referenced payload field is absent. Let templates wrap optional content in `[[` and `]]` so punctuation and other text can be omitted with the missing value. --- src/profile-logic/marker-schema.ts | 46 +++++++++++++++++++++++++++++ src/test/unit/marker-schema.test.ts | 38 ++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/src/profile-logic/marker-schema.ts b/src/profile-logic/marker-schema.ts index 90a81d4333..97c5afb27b 100644 --- a/src/profile-logic/marker-schema.ts +++ b/src/profile-logic/marker-schema.ts @@ -113,11 +113,16 @@ export function getSchemaFromMarker( // Matches ternary expressions inside marker labels, ie {marker.data.field ? 'truthy' : 'falsy'} const TERNARY_RE = /^\s*([\w.]+)\s*\?\s*'([^']*)'\s*:\s*'([^']*)'\s*$/; +const OPTIONAL_SEGMENT_RE = /\[\[([\s\S]*?)\]\]/; +const OPTIONAL_SEGMENT_PAYLOAD_KEY_RE = + /\{\s*marker\.data\.([^.{}\s?]+)(?=\s*(?:\}|\?))/g; /** * Marker schema can create a dynamic tooltip label. For instance a schema with * a `tooltipLabel` field of "Event at {marker.data.url}" would create a label based * off of the "url" property in the payload. + * Segments wrapped in `[[` and `]]` are omitted when any payload field they + * reference is absent or empty. * * Note that this is only exported for unit tests. */ @@ -127,6 +132,47 @@ export function parseLabel( stringTable: StringTable, label: string ): (marker: Marker) => string { + const segments = label.split(OPTIONAL_SEGMENT_RE); + if (segments.length > 1) { + const computeSegments = segments.map((segment, index) => { + const computeSegment = parseLabel( + markerSchema, + categories, + stringTable, + segment + ); + if (index % 2 === 0) { + return computeSegment; + } + + const payloadKeys = Array.from( + segment.matchAll(OPTIONAL_SEGMENT_PAYLOAD_KEY_RE), + (match) => match[1] + ); + if (payloadKeys.length === 0) { + return (marker: Marker) => `[[${computeSegment(marker)}]]`; + } + + return (marker: Marker) => { + for (const payloadKey of payloadKeys) { + const value = (marker.data as any)?.[payloadKey]; + if (value === undefined || value === null || value === '') { + return ''; + } + } + return computeSegment(marker); + }; + }); + + return (marker: Marker) => { + let result: string = ''; + for (const computeSegment of computeSegments) { + result += computeSegment(marker); + } + return result; + }; + } + // Split the label on the "{key}" capture groups. // Each (zero-indexed) even entry will be a raw string label. // Each (zero-indexed) odd entry will be a key to the payload. diff --git a/src/test/unit/marker-schema.test.ts b/src/test/unit/marker-schema.test.ts index 31f7ed8dd2..ad51615253 100644 --- a/src/test/unit/marker-schema.test.ts +++ b/src/test/unit/marker-schema.test.ts @@ -172,6 +172,44 @@ describe('marker schema labels', function () { expect(console.error).toHaveBeenCalledTimes(0); }); + describe('optional segments', function () { + it('omits a segment when any referenced payload value is absent', function () { + expect( + applyLabel({ + label: 'Values: [[{marker.data.first}/{marker.data.second}]]none', + schemaFields: [ + { key: 'first', label: 'First', format: 'string' }, + { key: 'second', label: 'Second', format: 'string' }, + ], + payload: { first: 'one' }, + }) + ).toEqual('Values: none'); + expect(console.error).toHaveBeenCalledTimes(0); + }); + + it('treats zero as a present payload value', function () { + expect( + applyLabel({ + label: '[[Count: {marker.data.count}]]', + schemaFields: [{ key: 'count', label: 'Count', format: 'integer' }], + payload: { count: 0 }, + }) + ).toEqual('Count: 0'); + expect(console.error).toHaveBeenCalledTimes(0); + }); + + it('preserves double brackets without a payload reference', function () { + expect( + applyLabel({ + label: 'Literal [[{marker.name}]]', + schemaFields: [], + payload: {}, + }) + ).toEqual('Literal [[TestDefinedMarker]]'); + expect(console.error).toHaveBeenCalledTimes(0); + }); + }); + describe('ternary expressions', function () { it('returns the truthy string when the field is truthy', function () { expect( From a483f6d208b7a320da20703a3e62dd6eb9248d00 Mon Sep 17 00:00:00 2001 From: fatadel Date: Thu, 3 Sep 2026 14:07:53 +0200 Subject: [PATCH 2/2] Move FileIO table labels into marker schemas Replace the hardcoded `data.type` branch in the generic label fallback with a template on the FileIO schema. --- docs-developer/CHANGELOG-formats.md | 4 +++ src/app-logic/constants.ts | 2 +- src/profile-logic/marker-schema.ts | 35 +++++++----------- src/profile-logic/process-profile.ts | 9 +++-- .../processed-profile-versioning.ts | 7 ++++ src/test/fixtures/profiles/marker-schema.ts | 2 ++ .../__snapshots__/profiler-edit.test.ts.snap | 8 ++--- .../__snapshots__/profile-view.test.ts.snap | 3 +- .../profile-conversion.test.ts.snap | 36 +++++++++---------- .../profile-upgrading.test.ts.snap | 11 +++--- src/test/unit/marker-schema.test.ts | 35 ++++++++++++++++++ src/test/unit/process-profile.test.ts | 27 ++++++++++++++ 12 files changed, 127 insertions(+), 52 deletions(-) diff --git a/docs-developer/CHANGELOG-formats.md b/docs-developer/CHANGELOG-formats.md index dcbcb8f484..e36f59d9ca 100644 --- a/docs-developer/CHANGELOG-formats.md +++ b/docs-developer/CHANGELOG-formats.md @@ -6,6 +6,10 @@ Note that this is not an exhaustive list. Processed profile format upgraders can ## Processed profile format +### Version 72 + +FileIO marker schemas now have a `tableLabel`. Marker label templates can wrap optional segments in `[[` and `]]`; an optional segment is omitted when any payload field it references is absent or empty. + ### Version 71 The frame table (`profile.shared.frameTable`) representation changed in such a way that all its columns can now be typed arrays when using [JsonSlabs](https://github.com/mstange/json-slabs/) profiles. diff --git a/src/app-logic/constants.ts b/src/app-logic/constants.ts index e0f67bd2ff..034f51bdc5 100644 --- a/src/app-logic/constants.ts +++ b/src/app-logic/constants.ts @@ -12,7 +12,7 @@ export const GECKO_PROFILE_VERSION = 36; // The current version of the "processed" profile format. // Please don't forget to update the processed profile format changelog in // `docs-developer/CHANGELOG-formats.md`. -export const PROCESSED_PROFILE_VERSION = 71; +export const PROCESSED_PROFILE_VERSION = 72; // The following are the margin sizes for the left and right of the timeline. Independent // components need to share these values. diff --git a/src/profile-logic/marker-schema.ts b/src/profile-logic/marker-schema.ts index 97c5afb27b..e1edca29a7 100644 --- a/src/profile-logic/marker-schema.ts +++ b/src/profile-logic/marker-schema.ts @@ -117,6 +117,18 @@ const OPTIONAL_SEGMENT_RE = /\[\[([\s\S]*?)\]\]/; const OPTIONAL_SEGMENT_PAYLOAD_KEY_RE = /\{\s*marker\.data\.([^.{}\s?]+)(?=\s*(?:\}|\?))/g; +export const FILE_IO_TABLE_LABEL = + '[[({marker.data.source}) ]]{marker.data.operation}[[ — {marker.data.filename}]]'; + +export function addFileIoTableLabel(schema: { + name: string; + tableLabel?: string; +}): void { + if (schema.name === 'FileIO' && schema.tableLabel === undefined) { + schema.tableLabel = FILE_IO_TABLE_LABEL; + } +} + /** * Marker schema can create a dynamic tooltip label. For instance a schema with * a `tooltipLabel` field of "Event at {marker.data.url}" would create a label based @@ -347,28 +359,7 @@ const fallbacks: Record string> = { chartLabel: (_marker) => '', - tableLabel: (marker: Marker) => { - let description = ''; - - if (marker.data) { - const data = marker.data; - switch (data.type) { - case 'FileIO': - if (data.source) { - description = `(${data.source}) `; - } - description += data.operation; - if (data.filename) { - description = data.operation - ? `${description} — ${data.filename}` - : data.filename; - } - break; - default: - } - } - return description; - }, + tableLabel: (_marker) => '', copyLabel: (marker) => marker.name, }; diff --git a/src/profile-logic/process-profile.ts b/src/profile-logic/process-profile.ts index 8be48440cb..adfa4002c1 100644 --- a/src/profile-logic/process-profile.ts +++ b/src/profile-logic/process-profile.ts @@ -58,7 +58,10 @@ import { toFloat64Array, toFloat64ArraySetNullToZero, } from '../utils/typed-arrays'; -import { computeStringIndexMarkerFieldsByDataType } from '../profile-logic/marker-schema'; +import { + addFileIoTableLabel, + computeStringIndexMarkerFieldsByDataType, +} from '../profile-logic/marker-schema'; import { convertJsTracerToThread } from '../profile-logic/js-tracer'; import type { StringTable } from '../utils/string-table'; @@ -1722,7 +1725,7 @@ function _convertGeckoMarkerSchema( description = staticFields[staticDescriptionFieldIndex].value; } - return { + const processedMarkerSchema = { name, tooltipLabel, tableLabel, @@ -1734,6 +1737,8 @@ function _convertGeckoMarkerSchema( colorField, isStackBased, }; + addFileIoTableLabel(processedMarkerSchema); + return processedMarkerSchema; } /** diff --git a/src/profile-logic/processed-profile-versioning.ts b/src/profile-logic/processed-profile-versioning.ts index c009bd052d..9e83b8a82f 100644 --- a/src/profile-logic/processed-profile-versioning.ts +++ b/src/profile-logic/processed-profile-versioning.ts @@ -19,6 +19,7 @@ import { StringTable } from '../utils/string-table'; import { timeCode } from '../utils/time-code'; import { PROCESSED_PROFILE_VERSION } from '../app-logic/constants'; import { ProfileVersionError } from './errors'; +import { addFileIoTableLabel } from './marker-schema'; import type { Profile } from 'firefox-profiler/types'; export type ProfileUpgradeInfo = { @@ -3433,6 +3434,12 @@ const _upgraders: { frameTable.address = new Uint32Array(frameTable.address); } }, + [72]: (profile: any) => { + // Ensure FileIO marker schemas provide their schema-driven table label. + for (const schema of profile.meta.markerSchema ?? []) { + addFileIoTableLabel(schema); + } + }, // If you add a new upgrader here, please document the change in // `docs-developer/CHANGELOG-formats.md`. }; diff --git a/src/test/fixtures/profiles/marker-schema.ts b/src/test/fixtures/profiles/marker-schema.ts index 00dc94843b..5b66b54e22 100644 --- a/src/test/fixtures/profiles/marker-schema.ts +++ b/src/test/fixtures/profiles/marker-schema.ts @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import type { MarkerSchema } from 'firefox-profiler/types'; +import { FILE_IO_TABLE_LABEL } from '../../../profile-logic/marker-schema'; export const markerSchemaForTests: MarkerSchema[] = [ { @@ -27,6 +28,7 @@ export const markerSchemaForTests: MarkerSchema[] = [ }, { name: 'FileIO', + tableLabel: FILE_IO_TABLE_LABEL, display: ['marker-chart', 'marker-table'], fields: [ { diff --git a/src/test/integration/profiler-edit/__snapshots__/profiler-edit.test.ts.snap b/src/test/integration/profiler-edit/__snapshots__/profiler-edit.test.ts.snap index 27af272e13..cfec2157bc 100644 --- a/src/test/integration/profiler-edit/__snapshots__/profiler-edit.test.ts.snap +++ b/src/test/integration/profiler-edit/__snapshots__/profiler-edit.test.ts.snap @@ -87,7 +87,7 @@ Object { "markerSchema": Array [], "oscpu": "macOS 14.6.1", "pausedRanges": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "a.out", "sampleUnits": Object { @@ -1488,7 +1488,7 @@ Object { "markerSchema": Array [], "oscpu": "macOS 14.6.1", "pausedRanges": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "a.out", "sampleUnits": Object { @@ -2889,7 +2889,7 @@ Object { "markerSchema": Array [], "oscpu": "macOS 14.6.1", "pausedRanges": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "a.out", "sampleUnits": Object { @@ -4290,7 +4290,7 @@ Object { "markerSchema": Array [], "oscpu": "macOS 14.6.1", "pausedRanges": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "a.out", "sampleUnits": Object { diff --git a/src/test/store/__snapshots__/profile-view.test.ts.snap b/src/test/store/__snapshots__/profile-view.test.ts.snap index 92fd2e39d8..cfce119151 100644 --- a/src/test/store/__snapshots__/profile-view.test.ts.snap +++ b/src/test/store/__snapshots__/profile-view.test.ts.snap @@ -140,6 +140,7 @@ Object { }, ], "name": "FileIO", + "tableLabel": "[[({marker.data.source}) ]]{marker.data.operation}[[ — {marker.data.filename}]]", }, Object { "display": Array [ @@ -428,7 +429,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "Firefox", "sourceURL": "", diff --git a/src/test/unit/__snapshots__/profile-conversion.test.ts.snap b/src/test/unit/__snapshots__/profile-conversion.test.ts.snap index 46f5bf9b8e..3bffbb2edf 100644 --- a/src/test/unit/__snapshots__/profile-conversion.test.ts.snap +++ b/src/test/unit/__snapshots__/profile-conversion.test.ts.snap @@ -42,7 +42,7 @@ Object { "RefreshDriverTick", "Network", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "ART Trace (Android)", "symbolicated": true, "version": 36, @@ -1022,7 +1022,7 @@ Object { "RefreshDriverTick", "Network", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "ART Trace (Android)", "symbolicated": true, "version": 36, @@ -2305,7 +2305,7 @@ Object { "markerSchemaNames": Array [ "EventDispatch", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Chrome Trace", "symbolicated": true, "version": 36, @@ -2697,7 +2697,7 @@ Object { "markerSchemaNames": Array [ "EventDispatch", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Chrome Trace", "symbolicated": true, "version": 36, @@ -3086,7 +3086,7 @@ Object { "markerSchemaNames": Array [ "EventDispatch", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Chrome Trace", "symbolicated": true, "version": 36, @@ -3187,7 +3187,7 @@ Object { "markerSchemaNames": Array [ "EventDispatch", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Chrome Trace", "symbolicated": true, "version": 36, @@ -3540,7 +3540,7 @@ Object { "markerSchemaNames": Array [ "EventDispatch", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Chrome Trace", "symbolicated": true, "version": 36, @@ -3605,7 +3605,7 @@ Object { "markerSchemaNames": Array [ "EventDispatch", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Chrome Trace", "symbolicated": true, "version": 36, @@ -3759,7 +3759,7 @@ Object { "markerSchemaNames": Array [ "EventDispatch", ], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Chrome Trace", "symbolicated": true, "version": 36, @@ -3817,7 +3817,7 @@ Object { "importedFrom": undefined, "interval": 1, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Firefox", "symbolicated": true, "version": 36, @@ -4207,7 +4207,7 @@ Object { "importedFrom": undefined, "interval": 1, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Firefox", "symbolicated": true, "version": 36, @@ -4265,7 +4265,7 @@ Object { "importedFrom": undefined, "interval": 1, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Firefox", "symbolicated": true, "version": 36, @@ -4323,7 +4323,7 @@ Object { "importedFrom": undefined, "interval": 1, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Firefox", "symbolicated": true, "version": 36, @@ -4643,7 +4643,7 @@ Object { "importedFrom": "Simpleperf", "interval": 0, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "com.example.sampleapplication", "symbolicated": undefined, "version": 30, @@ -5019,7 +5019,7 @@ Object { "importedFrom": "Simpleperf", "interval": 0, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "com.example.sampleapplication", "symbolicated": undefined, "version": 30, @@ -5319,7 +5319,7 @@ Object { "importedFrom": "dhat", "interval": 1, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "target/debug/examples/work_log (dhat)", "symbolicated": true, "version": 36, @@ -5452,7 +5452,7 @@ Object { "importedFrom": undefined, "interval": 1, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Flamegraph", "symbolicated": true, "version": 36, @@ -5510,7 +5510,7 @@ Object { "importedFrom": undefined, "interval": 1, "markerSchemaNames": Array [], - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "product": "Flamegraph", "symbolicated": true, "version": 36, diff --git a/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap b/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap index 4d039c9117..4cfec9be94 100644 --- a/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap +++ b/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap @@ -40,7 +40,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "Firefox", "sampleUnits": undefined, @@ -7554,6 +7554,7 @@ Object { }, ], "name": "FileIO", + "tableLabel": "[[({marker.data.source}) ]]{marker.data.operation}[[ — {marker.data.filename}]]", }, Object { "display": Array [ @@ -7834,7 +7835,7 @@ Object { "misc": "rv:48.0", "oscpu": "Intel Mac OS X 10.11", "platform": "Macintosh", - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "Firefox", "stackwalk": 1, @@ -8949,6 +8950,7 @@ Object { }, ], "name": "FileIO", + "tableLabel": "[[({marker.data.source}) ]]{marker.data.operation}[[ — {marker.data.filename}]]", }, Object { "display": Array [ @@ -9229,7 +9231,7 @@ Object { "misc": "rv:48.0", "oscpu": "Intel Mac OS X 10.11", "platform": "Macintosh", - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "Firefox", "stackwalk": 1, @@ -10514,6 +10516,7 @@ Object { }, ], "name": "FileIO", + "tableLabel": "[[({marker.data.source}) ]]{marker.data.operation}[[ — {marker.data.filename}]]", }, Object { "display": Array [ @@ -10794,7 +10797,7 @@ Object { "misc": "rv:48.0", "oscpu": "Intel Mac OS X 10.11", "platform": "Macintosh", - "preprocessedProfileVersion": 71, + "preprocessedProfileVersion": 72, "processType": 0, "product": "Firefox", "stackwalk": 1, diff --git a/src/test/unit/marker-schema.test.ts b/src/test/unit/marker-schema.test.ts index ad51615253..2b8858925c 100644 --- a/src/test/unit/marker-schema.test.ts +++ b/src/test/unit/marker-schema.test.ts @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { + FILE_IO_TABLE_LABEL, formatFromMarkerSchema, parseLabel, markerSchemaFrontEndOnly, @@ -173,6 +174,40 @@ describe('marker schema labels', function () { }); describe('optional segments', function () { + const fileIoFields: MarkerSchema['fields'] = [ + { key: 'operation', label: 'Operation', format: 'string' }, + { key: 'source', label: 'Source', format: 'string' }, + { key: 'filename', label: 'Filename', format: 'file-path' }, + ]; + + it('formats FileIO labels without empty optional segments', function () { + const separator = '—'; + expect( + [ + { + operation: 'create/open', + source: 'PoisonIOInterposer', + filename: '/foo/bar', + }, + { operation: 'create/open', source: '', filename: '/foo/bar' }, + { operation: 'create/open', source: 'PoisonIOInterposer' }, + { operation: 'create/open', source: '' }, + ].map((payload) => + applyLabel({ + label: FILE_IO_TABLE_LABEL, + schemaFields: fileIoFields, + payload, + }) + ) + ).toEqual([ + `(PoisonIOInterposer) create/open ${separator} /foo/bar`, + `create/open ${separator} /foo/bar`, + '(PoisonIOInterposer) create/open', + 'create/open', + ]); + expect(console.error).toHaveBeenCalledTimes(0); + }); + it('omits a segment when any referenced payload value is absent', function () { expect( applyLabel({ diff --git a/src/test/unit/process-profile.test.ts b/src/test/unit/process-profile.test.ts index 6bd72e94d1..1e56760569 100644 --- a/src/test/unit/process-profile.test.ts +++ b/src/test/unit/process-profile.test.ts @@ -22,6 +22,7 @@ import { getVisualMetrics, } from '../fixtures/profiles/gecko-profile'; import { ensureExists } from '../../utils/types'; +import { FILE_IO_TABLE_LABEL } from '../../profile-logic/marker-schema'; import type { JsAllocationPayload_Gecko, NativeAllocationPayload_Gecko, @@ -1075,6 +1076,32 @@ describe('source table processing', function () { }); describe('Marker schema conversion', function () { + function getConvertedFileIoTableLabel(tableLabel?: string) { + const geckoProfile = createGeckoProfile(); + geckoProfile.meta.markerSchema.push({ + name: 'FileIO', + tableLabel, + display: ['marker-chart', 'marker-table'], + data: [], + }); + + const processedProfile = processGeckoProfile(geckoProfile); + const fileIoSchema = processedProfile.meta.markerSchema.find( + (schema) => schema.name === 'FileIO' + ); + + return fileIoSchema?.tableLabel; + } + + it('adds the FileIO table label when Gecko does not provide one', function () { + expect(getConvertedFileIoTableLabel()).toBe(FILE_IO_TABLE_LABEL); + }); + + it('preserves a FileIO table label provided by Gecko', function () { + const geckoTableLabel = 'Custom FileIO label'; + expect(getConvertedFileIoTableLabel(geckoTableLabel)).toBe(geckoTableLabel); + }); + it('should preserve optional marker schema properties', function () { const geckoProfile = createGeckoProfile();