Skip to content

Commit

Permalink
Refactored split and OutputReference.
Browse files Browse the repository at this point in the history
Signed-off-by: dblock <[email protected]>
  • Loading branch information
dblock committed Dec 18, 2024
1 parent dcb6c69 commit f632b2a
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 68 deletions.
18 changes: 18 additions & 0 deletions tools/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,21 @@ export function write_json (file_path: string, content: any, replacer?: (this: a
export async function sleep (ms: number): Promise<void> {
await new Promise<void>((resolve) => setTimeout(resolve, ms))
}

/**
* Returns a string split using a delimiter, but only up to a certain number of times,
* returning the remainder of the string as the last element if the result.
*
* @param str a string
* @param delim delimiter
* @param count max number of splits
* @returns an array of strings
*/
export function split(str: any, delim: string, count: number = 0): string[] {
if (str === undefined) return []
const parts = str.split(delim)
if (count <= 0 || parts.length <= count) return parts
const result = parts.slice(0, count - 1)
result.push(parts.slice(count - 1).join(delim))
return result
}
57 changes: 57 additions & 0 deletions tools/src/tester/OutputReference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

import { split } from "helpers"

export class OutputReference {
chapter_id: string
output_name: string|undefined

constructor(chapter_id: string, output_name: string | undefined = undefined) {
this.chapter_id = chapter_id
this.output_name = output_name
}

/**
* Parses a string and returns a collection of output references that it may contain.
*
* @param str a string
* @returns an array of output references
*/
static parse(str: string): OutputReference[] {
const pattern = /\$\{([^}]+)\}/g
let match
var result = []
while ((match = pattern.exec(str)) !== null) {
const spl = split(match[1], '.', 2)
result.push(new OutputReference(spl[0], spl[1]))
}
return result
}

/**
* Replaces occurrences of output references.
* Takes special care of preserving the type of the reference value if the entire string is a reference.
*
* @param str a string that may contain output references
* @param callback a callback for fetching reference values
* @returns a string with output references replaced by their values
*/
static replace(str: string, callback: (chapter_id: any, variable: any) => string): any {
let full_match = str.match(/^\$\{([^}]+)\}$/)
if (full_match) {
// the entire string is a reference, preserve the type of the returned value
const spl = split(full_match[1], '.', 2)
return callback(spl[0], spl[1])
} else return str.replace(/\$\{([^}]+)\}/g, (_, k) => {
const spl = split(k, '.', 2)
return callback(spl[0], spl[1])
})
}
}
3 changes: 2 additions & 1 deletion tools/src/tester/StoryEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { ChapterRequest, Parameter, SupplementalChapter } from './types/story.types'
import { type StoryFile, type ChapterEvaluation, Result, type StoryEvaluation, OutputReference } from './types/eval.types'
import { type StoryFile, type ChapterEvaluation, Result, type StoryEvaluation } from './types/eval.types'
import type ChapterEvaluator from './ChapterEvaluator'
import { overall_result } from './helpers'
import { StoryOutputs } from './StoryOutputs'
Expand All @@ -17,6 +17,7 @@ import { ChapterOutput } from './ChapterOutput'
import * as semver from '../_utils/semver'
import _ from 'lodash'
import { ParsedChapter, ParsedStory } from './types/parsed_story.types'
import { OutputReference } from './OutputReference'

export default class StoryEvaluator {
private readonly _chapter_evaluator: ChapterEvaluator
Expand Down
43 changes: 0 additions & 43 deletions tools/src/tester/types/eval.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,46 +83,3 @@ export enum Result {
SKIPPED = 'SKIPPED',
ERROR = 'ERROR',
}

export class OutputReference {
chapter_id: string
output_name: string

private constructor(chapter_id: string, output_name: string) {
this.chapter_id = chapter_id
this.output_name = output_name
}

static parse(str: string): OutputReference[] {
const pattern = /\$\{([^}]+)\}/g
let match
var result = []
while ((match = pattern.exec(str)) !== null) {
const spl = this.#split(match[1], '.', 2)
result.push(new OutputReference(spl[0], spl[1]))
}
return result
}

static replace(str: string, callback: (chapter_id: any, variable: any) => string): any {
// preserve type if 1 value is returned
let full_match = str.match(/^\$\{([^}]+)\}$/)
if (full_match) {
const spl = this.#split(full_match[1], '.', 2)
return callback(spl[0], spl[1])
} else return str.replace(/\$\{([^}]+)\}/g, (_, k) => {
const spl = this.#split(k, '.', 2)
return callback(spl[0], spl[1])
});
}

static #split(str: any, delim: string, count: number): string[] {
if (str === undefined) return [str]
if (count <= 0) return [str]
const parts = str.split(delim)
if (parts.length <= count) return parts
const result = parts.slice(0, count - 1)
result.push(parts.slice(count - 1).join(delim))
return result
}
}
25 changes: 24 additions & 1 deletion tools/tests/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import _ from 'lodash'
import { delete_matching_keys, find_refs, sort_array_by_keys, to_json, to_ndjson } from '../src/helpers'
import { delete_matching_keys, find_refs, sort_array_by_keys, to_json, to_ndjson, split } from '../src/helpers'

describe('helpers', () => {
describe('sort_array_by_keys', () => {
Expand Down Expand Up @@ -195,4 +195,27 @@ describe('helpers', () => {
})).toEqual(new Set(['#1', '#2', '#3', '#dup', '#/schemas/schema1', '#/schemas/schema2']))
})
})

describe('split', () => {
test('undefined', () => {
expect(split(undefined, '.')).toEqual([])
})

test('one element', () => {
expect(split('str', '.')).toEqual(['str'])
expect(split('str', '.', -1)).toEqual(['str'])
expect(split('str', '.', 0)).toEqual(['str'])
expect(split('str', '.', 10)).toEqual(['str'])
})

test('multiple elements', () => {
expect(split('x.y.z', '.')).toEqual(['x', 'y', 'z'])
expect(split('x.y.z', '.', -1)).toEqual(['x', 'y', 'z'])
expect(split('x.y.z', '.', 0)).toEqual(['x', 'y', 'z'])
expect(split('x.y.z', '.', 1)).toEqual(['x.y.z'])
expect(split('x.y.z', '.', 2)).toEqual(['x', 'y.z'])
expect(split('x.y.z', '.', 3)).toEqual(['x', 'y', 'z'])
expect(split('x.y.z', '.', 4)).toEqual(['x', 'y', 'z'])
})
})
})
40 changes: 40 additions & 0 deletions tools/tests/tester/OutputReference.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

import { OutputReference } from "tester/OutputReference";

describe('OutputReference', () => {
let f = (id: any, k: any): string => `[${id}:${k}]`

describe('parse', () => {
it('replaces', () => {
expect(OutputReference.parse('string')).toEqual([])
expect(OutputReference.parse('${k.v}')).toEqual([new OutputReference('k', 'v')])
expect(OutputReference.parse('${k.value}')).toEqual([new OutputReference('k', 'value')])
expect(OutputReference.parse('${k.v.m}')).toEqual([new OutputReference('k', 'v.m')])
expect(OutputReference.parse('A reference to ${k.v.m} and ${x} and ${x.y}.')).toEqual([
new OutputReference('k', 'v.m'),
new OutputReference('x'),
new OutputReference('x', 'y')
])
})
})

describe('replace', () => {
it('replaces', () => {
expect(OutputReference.replace('string', f)).toEqual('string')
expect(OutputReference.replace('${k.v}', f)).toEqual('[k:v]')
expect(OutputReference.replace('${k.value}', f)).toEqual('[k:value]')
expect(OutputReference.replace('${k.v.m}', f)).toEqual('[k:v.m]')
expect(OutputReference.replace('A reference to ${k.v.m} and ${x} and ${x.y}.', f)).toEqual(
'A reference to [k:v.m] and [x:undefined] and [x:y].'
)
})
})
});
23 changes: 0 additions & 23 deletions tools/tests/types/eval.types.test.ts

This file was deleted.

0 comments on commit f632b2a

Please sign in to comment.