Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 14 additions & 3 deletions src/schema/expressionLanguage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,27 @@ Deno.test('test expression functions', async (t) => {
})
await t.step('intersects function', () => {
const intersects = expressionFunctions.intersects
assert(intersects([1, 2, 3], [2, 3, 4]) === true)
const equal = expressionFunctions.allequal

const truthy = (a: any): boolean => !!a

assert(truthy(intersects([1, 2, 3], [2, 3, 4])))
assert(intersects([1, 2, 3], [4, 5, 6]) === false)
assert(intersects(['abc', 'def'], ['def']) === true)
assert(truthy(intersects(['abc', 'def'], ['def'])))
assert(intersects(['abc', 'def'], ['ghi']) === false)
// Just checking values, I'm not concerned about types here
// @ts-expect-error
assert(equal(intersects([1, 2, 3], [2, 3, 4]), [2, 3]))
// @ts-expect-error
assert(equal(intersects(['abc', 'def'], ['def']), ['def']))

// Promote scalars to arrays
// @ts-ignore
assert(intersects('abc', ['abc', 'def']) === true)
assert(truthy(intersects('abc', ['abc', 'def'])))
// @ts-ignore
assert(intersects('abc', ['a', 'b', 'c']) === false)
// @ts-expect-error
assert(equal(intersects('abc', ['abc', 'def']), ['abc']))
})
await t.step('match function', () => {
const match = expressionFunctions.match
Expand Down
20 changes: 18 additions & 2 deletions src/schema/expressionLanguage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,30 @@ export const expressionFunctions = {
const index = list.indexOf(item)
return index != -1 ? index : null
},
intersects: <T>(a: T[], b: T[]): boolean => {
intersects: <T>(a: T[], b: T[]): T[] | boolean => {
// Tolerate single values
if (!Array.isArray(a)) {
a = [a]
}
if (!Array.isArray(b)) {
b = [b]
}
return a.some((x) => b.includes(x))
// Construct a set from the smaller list
if (a.length < b.length) {
const tmp = a
a = b
b = tmp
}
if (b.length === 0) {
return false
}

const bSet = new Set(b)
const intersection = a.filter((x) => bSet.has(x))
if (intersection.length === 0) {
return false
}
return intersection
},
match: (target: string, regex: string): boolean => {
const re = RegExp(regex)
Expand Down
13 changes: 12 additions & 1 deletion src/tests/schema-expression-language.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const equal = <T>(a: T, b: T): boolean => {
Deno.test('validate schema expression tests', async (t) => {
const results: string[][] = []
const header = ['expression', 'desired', 'actual', 'result'].map((x) => colors.magenta(x))
const xfails = ['intersects([1], [1, 2])']
for (const test of schema.meta.expression_tests) {
await t.step(`${test.expression} evals to ${test.result}`, () => {
const context = { file: { parent: null }, dataset: { tree: null } } as unknown as BIDSContext
Expand All @@ -33,6 +34,13 @@ Deno.test('validate schema expression tests', async (t) => {
pretty_null(actual_result),
colors.green('pass'),
])
} else if (xfails.includes(test.expression)) {
results.push([
colors.cyan(test.expression),
pretty_null(test.result),
pretty_null(actual_result),
colors.yellow('xfail'),
])
} else {
results.push([
colors.cyan(test.expression),
Expand All @@ -41,7 +49,10 @@ Deno.test('validate schema expression tests', async (t) => {
colors.red('fail'),
])
}
assertEquals(actual_result, test.result)
// Don't fail on xfail
if (!xfails.includes(test.expression)) {
assertEquals(actual_result, test.result)
}
})
}
results.sort((a, b) => {
Expand Down