-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFramework.ts
More file actions
166 lines (130 loc) · 5.82 KB
/
Framework.ts
File metadata and controls
166 lines (130 loc) · 5.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import {Testee, timeout} from './Testee';
import {HybridScheduler, Scheduler} from './Scheduler';
import {TestScenario} from './scenario/TestScenario';
import {TestbedSpecification} from '../testbeds/TestbedSpecification';
import {SuiteResult} from '../reporter/Results';
import {Reporter} from '../reporter/Reporter';
import {Outcome} from "../reporter/describers/Describer";
export interface TesteeOptions {
disabled?: boolean;
timeout?: number;
connectionTimout?: number;
}
export class Suite {
public title: string;
public scenarios: TestScenario[] = [];
public testees: Testee[] = [];
public scheduler: Scheduler;
public constructor(title: string, scheduler: Scheduler = new HybridScheduler()) {
this.title = title;
this.scheduler = scheduler;
}
public testee(name: string, specification: TestbedSpecification, options: TesteeOptions = {}) {
const testee = new Testee(name, specification, options.timeout ?? 2000, options.connectionTimout ?? 5000);
if (options.disabled) {
testee.skipall();
}
this.testees.push(testee);
}
public test(test: TestScenario) {
this.scenarios.push(test);
}
public tests(tests: TestScenario[]) {
tests.forEach(test => this.scenarios.push(test));
}
}
export class Framework {
private static implementation: Framework;
public runs: number = 1;
private scheduled: Suite[] = [];
public readonly reporter: Reporter = new Reporter();
private constructor() {
}
public suite(title: string, scheduler: Scheduler = new HybridScheduler()): Suite {
return new Suite(title, scheduler);
}
public suites(): Suite[] {
return this.scheduled;
}
public async sequential(suites: Suite[]) {
this.scheduled.concat(suites);
this.reporter.general();
const t0 = performance.now();
for (const suite of suites) {
for (const testee of suite.testees) {
const order: TestScenario[] = suite.scheduler.sequential(suite);
const result: SuiteResult = new SuiteResult(suite);
const first: TestScenario = order[0];
await timeout<Object | void>('Initialize testbed', testee.connector.timeout, testee.initialize(first.program, first.args ?? []).catch((e: Error) => result.error(e.message)));
await this.runSuite(result, testee, order);
this.reporter.report(result);
}
}
const t1 = performance.now();
this.reporter.results(t1 - t0);
await Promise.all(suites.map(suite => suite.testees.map(async (testee: Testee) => {
await timeout<Object | void>('Shutdown testbed', testee.timeout, testee.shutdown());
})))
}
public async run(suites: Suite[]): Promise<boolean> {
let success: boolean = true;
this.scheduled.concat(suites);
this.reporter.general();
const t0 = performance.now();
await Promise.all(suites.map(async (suite: Suite) => {
await Promise.all(suite.testees.map(async (testee: Testee) => {
const order: TestScenario[] = suite.scheduler.sequential(suite);
const result: SuiteResult = new SuiteResult(suite);
const first: TestScenario = order[0];
await timeout<Object | void>('Initialize testbed', testee.connector.timeout, testee.initialize(first.program, first.args ?? []).catch((e: Error) => result.error(e.message)));
await this.runSuite(result, testee, order);
this.reporter.report(result);
success = success && result.outcome === Outcome.succeeded;
}))
}))
const t1 = performance.now();
this.reporter.results(t1 - t0);
await Promise.all(suites.map(suite => suite.testees.map(async (testee: Testee) => {
await timeout<Object | void>('Shutdown testbed', testee.timeout, testee.shutdown());
})))
return success;
}
public async parallel(suites: Suite[]) {
this.scheduled.concat(suites);
this.reporter.general();
const t0 = performance.now();
await Promise.all(suites.map(async (suite: Suite) => {
const order: TestScenario[][] = suite.scheduler.parallel(suite, suite.testees.length);
await Promise.all(suite.testees.map(async (testee: Testee, i: number) => {
// console.log(`scheduling on ${testee.name}`)
const result: SuiteResult = new SuiteResult(suite);
const first: TestScenario = order[i][0];
await timeout<Object | void>('Initialize testbed', testee.connector.timeout, testee.initialize(first.program, first.args ?? []).catch((e: Error) => result.error(e.message)));
for (let j = i; j < order.length; j += suite.testees.length) {
await this.runSuite(result, testee, order[j]);
}
this.reporter.report(result);
}))
await Promise.all(suite.testees.map(async (testee: Testee) => {
await timeout<Object | void>('Shutdown testbed', testee.timeout, testee.shutdown());
}))
}))
const t1 = performance.now();
this.reporter.results(t1 - t0);
}
private async runSuite(result: SuiteResult, testee: Testee, order: TestScenario[]) {
for (const test of order) {
await testee.describe(test, result, this.runs);
}
}
public analyse(suite: Suite[], runs: number = 1) {
this.runs = runs;
this.run(suite).then((success: boolean) => process.exit(success ? 0 : 1));
}
public static getImplementation() {
if (!Framework.implementation) {
Framework.implementation = new Framework();
}
return Framework.implementation;
}
}