Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More test samples for dominators #12

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
10 changes: 7 additions & 3 deletions src/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ async function main() {
"--download-compilers <compilerKind...>",
`Download specified kind of supported compilers to compiler cache. Supports multiple entries.`
)
.option("--run-detectors", "Run defined detecotrs")
.option("--run-detectors", "Run defined detectors")
.option("--dump", "Dump generated DL")
.option(
"--dump-analyses <analysisName...>",
Expand Down Expand Up @@ -286,15 +286,17 @@ async function main() {
const units = reader.read(result.data);
const infer = new InferType(compilerVersion);

const datalog = buildDatalog(units, infer);

if (options.dump) {
const datalog = buildDatalog(units, infer);

console.log(datalog);

return;
}

if (options.runDetectors) {
const issues = await detect(units, reader.context, infer);

console.log(issues);

return;
Expand All @@ -308,13 +310,15 @@ async function main() {
options.dumpAnalyses
)) as SouffleCSVInstance;
const output = instance.results();

instance.release();

for (const analysis of options.dumpAnalyses) {
const facts = output.get(analysis);

console.log(analysis, facts ? facts.map((f) => f.toCSVRow()) : facts);
}

return;
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/lib/detector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface Issue {
}

function loadDetectorTemplate(jsonPath: string): DetectorTemplate {
return fse.readJSONSync(jsonPath) as DetectorTemplate;
return fse.readJSONSync(jsonPath);
}

export function loadDetectors(): DetectorTemplate[] {
Expand Down Expand Up @@ -135,10 +135,12 @@ function fmt(template: string, subst: SubstMap, ctx: sol.ASTContext): string {
const fieldVal = getField(node, field);

template = template.replace(fmtHoleRx, sol.pp(fieldVal));

continue;
}

m1 = pattern.match(fmtId);

if (m1 !== null) {
const argName = m1[1];
const val = subst.get(argName);
Expand All @@ -147,6 +149,7 @@ function fmt(template: string, subst: SubstMap, ctx: sol.ASTContext): string {

sol.assert(!(typeof val === "object"), ``);
template = template.replace(fmtHoleRx, sol.pp(val));

continue;
}

Expand All @@ -169,11 +172,14 @@ export function getIssues(output: OutputRelations, ctx: sol.ASTContext): Issue[]

// Parse results
for (const [name, facts] of output) {
if (!detectorMap.has(name)) {
const entry = detectorMap.get(name);

if (entry === undefined) {
continue;
}

const [args, template] = detectorMap.get(name) as [SignatureArgs, DetectorTemplate];
const [args, template] = entry;

for (const relnVals of facts) {
const subst = makeSubst(args, relnVals);

Expand Down
4 changes: 4 additions & 0 deletions src/lib/souffle/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export abstract class SouffleInstance {

async run(outputRelations: string[]): Promise<void> {
const sysTmpDir = os.tmpdir();

this.tmpDir = await fse.mkdtempSync(join(sysTmpDir, "sol-datalog-"));

this.inputFile = join(this.tmpDir, "input.dl");
Expand Down Expand Up @@ -103,6 +104,7 @@ export abstract class SouffleInstance {

release(): void {
fse.removeSync(this.inputFile);

for (const f of this.outputFiles) {
fse.removeSync(f);
}
Expand Down Expand Up @@ -130,6 +132,7 @@ export class BaseSouffleCSVInstance extends SouffleInstance {

results(): OutputRelations {
sol.assert(this.success, `Instance not run yet`);

if (!this._results) {
this._results = this.readProducedCsvFiles();
}
Expand Down Expand Up @@ -311,6 +314,7 @@ export class SouffleSQLiteInstance extends SouffleInstance implements SouffleSQL

async relationFacts(name: string): Promise<Fact[]> {
const r = this._relations.get(name);

sol.assert(r !== undefined, `Uknown relation ${name}`);

const rawRes = await this.db.all(`SELECT * from ${name}`);
Expand Down
2 changes: 2 additions & 0 deletions src/lib/souffle/souffle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export async function analyze(
: new SouffleSQLiteInstance(datalog, soDir);

await instance.run(outputRelations);

return instance;
}

Expand All @@ -77,6 +78,7 @@ export async function detect(

const instance = (await analyze(units, infer, "csv", outputRelations)) as SouffleCSVInstance;
const outputs = instance.results();

instance.release();

const res = getIssues(outputs, context);
Expand Down
25 changes: 14 additions & 11 deletions test/analyses.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,26 @@ describe("Analyses", () => {
describe(sample, () => {
let units: sol.SourceUnit[];
let expectedOutput: OutputRelations;
let reader: sol.ASTReader;
let version: string;

before(async () => {
reader = new sol.ASTReader();
const result = await sol.compileSol(sample, "auto");

const data = result.data;
const errors = sol.detectCompileErrors(data);

expect(errors).toHaveLength(0);

version = result.compilerVersion as string;

units = reader.read(data);
units = new sol.ASTReader().read(data);

expect(units.length).toBeGreaterThanOrEqual(1);

expectedOutput = fse.readJSONSync(json, {
encoding: "utf-8"
}) as OutputRelations;
expectedOutput = fse.readJSONSync(json, { encoding: "utf-8" });
});

it("Detectors produce expected results", async () => {
it("Analyses produce expected results", async () => {
const targetAnalyses = [...Object.keys(expectedOutput)];
const infer = new sol.InferType(version);
const instance = (await analyze(
Expand All @@ -51,9 +48,16 @@ describe("Analyses", () => {
targetAnalyses,
DIST_SO_DIR
)) as SouffleCSVInstance;

const analysisResults = instance.results();

instance.release();

// await fse.writeFile(
// json,
// JSON.stringify(Object.fromEntries(analysisResults.entries()), undefined, 4)
// );

for (const [key, val] of Object.entries(expectedOutput)) {
expect(
(analysisResults.get(key) as Fact[]).map((fact) => fact.toJSON())
Expand All @@ -71,11 +75,9 @@ describe("Analyses work in sqlite mode", () => {
describe(sample, () => {
let units: sol.SourceUnit[];
let expectedOutput: OutputRelations;
let reader: sol.ASTReader;
let version: string;

before(async () => {
reader = new sol.ASTReader();
const result = await sol.compileSol(sample, "auto");

const data = result.data;
Expand All @@ -84,7 +86,7 @@ describe("Analyses work in sqlite mode", () => {
expect(errors).toHaveLength(0);

version = result.compilerVersion as string;
units = reader.read(data);
units = new sol.ASTReader().read(data);

expect(units.length).toBeGreaterThanOrEqual(1);

Expand All @@ -93,7 +95,7 @@ describe("Analyses work in sqlite mode", () => {
}) as OutputRelations;
});

it("Detectors produce expected results", async () => {
it("Analyses produce expected results", async () => {
const targetAnalyses = [...Object.keys(expectedOutput)];
const infer = new sol.InferType(version);
const instance = (await analyze(
Expand All @@ -105,6 +107,7 @@ describe("Analyses work in sqlite mode", () => {

for (const [key, val] of Object.entries(expectedOutput)) {
const actualResutls = (await instance.relationFacts(key)).map((f) => f.fields);

expect(actualResutls).toEqual(val);
}

Expand Down
11 changes: 7 additions & 4 deletions test/detectors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,35 @@ describe("Detectors", () => {
describe(sample, () => {
let units: sol.SourceUnit[];
let expectedIssues: Issue[];
let reader: sol.ASTReader;
let ctx: sol.ASTContext;
let version: string;

before(async () => {
reader = new sol.ASTReader();
const result = await sol.compileSol(sample, "auto");

const data = result.data;
const errors = sol.detectCompileErrors(data);

expect(errors).toHaveLength(0);

const reader = new sol.ASTReader();

version = result.compilerVersion as string;

units = reader.read(data);
ctx = reader.context;

expect(units.length).toBeGreaterThanOrEqual(1);

expectedIssues = fse.readJSONSync(sample.replace(".sol", ".json"), {
encoding: "utf-8"
}) as Issue[];
});
});

it("Detectors produce expected results", async () => {
const infer = new sol.InferType(version);
const actualIssues = await detect(units, reader.context, infer);
const actualIssues = await detect(units, ctx, infer);

expect(actualIssues).toEqual(expectedIssues);
});
});
Expand Down
Loading