Skip to content

Commit f662766

Browse files
WIP: New test generator
1 parent 20c34ca commit f662766

8 files changed

Lines changed: 394 additions & 12 deletions

File tree

.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
"editor.formatOnSave": false
1212
},
1313
"cSpell.words": [
14+
"arrayextractor",
1415
"Arrayify",
16+
"arrayvalues",
1517
"bendcase",
1618
"bendelse",
1719
"bendfor",
@@ -22,6 +24,7 @@
2224
"bubbleanimation",
2325
"coeff",
2426
"coordsys",
27+
"datamanager",
2528
"deeplearningkerasmodel",
2629
"deeplearninglabelraster",
2730
"deeplearningobjectdetectionraster",
@@ -98,6 +101,7 @@
98101
"IMCP",
99102
"INCREMENTERS",
100103
"INDGEN",
104+
"inputparameters",
101105
"ioerror",
102106
"Keras",
103107
"lineanimation",
@@ -116,12 +120,14 @@
116120
"onigurama",
117121
"ONNX",
118122
"orthophoto",
123+
"outputparameters",
119124
"paren",
120125
"pointcloud",
121126
"pointcloudspatialref",
122127
"populators",
123128
"powerlines",
124129
"PROJCS",
130+
"propertyextractor",
125131
"pseudorasterspatialref",
126132
"Recurser",
127133
"Recursor",

apps/test-tokenizer/src/playground.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { PLAYGROUND_CODE } from './playground-code';
1717
/**
1818
* Nicely format any object as JSON so that it matches the default prettier formatting
1919
*/
20-
function Stringify(object: any): string {
20+
async function Stringify(object: any): Promise<string> {
2121
return prettier.format(JSON.stringify(object, null, 2), { parser: 'json' });
2222
}
2323

@@ -42,7 +42,7 @@ export async function Playground() {
4242
/**
4343
* Parse our code to get all the gory details for what we have
4444
*/
45-
let parsed: IParsed;
45+
let parsed!: IParsed;
4646
const t1 = TimeIt(() => {
4747
parsed = Parser(PLAYGROUND_CODE, new CancellationToken(), {
4848
cleanup: false,
@@ -123,35 +123,35 @@ export async function Playground() {
123123
);
124124
writeFileSync(
125125
join(process.cwd(), 'parse-test', 'tokens.json'),
126-
Stringify(parsed.tokens),
126+
await Stringify(parsed.tokens),
127127
);
128128
writeFileSync(
129129
join(process.cwd(), 'parse-test', 'textmate.json'),
130-
Stringify(tmParsed),
130+
await Stringify(tmParsed),
131131
);
132132
writeFileSync(
133133
join(process.cwd(), 'parse-test', 'tree.json'),
134-
Stringify(parsed.tree),
134+
await Stringify(parsed.tree),
135135
);
136136
writeFileSync(
137137
join(process.cwd(), 'parse-test', 'tree-assembled.json'),
138-
Stringify(formattedTokenized.tree),
138+
await Stringify(formattedTokenized.tree),
139139
);
140140
writeFileSync(
141141
join(process.cwd(), 'parse-test', 'problems.json'),
142-
Stringify(parsed.parseProblems),
142+
await Stringify(parsed.parseProblems),
143143
);
144144
writeFileSync(
145145
join(process.cwd(), 'parse-test', 'global.json'),
146-
Stringify(parsed.global),
146+
await Stringify(parsed.global),
147147
);
148148
writeFileSync(
149149
join(process.cwd(), 'parse-test', 'local.json'),
150-
Stringify(parsed.local),
150+
await Stringify(parsed.local),
151151
);
152152
writeFileSync(
153153
join(process.cwd(), 'parse-test', 'compile.json'),
154-
Stringify(parsed.compile),
154+
await Stringify(parsed.compile),
155155
);
156156
writeFileSync(
157157
join(process.cwd(), 'parse-test', 'formatted.pro'),

apps/test-tokenizer/src/test-maker/generate-automated-tests.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { TestsForAssembler } from './makers/tests-for-assembler';
66
import { TestsForAutoComplete } from './makers/tests-for-auto-complete';
77
import { TestForAutoFixing } from './makers/tests-for-auto-fixing';
88
import { TestsForConfigFileResolving } from './makers/tests-for-config-file-resolving';
9+
import { TestsForENVIModeler } from './makers/tests-for-envi-modeler';
910
import { TestsForGlobalProblems } from './makers/tests-for-global-problems';
1011
import { TestsForHoverHelp } from './makers/tests-for-hover-help';
1112
import { TestsForLocalGlobalScopeAndCompile } from './makers/tests-for-local-global-scope-compile-and-types';
@@ -23,6 +24,7 @@ import { TestsForTokenizer } from './makers/tests-for-tokenizer';
2324
import { AUTO_ASSEMBLER_TESTS } from './tests/auto-assembler-tests.interface';
2425
import { AUTO_AUTO_COMPLETE_TESTS } from './tests/auto-auto-complete-tests.interface';
2526
import { AUTO_CONFIG_FILE_RESOLVING } from './tests/auto-config-file-resolving-tests.interface';
27+
import { AUTO_ENVI_MODELER_TESTS } from './tests/auto-envi-modeler-tests.interface';
2628
import { AUTO_GLOBAL_PROBLEM_TESTS } from './tests/auto-global-problem-tests.interface';
2729
import { AUTO_HOVER_HELP_TESTS } from './tests/auto-hover-help-tests.interface';
2830
import { AUTO_LOCAL_GLOBAL_SCOPE_COMPILE_AND_TYPES_TESTS } from './tests/auto-local-global-scope-compile-and-types-tests.interface';
@@ -33,7 +35,7 @@ import { AUTO_SEMANTIC_TOKEN_TESTS } from './tests/auto-semantic-token-tests.int
3335
import { AUTO_POST_PROCESSOR_TESTS } from './tests/auto-syntax-post-processor-tests.interface';
3436
import { AUTO_SYNTAX_TESTS } from './tests/auto-syntax-validator-tests.interface';
3537
import { AUTO_TASK_ASSEMBLER_TESTS } from './tests/auto-task-assembler-tests.interface';
36-
import { AUTO_TASK_GENERATION_TESTS } from './tests/auto-task-generationtests.interface';
38+
import { AUTO_TASK_GENERATION_TESTS } from './tests/auto-task-generation-tests.interface';
3739
import { AUTO_TASK_PARSING_TESTS } from './tests/auto-task-parsing-tests.interface';
3840
import { AUTO_TOKEN_DEFINITION_TESTS } from './tests/auto-token-definition-tests.interface';
3941
import { AUTO_TOKEN_TESTS } from './tests/auto-token-tests.interface';
@@ -430,4 +432,25 @@ export async function GenerateAutomatedTests() {
430432
);
431433
}
432434
console.log();
435+
436+
// specify the output folder
437+
const outDirENVIModeler = join(
438+
process.cwd(),
439+
'libs/tests/envi-modeler/src/lib',
440+
);
441+
442+
// clean test directory
443+
CleanTestDir(outDirENVIModeler);
444+
445+
// process each test
446+
console.log('Generating tests for ENVI Modeler');
447+
for (let i = 0; i < AUTO_ENVI_MODELER_TESTS.length; i++) {
448+
console.log(` Suite (${i}): ${AUTO_ENVI_MODELER_TESTS[i].suiteName}`);
449+
await TestsForENVIModeler(
450+
AUTO_ENVI_MODELER_TESTS[i].suiteName,
451+
AUTO_ENVI_MODELER_TESTS[i].tests,
452+
join(outDirENVIModeler, AUTO_ENVI_MODELER_TESTS[i].fileName),
453+
);
454+
}
455+
console.log();
433456
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import {
2+
CreateENVIModelerWorkflow,
3+
ValidateENVIModelerNodes,
4+
} from '@idl/envi/modeler';
5+
import { LogManager } from '@idl/logger';
6+
import { MCPTaskRegistry } from '@idl/mcp/tasks';
7+
import { IDLIndex } from '@idl/parsing/index';
8+
import { GLOBAL_TOKEN_TYPES } from '@idl/types/idl-data-types';
9+
import { DEFAULT_IDL_EXTENSION_CONFIG } from '@idl/vscode/extension-config';
10+
import { writeFileSync } from 'fs';
11+
import { join } from 'path';
12+
13+
import { IENVIModelerTest } from '../tests.interface';
14+
15+
/**
16+
* Generates tests for ENVI Modeler validation and workflow creation.
17+
*
18+
* At generation time this bootstraps a real MCPTaskRegistry (same pattern as
19+
* the sandbox) to capture expected errors and workflow output as inline
20+
* snapshots. Each generated spec file re-creates the same setup so that
21+
* tests are self-contained and exercise real task registration.
22+
*/
23+
export async function TestsForENVIModeler(
24+
name: string,
25+
tests: IENVIModelerTest[],
26+
uri = join(process.cwd(), 'tokens.ts'),
27+
) {
28+
// track our strings
29+
const strings: string[] = [];
30+
31+
// --- imports ---
32+
strings.push(
33+
`import { CreateENVIModelerWorkflow, ValidateENVIModelerNodes } from '@idl/envi/modeler';`,
34+
);
35+
strings.push(`import { LogManager } from '@idl/logger';`);
36+
strings.push(`import { MCPTaskRegistry } from '@idl/mcp/tasks';`);
37+
strings.push(
38+
`import { IDL_INDEX_OPTIONS, IDLIndex } from '@idl/parsing/index';`,
39+
);
40+
strings.push(
41+
`import { GLOBAL_TOKEN_TYPES } from '@idl/types/idl-data-types';`,
42+
);
43+
strings.push(
44+
`import { ENVIModelerEdge, ENVIModelerNode } from '@idl/types/mcp';`,
45+
);
46+
strings.push(
47+
`import { DEFAULT_IDL_EXTENSION_CONFIG } from '@idl/vscode/extension-config';`,
48+
);
49+
strings.push(``);
50+
strings.push(`IDL_INDEX_OPTIONS.IS_TEST = true;`);
51+
strings.push(``);
52+
53+
// --- module-level registry setup (once per spec file, outside describe) ---
54+
strings.push(`// create log manager`);
55+
strings.push(`const logManager = new LogManager({`);
56+
strings.push(` alert: () => {`);
57+
strings.push(` // do nothing`);
58+
strings.push(` },`);
59+
strings.push(`});`);
60+
strings.push(``);
61+
strings.push(`// create index`);
62+
strings.push(`const index = new IDLIndex(logManager, 1, false);`);
63+
strings.push(``);
64+
strings.push(`// load global tokens`);
65+
strings.push(`index.loadGlobalTokens(DEFAULT_IDL_EXTENSION_CONFIG);`);
66+
strings.push(``);
67+
strings.push(`// create registry`);
68+
strings.push(`const registry = new MCPTaskRegistry(logManager);`);
69+
strings.push(``);
70+
strings.push(`// populate registry`);
71+
strings.push(`registry.registerTasksFromGlobalTokens(`);
72+
strings.push(
73+
` index.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.FUNCTION],`,
74+
);
75+
strings.push(
76+
` index.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.STRUCTURE],`,
77+
);
78+
strings.push(`);`);
79+
strings.push(``);
80+
81+
// --- bootstrap generation-time registry to capture expected outputs ---
82+
const genLogManager = new LogManager({
83+
alert: () => {
84+
// do nothing
85+
},
86+
});
87+
const genIndex = new IDLIndex(genLogManager, 1, false);
88+
genIndex.loadGlobalTokens(DEFAULT_IDL_EXTENSION_CONFIG);
89+
const genRegistry = new MCPTaskRegistry(genLogManager);
90+
genRegistry.registerTasksFromGlobalTokens(
91+
genIndex.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.FUNCTION],
92+
genIndex.globalIndex.globalTokensByTypeByName[GLOBAL_TOKEN_TYPES.STRUCTURE],
93+
);
94+
95+
// --- describe block ---
96+
strings.push(`describe(\`[auto generated] ${name}\`, () => {`);
97+
98+
for (let i = 0; i < tests.length; i++) {
99+
const test = tests[i];
100+
const testName = test.name;
101+
102+
// run validation at generation time to capture expected outputs
103+
const errors = ValidateENVIModelerNodes(
104+
test.nodes,
105+
test.edges,
106+
genRegistry,
107+
);
108+
109+
let workflow: Record<string, unknown> | undefined;
110+
if (errors.length === 0) {
111+
workflow = CreateENVIModelerWorkflow(test.nodes, test.edges, genRegistry);
112+
}
113+
114+
// serialize nodes and edges as JSON literals
115+
const nodesStr = JSON.stringify(test.nodes, null, 2);
116+
const edgesStr = JSON.stringify(test.edges, null, 2);
117+
118+
strings.push(` it(\`[auto generated] ${testName}\`, () => {`);
119+
strings.push(` // define nodes`);
120+
strings.push(` const nodes: ENVIModelerNode[] = ${nodesStr};`);
121+
strings.push(``);
122+
strings.push(` // define edges`);
123+
strings.push(` const edges: ENVIModelerEdge[] = ${edgesStr};`);
124+
strings.push(``);
125+
strings.push(` // validate nodes`);
126+
strings.push(
127+
` const errors = ValidateENVIModelerNodes(nodes, edges, registry);`,
128+
);
129+
strings.push(``);
130+
strings.push(` // define expected errors`);
131+
strings.push(
132+
` const expectedErrors: string[] = ${JSON.stringify(errors)};`,
133+
);
134+
strings.push(``);
135+
strings.push(` // verify errors`);
136+
strings.push(` expect(errors).toEqual(expectedErrors);`);
137+
138+
if (workflow !== undefined) {
139+
strings.push(``);
140+
strings.push(` // define expected workflow`);
141+
strings.push(
142+
` const expectedWorkflow = ${JSON.stringify(workflow, null, 2)} as Record<string, unknown>;`,
143+
);
144+
strings.push(``);
145+
strings.push(` // verify workflow`);
146+
strings.push(
147+
` expect(CreateENVIModelerWorkflow(nodes, edges, registry)).toEqual(expectedWorkflow);`,
148+
);
149+
}
150+
151+
strings.push(` });`);
152+
strings.push(``);
153+
}
154+
155+
strings.push(`});`);
156+
strings.push(``);
157+
158+
writeFileSync(uri, strings.join('\n'));
159+
}

apps/test-tokenizer/src/test-maker/tests.interface.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { FormatterType, IAssemblerInputOptions } from '@idl/assembling/config';
22
import { IIndexProCodeOptions } from '@idl/parsing/index';
3+
import { ENVIModelerEdge, ENVIModelerNode } from '@idl/types/envi/modeler';
34
import { Position } from 'vscode-languageserver/node';
45

56
/**
@@ -289,3 +290,23 @@ export interface IConfigTests extends IBaseAutoTest {
289290
/** Tests to generate */
290291
tests: IConfigTest[];
291292
}
293+
294+
/**
295+
* A single test case for ENVI Modeler validation and workflow creation
296+
*/
297+
export interface IENVIModelerTest {
298+
/** Edges for the workflow graph */
299+
edges: ENVIModelerEdge[];
300+
/** Name of the test */
301+
name: string;
302+
/** Nodes for the workflow graph */
303+
nodes: ENVIModelerNode[];
304+
}
305+
306+
/**
307+
* Data structure for automated ENVI Modeler tests
308+
*/
309+
export interface IAutoENVIModelerTest extends IBaseAutoTest {
310+
/** Tests to generate */
311+
tests: IENVIModelerTest[];
312+
}

0 commit comments

Comments
 (0)