Skip to content

Commit af7ebce

Browse files
authored
Merge pull request os-checker#132 from os-checker/feat/testcases
feat: 增加 testcases 页面,展示测试和 Miri 详情
2 parents 6933a3c + 8a5e4e1 commit af7ebce

File tree

4 files changed

+199
-5
lines changed

4 files changed

+199
-5
lines changed

os-checks/components/TargetDropDown.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ function fetch() {
4545
4646
function change(path: string, params: any) {
4747
// console.log("path =", path);
48-
if (path === "/" || path === "/repos" || path === "/charts" || path === "/target" || path === "/workflows") {
48+
const excludes = ["/", "/repos", "/charts", "/target", "/workflows", "/testcases"];
49+
if (excludes.findIndex(p => p === path) !== -1) {
4950
visible.value = false;
5051
return;
5152
} else if (params) {

os-checks/components/TopBar.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,28 @@
1111
<Button title="Repositories Infomation" icon="pi pi-warehouse" :style="btnStyle('/repos')" />
1212
</NuxtLink>
1313

14+
<NuxtLink to="/testcases">
15+
<Button title="Test Cases" icon="pi pi-code" :style="btnStyle('/testcases')" />
16+
</NuxtLink>
17+
1418
<NuxtLink to="/diagnostics">
1519
<Button title="Diagnostics" icon="pi pi-microchip" :style="btnStyle('/diagnostics')" />
1620
</NuxtLink>
1721

1822
<NuxtLink to="/file-tree">
19-
<Button title="问题文件树" icon="pi pi-sitemap" :style="btnStyle('/file-tree')"/>
23+
<Button title="问题文件树" icon="pi pi-sitemap" :style="btnStyle('/file-tree')" />
2024
</NuxtLink>
2125

2226
<NuxtLink to="/charts">
23-
<Button title="统计图" icon="pi pi-chart-bar" :style="btnStyle('/charts')"/>
27+
<Button title="统计图" icon="pi pi-chart-bar" :style="btnStyle('/charts')" />
2428
</NuxtLink>
2529

2630
<NuxtLink to="/target">
27-
<Button title="编译目标明细表" icon="pi pi-objects-column" :style="btnStyle('/target')"/>
31+
<Button title="编译目标明细表" icon="pi pi-objects-column" :style="btnStyle('/target')" />
2832
</NuxtLink>
2933

3034
<NuxtLink to="/workflows">
31-
<Button title="Github Workflows" icon="pi pi-bell" :style="btnStyle('/workflows')"/>
35+
<Button title="Github Workflows" icon="pi pi-bell" :style="btnStyle('/workflows')" />
3236
</NuxtLink>
3337

3438
</div>

os-checks/pages/testcases.vue

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<template>
2+
3+
<DataTable :value="testcases" scrollable :scrollHeight="tableHeight" showGridlines selectionMode="single"
4+
v-model:selection="selectedTest" v-model:filters="selected.text" :multiSortMeta="selected.sorts"
5+
@update:multiSortMeta="sortsChanged" sortMode="multiple" removableSort paginator :rows="10"
6+
:rowsPerPageOptions="[5, 10, 20, 50, 100, 200, 1000]"
7+
:globalFilterFields="['user', 'repo', 'pkg', 'kind', 'bin', 'name']">
8+
9+
<template #empty><b> No testcases found. </b></template>
10+
<template #header>
11+
<div style="display: flex; justify-content: space-between;">
12+
<div style="display: flex; gap: 10px;">
13+
<!-- <MultiSelect v-model="selected.categories" display="chip" :options="categories" filter :maxSelectedLabels="4" -->
14+
<!-- placeholder="Select Categories" /> -->
15+
</div>
16+
17+
<div>
18+
<IconField>
19+
<InputIcon> <i class="pi pi-search" /> </InputIcon>
20+
<InputText style="width: 300px" v-model="selected.text['global'].value" placeholder="Search" />
21+
</IconField>
22+
</div>
23+
24+
</div>
25+
</template>
26+
27+
<Column field="idx" header="Idx" :pt="ptColumnCenter" />
28+
<Column field="user" sortable header="User" style="min-width: 120px;" />
29+
<Column field="repo" sortable header="Repo" />
30+
<Column field="pkg" sortable header="Package" />
31+
<Column field="bin" sortable header="Test Bin" />
32+
<Column field="kind" sortable header="Kind" :pt="ptColumnCenter" />
33+
<Column field="name" sortable header="Test Name" />
34+
<Column field="test_pass" sortable header="Test Pass" :pt="ptColumnCenter" />
35+
<Column field="test_duration_ms" sortable header="Test (ms)" :pt="ptColumnRight" />
36+
<Column field="miri_pass" sortable header="Miri Pass" :pt="ptColumnCenter" />
37+
<Column field="miri_timeout" sortable header="Miri Timed Out" :pt="ptColumnCenter" />
38+
39+
</DataTable>
40+
41+
<Dialog v-model:visible="dialogShow" modal :style="{ width: '70%' }">
42+
<template #header>
43+
<span style="display: inline-flex; justify-content:center; gap: 40px; font-size: larger; font-weight: bold;">
44+
<div>
45+
<NuxtLink :to="`https://github.com/${selectedTest!.user}/${selectedTest!.repo}`" target="_blank">
46+
<Tag icon="pi pi-github" severity="info" style="font-weight: bold;">
47+
{{ `${selectedTest!.user} / ${selectedTest!.repo}` }}
48+
</Tag>
49+
</NuxtLink>
50+
</div>
51+
52+
<div style="margin-top: 3.2px;">Test Name:
53+
<span style="color: var(--p-rose-500); margin-right: 5px">
54+
{{ selectedTest!.name }}
55+
</span>
56+
</div>
57+
</span>
58+
</template>
59+
60+
<div style="padding: 3px;">
61+
<b style="margin-right: 5px">Pkg:</b>
62+
<Tag severity="warn" :value="selectedTest!.pkg" style="margin-right: 6px;" />
63+
<b style="margin-right: 5px">Test Binary:</b>
64+
<Tag severity="warn" :value="selectedTest!.bin" style="margin-right: 6px;" />
65+
<b style="margin-right: 5px">Test Name:</b>
66+
<Tag severity="warn" :value="selectedTest!.name" style="margin-right: 6px;" />
67+
<b style="margin-right: 5px">Test Pass:</b>
68+
{{ selectedTest!.test_pass }}
69+
<b style="margin-right: 5px">Miri Pass:</b>
70+
{{ selectedTest!.miri_pass }}
71+
</div>
72+
73+
<Accordion value="0">
74+
<AccordionPanel value="0" v-if="selectedTest?.test_error">
75+
<AccordionHeader>Test Error</AccordionHeader>
76+
<AccordionContent>
77+
<CodeBlock :snippets="selectedTest?.test_error ? [selectedTest.test_error] : []" />
78+
</AccordionContent>
79+
</AccordionPanel>
80+
<AccordionPanel value="1" v-if="selectedTest?.miri_output">
81+
<AccordionHeader>Miri Output</AccordionHeader>
82+
<AccordionContent>
83+
<CodeBlock :snippets="selectedTest?.miri_output ? [selectedTest.miri_output] : []" />
84+
</AccordionContent>
85+
</AccordionPanel>
86+
</Accordion>
87+
88+
</Dialog>
89+
90+
</template>
91+
92+
<script setup lang="ts">
93+
import type { DataTableSortMeta } from 'primevue/datatable';
94+
import { FilterMatchMode } from '@primevue/core/api';
95+
import type { PkgInfo } from '~/shared/info';
96+
97+
// styling
98+
const { viewportHeight } = storeToRefs(useStyleStore());
99+
const tableHeight = computed(() => `${Math.round(viewportHeight.value * 0.8)}px`);
100+
const ptColumnCenter = ref({
101+
columnHeaderContent: { style: { "justify-content": "center" } },
102+
bodyCell: { style: { "text-align": "center" } }
103+
});
104+
const ptColumnRight = ref({
105+
columnHeaderContent: { style: { "justify-content": "right" } },
106+
bodyCell: { style: { "text-align": "right" } }
107+
});
108+
highlightRust();
109+
110+
const testcases = ref<TestResult[]>([]);
111+
const selectedTest = ref<TestResult | null>(null);
112+
113+
// pop up details
114+
const dialogShow = ref(false);
115+
watch(selectedTest, sel => dialogShow.value = sel ? true : false);
116+
117+
githubFetch<PkgInfo[]>({
118+
path: "plugin/cargo/info/summaries.json"
119+
}).then(val => {
120+
testcases.value = summariesToTestResult(val);
121+
});
122+
123+
type TestResult = {
124+
idx: number,
125+
user: string,
126+
repo: string,
127+
pkg: string,
128+
bin: string,
129+
kind: string,
130+
name: string,
131+
test_pass: string,
132+
test_duration_ms: number | null,
133+
test_error: string | null,
134+
miri_pass: string,
135+
miri_output: string | null,
136+
miri_timeout: string,
137+
};
138+
139+
function summariesToTestResult(pkg_info: PkgInfo[]): TestResult[] {
140+
let result: TestResult[] = [];
141+
let idx = 0;
142+
143+
for (const info of pkg_info) {
144+
for (const [pkg, value] of Object.entries(info.pkgs)) {
145+
for (const test of value.testcases?.tests || []) {
146+
for (const testcase of test.testcases) {
147+
result.push({
148+
idx: idx++,
149+
user: info.user,
150+
repo: info.repo,
151+
pkg,
152+
bin: test.binary_name,
153+
kind: test.kind,
154+
name: testcase.name,
155+
test_pass: testcase.status === "ok" ? "" : (testcase.status === "failed" ? "" : ""),
156+
test_duration_ms: testcase.duration_ms,
157+
test_error: testcase.error,
158+
miri_pass: testcase.miri_pass ? "" : "",
159+
miri_output: testcase.miri_output,
160+
miri_timeout: testcase.miri_timeout ? "💥" : "",
161+
});
162+
}
163+
}
164+
}
165+
}
166+
167+
return result;
168+
}
169+
170+
function sortsChanged(meta?: DataTableSortMeta[] | null) {
171+
if (meta) {
172+
selected.sorts = meta;
173+
}
174+
}
175+
176+
const selected = reactive<{
177+
text: any,
178+
sorts: DataTableSortMeta[],
179+
}>({
180+
text: { global: { value: null, matchMode: FilterMatchMode.CONTAINS }, },
181+
sorts: [],
182+
});
183+
184+
useHead({ title: 'Test Cases' });
185+
</script>

os-checks/shared/info.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export type TestCase = {
5151
name: string,
5252
status: string | null,
5353
duration_ms: number | null,
54+
error: string | null,
55+
miri_pass: boolean,
56+
miri_output: string | null,
57+
miri_timeout: boolean,
5458
}
5559

5660
export function unique_field(summaries: PkgInfo[], cb: (_: Pkg) => string[]): string[] {

0 commit comments

Comments
 (0)