Skip to content

Commit 41406da

Browse files
committed
Only run test when a requirement exists
1 parent 6b3410d commit 41406da

File tree

4 files changed

+43
-24
lines changed

4 files changed

+43
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
88

99
- Learned Go's `fallthrough` keyword
1010
- Learned an option to draw flat-switches (where all cases are direct descendants of the switch head)
11+
- Added utilities for basic reachability testing
1112

1213
## [0.0.2] - 2024-09-06
1314

src/control-flow/cfg.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ interface Case {
127127

128128
interface BuilderOptions {
129129
flatSwitch?: boolean;
130-
markerPattern?:RegExp;
130+
markerPattern?: RegExp;
131131
}
132132

133133
export class CFGBuilder {
@@ -231,7 +231,7 @@ export class CFGBuilder {
231231
}
232232
}
233233
private processComment(commentSyntax: Parser.SyntaxNode): BasicBlock {
234-
// We only ever ger here when marker comments are enabled,
234+
// We only ever ger here when marker comments are enabled,
235235
// and only for marker comments as the rest are filtered out.
236236
const commentNode = this.addNode("MARKER_COMMENT", commentSyntax.text);
237237
if (this.markerPattern) {
@@ -395,15 +395,15 @@ export class CFGBuilder {
395395
const blockHandler = new BlockHandler();
396396

397397
// Ignore comments
398-
const codeStatements = statements.filter(
399-
(syntax) => {
400-
if (syntax.type !== "comment") {
401-
return true;
402-
}
403-
404-
return this.markerPattern && Boolean(syntax.text.match(this.markerPattern));
398+
const codeStatements = statements.filter((syntax) => {
399+
if (syntax.type !== "comment") {
400+
return true;
405401
}
406-
);
402+
403+
return (
404+
this.markerPattern && Boolean(syntax.text.match(this.markerPattern))
405+
);
406+
});
407407

408408
if (codeStatements.length === 0) {
409409
const emptyNode = this.addNode("EMPTY", "empty block");

src/test/nodecount.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ label:
4949
}
5050

5151
/*
52-
reaches: [["a", "b"]]
52+
nodes: 1,
53+
reaches: [
54+
["a", "b"]
55+
]
5356
*/
5457
func trivialReachability() {
5558
// CFG: a

src/test/nodecount.test.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,8 @@ function parseComment(text: string): Requirements {
3434
const jsonContent = text
3535
.slice(2, -2)
3636
.trim()
37-
.replaceAll(/^/gm, '"')
38-
.replaceAll(/:/gm, '":')
39-
.replaceAll(/$/gm, ",")
40-
.replaceAll(/,$/gm, "");
37+
.replaceAll(/^(?=\w)/gm, '"')
38+
.replaceAll(/:/gm, '":');
4139
return JSON.parse(`{${jsonContent}}`);
4240
}
4341

@@ -89,21 +87,26 @@ function buildSimpleCFG(functionNode: Parser.SyntaxNode): CFG {
8987
function buildMarkerCFG(functionNode: Parser.SyntaxNode): CFG {
9088
const builder = new CFGBuilder({ markerPattern });
9189
return builder.buildCFG(functionNode);
92-
9390
}
9491

95-
function pathExists(graph: MultiDirectedGraph, source: string, target: string): boolean {
92+
function pathExists(
93+
graph: MultiDirectedGraph,
94+
source: string,
95+
target: string,
96+
): boolean {
9697
let foundTarget = false;
9798
bfsFromNode(graph, source, (node) => {
9899
foundTarget ||= node == target;
99100
return foundTarget;
100-
})
101+
});
101102
return foundTarget;
102103
}
103104

104105
function getMarkerMap(cfg: CFG): Map<string, string> {
105106
const markerMap: Map<string, string> = new Map();
106-
cfg.graph.forEachNode((node, { markers }) => { markers?.forEach(marker => markerMap.set(marker, node)) })
107+
cfg.graph.forEachNode((node, { markers }) => {
108+
markers?.forEach((marker) => markerMap.set(marker, node));
109+
});
107110
return markerMap;
108111
}
109112

@@ -112,7 +115,15 @@ const testMap = new Map(
112115
testFunctions.map((testFunc) => [testFunc.name, testFunc]),
113116
);
114117
const testNames = [...testMap.keys()];
115-
test.each(testNames)("Node count for %s", (name) => {
118+
119+
function testsFor(reqName: string): string[] {
120+
return testNames.filter((name) => {
121+
const testFunc = testMap.get(name) as TestFunction;
122+
return Object.hasOwn(testFunc.reqs, reqName);
123+
});
124+
}
125+
126+
test.each(testsFor("nodes"))("Node count for %s", (name) => {
116127
const testFunc = testMap.get(name) as TestFunction;
117128
expect(testFunc).toBeDefined();
118129

@@ -122,7 +133,7 @@ test.each(testNames)("Node count for %s", (name) => {
122133
}
123134
});
124135

125-
test.each(testNames)("Reachability for %s", (name) => {
136+
test.each(testsFor("reaches"))("Reachability for %s", (name) => {
126137
const testFunc = testMap.get(name) as TestFunction;
127138
expect(testFunc).toBeDefined();
128139

@@ -134,8 +145,12 @@ test.each(testNames)("Reachability for %s", (name) => {
134145
if (node) {
135146
return node;
136147
}
137-
throw new Error(`No node found for marker ${marker}`)
138-
}
139-
testFunc.reqs.reaches.forEach(([source, target]) => expect(pathExists(cfg.graph, getNode(source), getNode(target))).toBe(true))
148+
throw new Error(`No node found for marker ${marker}`);
149+
};
150+
testFunc.reqs.reaches.forEach(([source, target]) =>
151+
expect(pathExists(cfg.graph, getNode(source), getNode(target))).toBe(
152+
true,
153+
),
154+
);
140155
}
141156
});

0 commit comments

Comments
 (0)