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

improved spec coverage report #38

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
9 changes: 9 additions & 0 deletions vscode/src/cliConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ export async function usedSegments(): Promise<ContextSegment> {
*/
export async function activeSegments(): Promise<api.WorkspaceSegmentMetadata[]> {
const modality = toolPath("modality");

const segmentUseRes = await execFile(modality, ["segment", "use", "--format", "json"], { encoding: "utf8" });
const segmentUseJson = JSON.parse(segmentUseRes.stdout);
if (segmentUseJson == "All") {
const segmentListRes = await execFile(modality, ["segment", "list", "--detailed", "--format", "json"], { encoding: "utf8" });
const mds = JSON.parse(segmentListRes.stdout).segments as api.WorkspaceSegmentMetadata[];
return mds;
}

try {
const res = await execFile(modality, ["segment", "inspect", "--format", "json"], { encoding: "utf8" });
return JSON.parse(res.stdout).segments as api.WorkspaceSegmentMetadata[];
Expand Down
3 changes: 3 additions & 0 deletions vscode/src/mutators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,16 @@ export class MutatorsTreeDataProvider implements vscode.TreeDataProvider<Mutator
vscode.commands.registerCommand("auxon.mutators.createMutation", (itemData) => {
this.createMutation(itemData);
}),
this.wss.onDidChangeActiveWorkspace(() => this.refresh()),
this.wss.onDidChangeUsedSegments(() => this.refresh())
);

this.refresh();
}

refresh(): void {
this.workspaceMutatorGroupingAttrs = this.wss.mutatorGroupingAttrs;

vscode.commands.executeCommand(
"setContext",
"auxon.mutators.unavailable",
Expand Down
111 changes: 78 additions & 33 deletions vscode/src/specCoverage.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import * as api from "./modalityApi";
import * as vscode from "vscode";
import * as handlebars from "handlebars";
("");
import * as fs from "fs";
import * as child_process from "child_process";
import * as util from "util";

import { toolPath } from "./config";
const execFile = util.promisify(child_process.execFile);

export interface SpecCoverageParams {
segmentId: api.WorkspaceSegmentId;
segmentIds: api.WorkspaceSegmentId[];
specNames?: string[];
specVersions?: string[];
specResultIds?: api.SpecEvalResultId[];
specFilter?: string;
caseFilter?: string;
}

/// Shows a spec coverage report as a webview, when asked.
Expand All @@ -33,43 +35,86 @@ export class SpecCoverageProvider {
}

async showSpecCoverage(params: SpecCoverageParams) {
const coverage = await this.apiClient
.segment(params.segmentId)
.specCoverage(
params.specNames,
params.specVersions,
params.specResultIds,
params.specFilter,
params.caseFilter
);

let percentageBehaviorsCovered = 0.0;
if (coverage.coverage_aggregates.n_behaviors > 0 && coverage.coverage_aggregates.n_behaviors_executed > 0) {
percentageBehaviorsCovered = 100.0 - coverage.coverage_aggregates.percentage_behaviors_vacuous;
const conform = toolPath("conform");
var args = ["spec", "coverage", "--format", "html"];

var segmentationRule = undefined;
for (const seg of params.segmentIds) {
if (segmentationRule) {
if (seg.rule_name != segmentationRule) {
throw new Error("Cannot create a coverage report for segments originating from different segmentation rules");
}
} else {
segmentationRule = seg.rule_name;
}
args.push("--segment")
args.push(seg.segment_name)
}

const html = this.template({
designUnit: 8,
borderWidth: 1,
cornerRadius: 0,
header: {
percentageSpecsExecuted: coverage.coverage_aggregates.percentage_specs_executed,
percentageSpecsPassing: coverage.coverage_aggregates.percentage_specs_passing,
percentageBehaviorsCovered,
percentageCasesEverMatched: coverage.coverage_aggregates.percentage_cases_ever_matched,
},
specs: coverage.spec_coverages.map(specViewModel).sort((a, b) => a.name.localeCompare(b.name)),
params,
percentageBehaviorsCovered,
});
if (segmentationRule) {
args.push("--segmentation-rule", segmentationRule);
}

var specFilters = [];
if (params.specNames) {
for (const name of params.specNames) {
specFilters.push(`_.name='${name}'`)
}
}

if (params.specVersions) {
for (const version of params.specVersions) {
specFilters.push(`_.spec.version_id = "${version}"`)
}
}

// TODO what about params.specResultIds?
if (specFilters.length > 0) {
args.push("--spec-filter");
args.push(specFilters.join(" or "));
}

const coverageRes = await execFile(conform, args, { encoding: "utf8" });

// const coverage = await this.apiClient
// .segment(params.segmentId)
// .specCoverage(
// params.specNames,
// params.specVersions,
// params.specResultIds,
// params.specFilter,
// params.caseFilter
// );

// let percentageBehaviorsCovered = 0.0;
// if (coverage.coverage_aggregates.n_behaviors > 0 && coverage.coverage_aggregates.n_behaviors_executed > 0) {
// percentageBehaviorsCovered = 100.0 - coverage.coverage_aggregates.percentage_behaviors_vacuous;
// }

// const html = this.template({
// designUnit: 8,
// borderWidth: 1,
// cornerRadius: 0,
// header: {
// percentageSpecsExecuted: coverage.coverage_aggregates.percentage_specs_executed,
// percentageSpecsPassing: coverage.coverage_aggregates.percentage_specs_passing,
// percentageBehaviorsCovered,
// percentageCasesEverMatched: coverage.coverage_aggregates.percentage_cases_ever_matched,
// },
// specs: coverage.spec_coverages.map(specViewModel).sort((a, b) => a.name.localeCompare(b.name)),
// params,
// percentageBehaviorsCovered,
// });


const panel = vscode.window.createWebviewPanel(
"auxon.specCoverageView",
`Coverage Report: ${params.segmentId.segment_name}`,
"Coverage Report", // TODO formatted version
//`Coverage Report: ${params.segmentId.segment_name}`,
vscode.ViewColumn.One,
{}
);
panel.webview.html = html;
panel.webview.html = coverageRes.stdout;
}
}

Expand Down
6 changes: 2 additions & 4 deletions vscode/src/specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,14 +247,12 @@ export class SpecsTreeDataProvider implements vscode.TreeDataProvider<SpecsTreeI

async coverage(item: SpecsTreeItemData) {
const activeSegments = await cliConfig.activeSegments();
if (activeSegments.length > 1) {
throw new Error("Can't currently show coverage for multiple segments at once");
} else if (activeSegments.length == 0) {
if (activeSegments.length == 0) {
throw new Error("No segments are active");
}

const params: specCoverage.SpecCoverageParams = {
segmentId: activeSegments[0].id,
segmentIds: activeSegments.map(seg => seg.id)
};

// consider the clicked item to be part of the selection for
Expand Down
10 changes: 8 additions & 2 deletions vscode/src/workspaceState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export class WorkspaceAndSegmentState {
public activeWorkspaceName: string,
public activeWorkspaceVersionId: string,
public usedSegmentConfig: cliConfig.ContextSegment,
public activeSegments: ActiveSegments
public activeSegments: ActiveSegments,
public mutatorGroupingAttrs: string[],
) {}

static async create(apiClient: api.Client): Promise<WorkspaceAndSegmentState> {
Expand Down Expand Up @@ -96,6 +97,7 @@ export class WorkspaceAndSegmentState {
}
}
}

if (resetToLatestWorkspace) {
vscode.window.showWarningMessage(`Active segment is for a different workspace; reverting to latest.`);
await _useLatestSegment();
Expand All @@ -106,12 +108,16 @@ export class WorkspaceAndSegmentState {
};
}

let ws_def = await apiClient.workspace(activeWorkspaceVersionId).definition();
let mutatorGroupingAttrs = ws_def.mutator_grouping_attrs;

return new WorkspaceAndSegmentState(
apiClient,
activeWorkspaceName,
activeWorkspaceVersionId,
usedSegmentConfig,
activeSegments
activeSegments,
mutatorGroupingAttrs
);
}

Expand Down
Loading