@libraz/coverwise 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +191 -0
- package/README.md +119 -0
- package/README.npm.md +119 -0
- package/dist/coverwise.js +2 -0
- package/dist/coverwise.wasm +0 -0
- package/dist/js/constraint.d.ts +78 -0
- package/dist/js/constraint.d.ts.map +1 -0
- package/dist/js/constraint.js +213 -0
- package/dist/js/constraint.js.map +1 -0
- package/dist/js/index.d.ts +94 -0
- package/dist/js/index.d.ts.map +1 -0
- package/dist/js/index.js +164 -0
- package/dist/js/index.js.map +1 -0
- package/dist/js/pure/adapter.d.ts +40 -0
- package/dist/js/pure/adapter.d.ts.map +1 -0
- package/dist/js/pure/adapter.js +207 -0
- package/dist/js/pure/adapter.js.map +1 -0
- package/dist/js/pure/index.d.ts +83 -0
- package/dist/js/pure/index.d.ts.map +1 -0
- package/dist/js/pure/index.js +132 -0
- package/dist/js/pure/index.js.map +1 -0
- package/dist/js/types.d.ts +132 -0
- package/dist/js/types.d.ts.map +1 -0
- package/dist/js/types.js +3 -0
- package/dist/js/types.js.map +1 -0
- package/dist/src/ts/algo/greedy.d.ts +9 -0
- package/dist/src/ts/algo/greedy.d.ts.map +1 -0
- package/dist/src/ts/algo/greedy.js +137 -0
- package/dist/src/ts/algo/greedy.js.map +1 -0
- package/dist/src/ts/algo/index.d.ts +2 -0
- package/dist/src/ts/algo/index.d.ts.map +1 -0
- package/dist/src/ts/algo/index.js +2 -0
- package/dist/src/ts/algo/index.js.map +1 -0
- package/dist/src/ts/core/coverage-engine.d.ts +40 -0
- package/dist/src/ts/core/coverage-engine.d.ts.map +1 -0
- package/dist/src/ts/core/coverage-engine.js +366 -0
- package/dist/src/ts/core/coverage-engine.js.map +1 -0
- package/dist/src/ts/core/generator.d.ts +6 -0
- package/dist/src/ts/core/generator.d.ts.map +1 -0
- package/dist/src/ts/core/generator.js +394 -0
- package/dist/src/ts/core/generator.js.map +1 -0
- package/dist/src/ts/core/index.d.ts +3 -0
- package/dist/src/ts/core/index.d.ts.map +1 -0
- package/dist/src/ts/core/index.js +3 -0
- package/dist/src/ts/core/index.js.map +1 -0
- package/dist/src/ts/model/boundary.d.ts +29 -0
- package/dist/src/ts/model/boundary.d.ts.map +1 -0
- package/dist/src/ts/model/boundary.js +102 -0
- package/dist/src/ts/model/boundary.js.map +1 -0
- package/dist/src/ts/model/constraint-ast.d.ts +152 -0
- package/dist/src/ts/model/constraint-ast.d.ts.map +1 -0
- package/dist/src/ts/model/constraint-ast.js +384 -0
- package/dist/src/ts/model/constraint-ast.js.map +1 -0
- package/dist/src/ts/model/constraint-parser.d.ts +49 -0
- package/dist/src/ts/model/constraint-parser.d.ts.map +1 -0
- package/dist/src/ts/model/constraint-parser.js +831 -0
- package/dist/src/ts/model/constraint-parser.js.map +1 -0
- package/dist/src/ts/model/error.d.ts +19 -0
- package/dist/src/ts/model/error.d.ts.map +1 -0
- package/dist/src/ts/model/error.js +19 -0
- package/dist/src/ts/model/error.js.map +1 -0
- package/dist/src/ts/model/generate-options.d.ts +82 -0
- package/dist/src/ts/model/generate-options.d.ts.map +1 -0
- package/dist/src/ts/model/generate-options.js +52 -0
- package/dist/src/ts/model/generate-options.js.map +1 -0
- package/dist/src/ts/model/index.d.ts +6 -0
- package/dist/src/ts/model/index.d.ts.map +1 -0
- package/dist/src/ts/model/index.js +6 -0
- package/dist/src/ts/model/index.js.map +1 -0
- package/dist/src/ts/model/parameter.d.ts +65 -0
- package/dist/src/ts/model/parameter.d.ts.map +1 -0
- package/dist/src/ts/model/parameter.js +157 -0
- package/dist/src/ts/model/parameter.js.map +1 -0
- package/dist/src/ts/model/test-case.d.ts +67 -0
- package/dist/src/ts/model/test-case.d.ts.map +1 -0
- package/dist/src/ts/model/test-case.js +28 -0
- package/dist/src/ts/model/test-case.js.map +1 -0
- package/dist/src/ts/util/bitset.d.ts +14 -0
- package/dist/src/ts/util/bitset.d.ts.map +1 -0
- package/dist/src/ts/util/bitset.js +66 -0
- package/dist/src/ts/util/bitset.js.map +1 -0
- package/dist/src/ts/util/combinatorics.d.ts +4 -0
- package/dist/src/ts/util/combinatorics.d.ts.map +1 -0
- package/dist/src/ts/util/combinatorics.js +60 -0
- package/dist/src/ts/util/combinatorics.js.map +1 -0
- package/dist/src/ts/util/index.d.ts +5 -0
- package/dist/src/ts/util/index.d.ts.map +1 -0
- package/dist/src/ts/util/index.js +7 -0
- package/dist/src/ts/util/index.js.map +1 -0
- package/dist/src/ts/util/rng.d.ts +13 -0
- package/dist/src/ts/util/rng.d.ts.map +1 -0
- package/dist/src/ts/util/rng.js +112 -0
- package/dist/src/ts/util/rng.js.map +1 -0
- package/dist/src/ts/util/string_util.d.ts +3 -0
- package/dist/src/ts/util/string_util.d.ts.map +1 -0
- package/dist/src/ts/util/string_util.js +25 -0
- package/dist/src/ts/util/string_util.js.map +1 -0
- package/dist/src/ts/validator/constraint-validator.d.ts +34 -0
- package/dist/src/ts/validator/constraint-validator.d.ts.map +1 -0
- package/dist/src/ts/validator/constraint-validator.js +51 -0
- package/dist/src/ts/validator/constraint-validator.js.map +1 -0
- package/dist/src/ts/validator/coverage-validator.d.ts +42 -0
- package/dist/src/ts/validator/coverage-validator.d.ts.map +1 -0
- package/dist/src/ts/validator/coverage-validator.js +230 -0
- package/dist/src/ts/validator/coverage-validator.js.map +1 -0
- package/dist/src/ts/validator/index.d.ts +3 -0
- package/dist/src/ts/validator/index.d.ts.map +1 -0
- package/dist/src/ts/validator/index.js +3 -0
- package/dist/src/ts/validator/index.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/// @file generator.ts
|
|
2
|
+
/// @brief Main test generation orchestrator.
|
|
3
|
+
import { greedyConstruct } from '../algo/greedy.js';
|
|
4
|
+
import { expandBoundaryValues } from '../model/boundary.js';
|
|
5
|
+
import { parseConstraint } from '../model/constraint-parser.js';
|
|
6
|
+
import { ErrorCode } from '../model/error.js';
|
|
7
|
+
import { createModelStats, ExtendMode, getWeight, isWeightConfigEmpty, } from '../model/generate-options.js';
|
|
8
|
+
import { hasInvalidValues, Parameter } from '../model/parameter.js';
|
|
9
|
+
import { createGenerateResult, uncoveredTupleToString, } from '../model/test-case.js';
|
|
10
|
+
import { Rng } from '../util/rng.js';
|
|
11
|
+
import { CoverageEngine } from './coverage-engine.js';
|
|
12
|
+
/// Resolve parameter names to sorted indices.
|
|
13
|
+
/// Returns indices array and error message (empty string on success).
|
|
14
|
+
function resolveParamNames(names, params) {
|
|
15
|
+
const indices = [];
|
|
16
|
+
for (const name of names) {
|
|
17
|
+
let found = false;
|
|
18
|
+
for (let i = 0; i < params.length; ++i) {
|
|
19
|
+
if (params[i].name === name) {
|
|
20
|
+
indices.push(i);
|
|
21
|
+
found = true;
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!found) {
|
|
26
|
+
return { indices: [], error: `Unknown parameter in sub-model: ${name}` };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Sort for consistent combination generation.
|
|
30
|
+
indices.sort((a, b) => a - b);
|
|
31
|
+
return { indices, error: '' };
|
|
32
|
+
}
|
|
33
|
+
/// Check if all engines are complete.
|
|
34
|
+
function allComplete(global, subEngines) {
|
|
35
|
+
if (!global.isComplete) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
for (const eng of subEngines) {
|
|
39
|
+
if (!eng.isComplete) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
/// Sum scoreCandidate across all engines.
|
|
46
|
+
function totalScore(global, subEngines, tc) {
|
|
47
|
+
let score = global.scoreCandidate(tc);
|
|
48
|
+
for (const eng of subEngines) {
|
|
49
|
+
score += eng.scoreCandidate(tc);
|
|
50
|
+
}
|
|
51
|
+
return score;
|
|
52
|
+
}
|
|
53
|
+
/// Build an allowedValues mask that only permits valid values.
|
|
54
|
+
function buildValidOnlyMask(params) {
|
|
55
|
+
const mask = new Array(params.length);
|
|
56
|
+
for (let pi = 0; pi < params.length; ++pi) {
|
|
57
|
+
mask[pi] = new Array(params[pi].size);
|
|
58
|
+
for (let vi = 0; vi < params[pi].size; ++vi) {
|
|
59
|
+
mask[pi][vi] = !params[pi].isInvalid(vi);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return mask;
|
|
63
|
+
}
|
|
64
|
+
/// Build an allowedValues mask for negative test generation.
|
|
65
|
+
///
|
|
66
|
+
/// The fixed parameter is allowed only at the given invalid value index.
|
|
67
|
+
/// All other parameters are allowed only at their valid values.
|
|
68
|
+
function buildNegativeMask(params, fixedParam, fixedValue) {
|
|
69
|
+
const mask = new Array(params.length);
|
|
70
|
+
for (let pi = 0; pi < params.length; ++pi) {
|
|
71
|
+
mask[pi] = new Array(params[pi].size).fill(false);
|
|
72
|
+
if (pi === fixedParam) {
|
|
73
|
+
mask[pi][fixedValue] = true;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
for (let vi = 0; vi < params[pi].size; ++vi) {
|
|
77
|
+
if (!params[pi].isInvalid(vi)) {
|
|
78
|
+
mask[pi][vi] = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return mask;
|
|
84
|
+
}
|
|
85
|
+
/// Generate negative tests for parameters with invalid values.
|
|
86
|
+
///
|
|
87
|
+
/// For each invalid value of each parameter, generates test cases that pair
|
|
88
|
+
/// the invalid value with valid values of all other parameters using pairwise
|
|
89
|
+
/// coverage. Each negative test case contains exactly one invalid value.
|
|
90
|
+
function generateNegativeTests(params, strength, constraints, rng, negativeTests) {
|
|
91
|
+
const kMaxRetries = 50;
|
|
92
|
+
for (let pi = 0; pi < params.length; ++pi) {
|
|
93
|
+
for (let vi = 0; vi < params[pi].size; ++vi) {
|
|
94
|
+
if (!params[pi].isInvalid(vi)) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// Create a coverage engine for generating tests that pair this invalid
|
|
98
|
+
// value with valid values of all other parameters.
|
|
99
|
+
const freshResult = CoverageEngine.create(params, strength);
|
|
100
|
+
if (freshResult.error.code !== ErrorCode.Ok) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const freshCov = freshResult.engine;
|
|
104
|
+
// Exclude constraint-invalid tuples.
|
|
105
|
+
freshCov.excludeInvalidTuples(constraints);
|
|
106
|
+
// Build mask: pi can only be vi, others can only be valid.
|
|
107
|
+
const negMask = buildNegativeMask(params, pi, vi);
|
|
108
|
+
// Generate test cases with this mask until coverage of relevant tuples
|
|
109
|
+
// is complete or we hit retry limit.
|
|
110
|
+
let retries = 0;
|
|
111
|
+
// Bound: at most max valid_count of other params (generous upper bound).
|
|
112
|
+
let maxNegTests = 0;
|
|
113
|
+
for (let pj = 0; pj < params.length; ++pj) {
|
|
114
|
+
if (pj !== pi) {
|
|
115
|
+
maxNegTests = Math.max(maxNegTests, params[pj].validCount);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (maxNegTests === 0) {
|
|
119
|
+
maxNegTests = 1;
|
|
120
|
+
}
|
|
121
|
+
let generated = 0;
|
|
122
|
+
while (generated < maxNegTests) {
|
|
123
|
+
const negScoreFn = (partial, paramIdx, valIdx) => {
|
|
124
|
+
return freshCov.scoreValue(partial, paramIdx, valIdx);
|
|
125
|
+
};
|
|
126
|
+
const tc = greedyConstruct(params, negScoreFn, constraints, rng, negMask);
|
|
127
|
+
const score = freshCov.scoreCandidate(tc);
|
|
128
|
+
if (score === 0) {
|
|
129
|
+
if (++retries >= kMaxRetries) {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
retries = 0;
|
|
135
|
+
freshCov.addTestCase(tc);
|
|
136
|
+
negativeTests.push(tc);
|
|
137
|
+
++generated;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/// Resolve string-based WeightConfig to index-based weight vectors.
|
|
143
|
+
/// Returns weights[paramIdx][valueIdx] = weight (default 1.0).
|
|
144
|
+
/// Empty array if no weights are configured.
|
|
145
|
+
function resolveWeights(params, config) {
|
|
146
|
+
if (isWeightConfigEmpty(config)) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
const resolved = new Array(params.length);
|
|
150
|
+
for (let pi = 0; pi < params.length; ++pi) {
|
|
151
|
+
resolved[pi] = new Array(params[pi].size);
|
|
152
|
+
for (let vi = 0; vi < params[pi].size; ++vi) {
|
|
153
|
+
resolved[pi][vi] = getWeight(config, params[pi].name, params[pi].values[vi]);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return resolved;
|
|
157
|
+
}
|
|
158
|
+
/// Apply boundary value expansion to parameters with boundary configs.
|
|
159
|
+
function applyBoundaryExpansion(opts) {
|
|
160
|
+
const params = [];
|
|
161
|
+
for (const p of opts.parameters) {
|
|
162
|
+
const param = p.invalid
|
|
163
|
+
? new Parameter(p.name, p.values, p.invalid)
|
|
164
|
+
: new Parameter(p.name, p.values);
|
|
165
|
+
const bc = opts.boundaryConfigs[p.name];
|
|
166
|
+
if (bc) {
|
|
167
|
+
params.push(expandBoundaryValues(param, bc));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
params.push(param);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return params;
|
|
174
|
+
}
|
|
175
|
+
/// Generate a covering array for the given options.
|
|
176
|
+
/// @returns The generated test suite with coverage metadata, stats, and suggestions.
|
|
177
|
+
export function generate(options) {
|
|
178
|
+
const result = createGenerateResult();
|
|
179
|
+
// Apply boundary value expansion to parameters that have boundary configs.
|
|
180
|
+
const params = applyBoundaryExpansion(options);
|
|
181
|
+
const hasInvalid = hasInvalidValues(params);
|
|
182
|
+
const coverageResult = CoverageEngine.create(params, options.strength);
|
|
183
|
+
if (coverageResult.error.code !== ErrorCode.Ok) {
|
|
184
|
+
result.warnings.push(`${coverageResult.error.message}: ${coverageResult.error.detail}`);
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
const coverage = coverageResult.engine;
|
|
188
|
+
// Create sub-model engines.
|
|
189
|
+
const subEngines = [];
|
|
190
|
+
for (const sm of options.subModels) {
|
|
191
|
+
const resolved = resolveParamNames(sm.parameterNames, params);
|
|
192
|
+
if (resolved.error.length > 0) {
|
|
193
|
+
result.warnings.push(resolved.error);
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
if (resolved.indices.length < sm.strength) {
|
|
197
|
+
result.warnings.push('Sub-model strength (' +
|
|
198
|
+
sm.strength +
|
|
199
|
+
') exceeds parameter count (' +
|
|
200
|
+
resolved.indices.length +
|
|
201
|
+
')');
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
const smResult = CoverageEngine.createFromSubset(params, resolved.indices, sm.strength);
|
|
205
|
+
if (smResult.error.code !== ErrorCode.Ok) {
|
|
206
|
+
result.warnings.push(`${smResult.error.message}: ${smResult.error.detail}`);
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
subEngines.push(smResult.engine);
|
|
210
|
+
}
|
|
211
|
+
// Parse constraint expressions into AST.
|
|
212
|
+
const constraints = [];
|
|
213
|
+
for (const expr of options.constraintExpressions) {
|
|
214
|
+
const parseResult = parseConstraint(expr, params);
|
|
215
|
+
if (parseResult.error.code !== ErrorCode.Ok) {
|
|
216
|
+
result.warnings.push(`${parseResult.error.message}: ${parseResult.error.detail}`);
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
constraints.push(parseResult.constraint);
|
|
220
|
+
}
|
|
221
|
+
// Exclude tuples that are inherently invalid due to constraints.
|
|
222
|
+
coverage.excludeInvalidTuples(constraints);
|
|
223
|
+
for (const eng of subEngines) {
|
|
224
|
+
eng.excludeInvalidTuples(constraints);
|
|
225
|
+
}
|
|
226
|
+
// Exclude tuples involving invalid values for positive generation.
|
|
227
|
+
if (hasInvalid) {
|
|
228
|
+
coverage.excludeInvalidValues();
|
|
229
|
+
for (const eng of subEngines) {
|
|
230
|
+
eng.excludeInvalidValues();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// Build allowedValues mask for positive generation (valid values only).
|
|
234
|
+
let validMask = [];
|
|
235
|
+
if (hasInvalid) {
|
|
236
|
+
validMask = buildValidOnlyMask(params);
|
|
237
|
+
}
|
|
238
|
+
// Resolve value weights to index-based vectors.
|
|
239
|
+
const resolvedWeights = resolveWeights(params, options.weights);
|
|
240
|
+
const rng = new Rng(options.seed);
|
|
241
|
+
// Pre-load seed tests into all engines.
|
|
242
|
+
for (const seedTest of options.seeds) {
|
|
243
|
+
coverage.addTestCase(seedTest);
|
|
244
|
+
for (const eng of subEngines) {
|
|
245
|
+
eng.addTestCase(seedTest);
|
|
246
|
+
}
|
|
247
|
+
result.tests.push(seedTest);
|
|
248
|
+
}
|
|
249
|
+
// Build scoring function that sums across all engines.
|
|
250
|
+
let scoreFn;
|
|
251
|
+
if (subEngines.length === 0) {
|
|
252
|
+
scoreFn = (partial, pi, vi) => {
|
|
253
|
+
return coverage.scoreValue(partial, pi, vi);
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
scoreFn = (partial, pi, vi) => {
|
|
258
|
+
let score = coverage.scoreValue(partial, pi, vi);
|
|
259
|
+
for (const eng of subEngines) {
|
|
260
|
+
score += eng.scoreValue(partial, pi, vi);
|
|
261
|
+
}
|
|
262
|
+
return score;
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
// Constructive greedy generation loop (positive tests only).
|
|
266
|
+
const kMaxRetries = 50;
|
|
267
|
+
let retries = 0;
|
|
268
|
+
while (!allComplete(coverage, subEngines) &&
|
|
269
|
+
(options.maxTests === 0 || result.tests.length < options.maxTests)) {
|
|
270
|
+
const tc = greedyConstruct(params, scoreFn, constraints, rng, validMask, resolvedWeights);
|
|
271
|
+
const score = totalScore(coverage, subEngines, tc);
|
|
272
|
+
if (score === 0) {
|
|
273
|
+
if (++retries >= kMaxRetries) {
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
retries = 0;
|
|
279
|
+
coverage.addTestCase(tc);
|
|
280
|
+
for (const eng of subEngines) {
|
|
281
|
+
eng.addTestCase(tc);
|
|
282
|
+
}
|
|
283
|
+
result.tests.push(tc);
|
|
284
|
+
}
|
|
285
|
+
// Generate negative tests if any parameter has invalid values.
|
|
286
|
+
if (hasInvalid) {
|
|
287
|
+
generateNegativeTests(params, options.strength, constraints, rng, result.negativeTests);
|
|
288
|
+
}
|
|
289
|
+
// Collect uncovered tuples from all engines.
|
|
290
|
+
if (!allComplete(coverage, subEngines)) {
|
|
291
|
+
const globalUncovered = coverage.getUncoveredTuples(params);
|
|
292
|
+
for (const ut of globalUncovered) {
|
|
293
|
+
result.uncovered.push(ut);
|
|
294
|
+
}
|
|
295
|
+
for (const eng of subEngines) {
|
|
296
|
+
const subUncovered = eng.getUncoveredTuples(params);
|
|
297
|
+
for (const ut of subUncovered) {
|
|
298
|
+
result.uncovered.push(ut);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
for (const ut of result.uncovered) {
|
|
302
|
+
const suggestion = {
|
|
303
|
+
description: `Add test: ${uncoveredTupleToString(ut)}`,
|
|
304
|
+
testCase: { values: [] },
|
|
305
|
+
};
|
|
306
|
+
result.suggestions.push(suggestion);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Report coverage as the minimum across all engines (for pass/fail).
|
|
310
|
+
result.coverage = coverage.coverageRatio;
|
|
311
|
+
for (const eng of subEngines) {
|
|
312
|
+
result.coverage = Math.min(result.coverage, eng.coverageRatio);
|
|
313
|
+
}
|
|
314
|
+
result.stats.totalTuples = coverage.totalTuples;
|
|
315
|
+
for (const eng of subEngines) {
|
|
316
|
+
result.stats.totalTuples += eng.totalTuples;
|
|
317
|
+
}
|
|
318
|
+
result.stats.coveredTuples = coverage.coveredCount;
|
|
319
|
+
for (const eng of subEngines) {
|
|
320
|
+
result.stats.coveredTuples += eng.coveredCount;
|
|
321
|
+
}
|
|
322
|
+
result.stats.testCount = result.tests.length;
|
|
323
|
+
return result;
|
|
324
|
+
}
|
|
325
|
+
/// Extend an existing test suite to improve coverage.
|
|
326
|
+
export function extend(existing, options, _mode = ExtendMode.Strict) {
|
|
327
|
+
const opts = {
|
|
328
|
+
...options,
|
|
329
|
+
seeds: existing,
|
|
330
|
+
};
|
|
331
|
+
return generate(opts);
|
|
332
|
+
}
|
|
333
|
+
/// Estimate model statistics without running generation.
|
|
334
|
+
/// @param options The generation options to analyze.
|
|
335
|
+
/// @returns Model statistics including estimated test count.
|
|
336
|
+
export function estimateModel(options) {
|
|
337
|
+
// Apply boundary expansion for estimation.
|
|
338
|
+
const params = applyBoundaryExpansion(options);
|
|
339
|
+
const stats = createModelStats();
|
|
340
|
+
stats.parameterCount = params.length;
|
|
341
|
+
stats.strength = options.strength;
|
|
342
|
+
stats.subModelCount = options.subModels.length;
|
|
343
|
+
stats.constraintCount = options.constraintExpressions.length;
|
|
344
|
+
let maxValues = 0;
|
|
345
|
+
for (const p of params) {
|
|
346
|
+
stats.totalValues += p.size;
|
|
347
|
+
if (p.size > maxValues) {
|
|
348
|
+
maxValues = p.size;
|
|
349
|
+
}
|
|
350
|
+
stats.parameters.push({
|
|
351
|
+
name: p.name,
|
|
352
|
+
valueCount: p.size,
|
|
353
|
+
invalidCount: p.invalidCount,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
// Compute exact total tuples using CoverageEngine.
|
|
357
|
+
const createResult = CoverageEngine.create(params, options.strength);
|
|
358
|
+
if (createResult.error.code === ErrorCode.Ok) {
|
|
359
|
+
stats.totalTuples = createResult.engine.totalTuples;
|
|
360
|
+
}
|
|
361
|
+
// Estimate test count.
|
|
362
|
+
if (stats.parameterCount === 0) {
|
|
363
|
+
stats.estimatedTests = 0;
|
|
364
|
+
}
|
|
365
|
+
else if (stats.parameterCount <= stats.strength) {
|
|
366
|
+
let product = 1;
|
|
367
|
+
for (const p of params) {
|
|
368
|
+
product *= p.size;
|
|
369
|
+
}
|
|
370
|
+
stats.estimatedTests = product;
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
let estimate = 1;
|
|
374
|
+
for (let i = 0; i < stats.strength; ++i) {
|
|
375
|
+
estimate *= maxValues;
|
|
376
|
+
if (estimate > 0xffffffff) {
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// Refine with log factor: roughly max_v^t * ceil(log2(n)).
|
|
381
|
+
let logFactor = Math.ceil(Math.log2(stats.parameterCount));
|
|
382
|
+
if (logFactor < 1) {
|
|
383
|
+
logFactor = 1;
|
|
384
|
+
}
|
|
385
|
+
estimate *= logFactor;
|
|
386
|
+
// Cap at totalTuples (can't need more tests than tuples).
|
|
387
|
+
if (stats.totalTuples > 0 && estimate > stats.totalTuples) {
|
|
388
|
+
estimate = stats.totalTuples;
|
|
389
|
+
}
|
|
390
|
+
stats.estimatedTests = Math.min(estimate, 0xffffffff) | 0;
|
|
391
|
+
}
|
|
392
|
+
return stats;
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../src/ts/core/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ts/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ts/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAqB,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Parameter } from './parameter.js';
|
|
2
|
+
/** Boundary value type: integer or float. */
|
|
3
|
+
export declare enum BoundaryType {
|
|
4
|
+
Integer = "integer",
|
|
5
|
+
Float = "float"
|
|
6
|
+
}
|
|
7
|
+
/** Configuration for boundary value expansion of a numeric parameter. */
|
|
8
|
+
export interface BoundaryConfig {
|
|
9
|
+
type: BoundaryType;
|
|
10
|
+
minValue: number;
|
|
11
|
+
maxValue: number;
|
|
12
|
+
/** Step size for float type (default 1.0 for integer). */
|
|
13
|
+
step: number;
|
|
14
|
+
}
|
|
15
|
+
/** Create a default BoundaryConfig. */
|
|
16
|
+
export declare function createBoundaryConfig(params?: Partial<BoundaryConfig>): BoundaryConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Expand a parameter's values to include boundary values.
|
|
19
|
+
*
|
|
20
|
+
* For integer type, adds: min-1, min, min+1, max-1, max, max+1.
|
|
21
|
+
* For float type, adds: min-step, min, min+step, max-step, max, max+step.
|
|
22
|
+
* Merges with existing values (dedup) and sorts numerically.
|
|
23
|
+
*
|
|
24
|
+
* @param param The original parameter.
|
|
25
|
+
* @param config The boundary configuration specifying the range.
|
|
26
|
+
* @returns A new Parameter with expanded values.
|
|
27
|
+
*/
|
|
28
|
+
export declare function expandBoundaryValues(param: Parameter, config: BoundaryConfig): Parameter;
|
|
29
|
+
//# sourceMappingURL=boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../../../src/ts/model/boundary.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,6CAA6C;AAC7C,oBAAY,YAAY;IACtB,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,uCAAuC;AACvC,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAOrF;AAoBD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,SAAS,CA4DxF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/// Boundary value expansion for numeric parameters.
|
|
2
|
+
import { Parameter } from './parameter.js';
|
|
3
|
+
/** Boundary value type: integer or float. */
|
|
4
|
+
export var BoundaryType;
|
|
5
|
+
(function (BoundaryType) {
|
|
6
|
+
BoundaryType["Integer"] = "integer";
|
|
7
|
+
BoundaryType["Float"] = "float";
|
|
8
|
+
})(BoundaryType || (BoundaryType = {}));
|
|
9
|
+
/** Create a default BoundaryConfig. */
|
|
10
|
+
export function createBoundaryConfig(params) {
|
|
11
|
+
return {
|
|
12
|
+
type: params?.type ?? BoundaryType.Integer,
|
|
13
|
+
minValue: params?.minValue ?? 0,
|
|
14
|
+
maxValue: params?.maxValue ?? 0,
|
|
15
|
+
step: params?.step ?? 1.0,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Check if a string can be parsed as a finite number. */
|
|
19
|
+
function isNumeric(s) {
|
|
20
|
+
if (s.trim().length === 0) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return Number.isFinite(Number(s));
|
|
24
|
+
}
|
|
25
|
+
/** Format an integer value as a string. */
|
|
26
|
+
function formatInteger(value) {
|
|
27
|
+
return String(Math.round(value));
|
|
28
|
+
}
|
|
29
|
+
/** Format a float value as a string, trimming trailing zeros. */
|
|
30
|
+
function formatFloat(value) {
|
|
31
|
+
return String(value);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Expand a parameter's values to include boundary values.
|
|
35
|
+
*
|
|
36
|
+
* For integer type, adds: min-1, min, min+1, max-1, max, max+1.
|
|
37
|
+
* For float type, adds: min-step, min, min+step, max-step, max, max+step.
|
|
38
|
+
* Merges with existing values (dedup) and sorts numerically.
|
|
39
|
+
*
|
|
40
|
+
* @param param The original parameter.
|
|
41
|
+
* @param config The boundary configuration specifying the range.
|
|
42
|
+
* @returns A new Parameter with expanded values.
|
|
43
|
+
*/
|
|
44
|
+
export function expandBoundaryValues(param, config) {
|
|
45
|
+
// Generate boundary values.
|
|
46
|
+
let boundaryNums;
|
|
47
|
+
if (config.type === BoundaryType.Integer) {
|
|
48
|
+
const step = 1.0;
|
|
49
|
+
boundaryNums = [
|
|
50
|
+
config.minValue - step,
|
|
51
|
+
config.minValue,
|
|
52
|
+
config.minValue + step,
|
|
53
|
+
config.maxValue - step,
|
|
54
|
+
config.maxValue,
|
|
55
|
+
config.maxValue + step,
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
boundaryNums = [
|
|
60
|
+
config.minValue - config.step,
|
|
61
|
+
config.minValue,
|
|
62
|
+
config.minValue + config.step,
|
|
63
|
+
config.maxValue - config.step,
|
|
64
|
+
config.maxValue,
|
|
65
|
+
config.maxValue + config.step,
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
// Collect existing values as numbers (for dedup), and track non-numeric values.
|
|
69
|
+
const seenNums = new Set();
|
|
70
|
+
const nonNumericValues = [];
|
|
71
|
+
for (const v of param.values) {
|
|
72
|
+
if (isNumeric(v)) {
|
|
73
|
+
seenNums.add(Number(v));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
nonNumericValues.push(v);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Add boundary values (dedup).
|
|
80
|
+
for (const bv of boundaryNums) {
|
|
81
|
+
seenNums.add(bv);
|
|
82
|
+
}
|
|
83
|
+
// Sort numerically and format.
|
|
84
|
+
const sortedNums = Array.from(seenNums).sort((a, b) => a - b);
|
|
85
|
+
const expandedValues = [];
|
|
86
|
+
for (const d of sortedNums) {
|
|
87
|
+
if (config.type === BoundaryType.Integer) {
|
|
88
|
+
expandedValues.push(formatInteger(d));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
expandedValues.push(formatFloat(d));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Append non-numeric values at the end.
|
|
95
|
+
for (const v of nonNumericValues) {
|
|
96
|
+
expandedValues.push(v);
|
|
97
|
+
}
|
|
98
|
+
// Build the result parameter. Preserve name, drop invalid/aliases since
|
|
99
|
+
// boundary expansion changes the value set.
|
|
100
|
+
return new Parameter(param.name, expandedValues);
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=boundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../../../src/ts/model/boundary.ts"],"names":[],"mappings":"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"}
|