Testcase generation tool for combinatorial interaction testing
Revision | 8bbb7dd2cd5f95dcde868515c1d1ac76f8ec00cd (tree) |
---|---|
Time | 2015-11-02 19:26:30 |
Author | t-tutiya <tatsuhiro@ieee...> |
Commiter | t-tutiya |
Somewhat big changes are made. Now only the parameters involved in the
constraints are taken into account when building the BDD. This results
in a substantial reduction of computation time.
TO DO: The current version does not work when the constraints induce an
empty test space. This must be corrected soon.
@@ -3,7 +3,7 @@ | ||
3 | 3 | OS (Windows7 Windows7_64 Vista) |
4 | 4 | メモリ (4.0 2 1 8 8.0 NA) |
5 | 5 | SDD (4 2.0 2) |
6 | -# CPU ( Corei7 Corei5 Atom ) | |
6 | +CPU ( Corei7 Corei5 Atom ) | |
7 | 7 | Disk (SDD HDD) |
8 | 8 | Disk2 (SDD HDD) |
9 | 9 |
@@ -16,7 +16,7 @@ Disk2 (SDD HDD) | ||
16 | 16 | |
17 | 17 | (<> [メモリ] 4.0) |
18 | 18 | (<> [SDD] 4) |
19 | -(if (and (=== [メモリ] 8) (== [Disk] HDD) ) (or (== Vista [OS]) (<> [OS] Windows7) (<> [Disk] [Disk2]) )) | |
19 | +# (if (and (=== [メモリ] 8) (== [Disk] HDD) ) (or (== Vista [OS]) (<> [OS] Windows7) (<> [Disk] [Disk2]) )) | |
20 | 20 | |
21 | 21 | #(ite (== [Disk] [Disk2]) (== [メモリ] 4) (<> [メモリ] 2)) |
22 | 22 |
@@ -40,7 +40,11 @@ class ConstraintHandler { | ||
40 | 40 | this.constrainedParameters = constrainedParameters; |
41 | 41 | |
42 | 42 | // parameterのリスト |
43 | - parameters = setBDDforParameter(parameterList); | |
43 | + PList constrainedParameterList = new PList(); | |
44 | + for (Integer factor: constrainedParameters) { | |
45 | + constrainedParameterList.add(parameterList.get(factor)); | |
46 | + } | |
47 | + parameters = setBDDforParameter(constrainedParameterList); | |
44 | 48 | |
45 | 49 | // contrainListから、ノードを呼ぶ |
46 | 50 | bddConstraint = setBddConstraint(constraintList); |
@@ -140,7 +144,7 @@ class ConstraintHandler { | ||
140 | 144 | int f = bdd.getOne(); |
141 | 145 | bdd.ref(f); |
142 | 146 | |
143 | - // パラメータでつかわない領域をfalseにする | |
147 | + // パラメータでつかわない値をとった場合にfalseとなるようにする | |
144 | 148 | for (VariableAndBDD vb : parameters) { |
145 | 149 | int tmp = bdd.ref(bdd.and(f, vb.constraint)); |
146 | 150 | bdd.deref(f); |
@@ -148,63 +152,21 @@ class ConstraintHandler { | ||
148 | 152 | } |
149 | 153 | |
150 | 154 | // 制約式の論理積をとる |
151 | - for (Node n : constraintList) { | |
152 | - int g = n.evaluate(bdd, parameters); | |
153 | - int tmp = bdd.ref(bdd.and(f, g)); | |
154 | - bdd.deref(f); | |
155 | - bdd.deref(g); | |
156 | - f = tmp; | |
157 | - } | |
158 | - | |
159 | - // *を付加 | |
160 | - f = extendBddConstraint(f); | |
161 | - | |
162 | - return f; | |
163 | - } | |
164 | - | |
165 | - | |
166 | - private int setBddConstraintNewBuggy(List<Node> constraintList) { | |
167 | - int f = bdd.getOne(); | |
168 | - bdd.ref(f); | |
169 | - | |
170 | - // 制約式の論理積をとる | |
171 | - for (Node n : constraintList) { | |
172 | - int g = n.evaluate(bdd, parameters); | |
155 | + for (Node n : constraintList) { | |
156 | + int g = n.evaluate(bdd, parameters, constrainedParameters); | |
173 | 157 | int tmp = bdd.ref(bdd.and(f, g)); |
174 | 158 | bdd.deref(f); |
175 | 159 | bdd.deref(g); |
176 | 160 | f = tmp; |
177 | 161 | } |
178 | 162 | |
179 | - // パラメータでつかわない領域をfalseにする | |
180 | - int fordebug = 0; | |
181 | - for (VariableAndBDD vb : parameters) { | |
182 | - int cube = vb.var[0]; | |
183 | - bdd.ref(cube); | |
184 | - for (int i = 1; i < vb.var.length; i++) { | |
185 | - int tmp = bdd.ref(bdd.and(cube, vb.var[i])); | |
186 | - bdd.deref(cube); | |
187 | - cube = tmp; | |
188 | - } | |
189 | - int tmp = bdd.ref(bdd.exists(f, cube)); | |
190 | - // 制約に関係する場合のみ | |
191 | - if (tmp != f) { | |
192 | - fordebug++; | |
193 | - int tmp1 = bdd.ref(bdd.and(f, vb.constraint)); | |
194 | - bdd.deref(f); | |
195 | - f = tmp1; | |
196 | - } | |
197 | - bdd.deref(cube); | |
198 | - bdd.deref(tmp); | |
199 | - } | |
200 | - System.out.println(fordebug); | |
201 | 163 | // *を付加 |
202 | 164 | f = extendBddConstraint(f); |
203 | 165 | |
204 | 166 | return f; |
205 | 167 | } |
206 | 168 | |
207 | - | |
169 | + | |
208 | 170 | private int extendBddConstraint(int constraint) { |
209 | 171 | int f = constraint; |
210 | 172 | for (VariableAndBDD p : parameters) { |
@@ -229,7 +191,7 @@ class ConstraintHandler { | ||
229 | 191 | } |
230 | 192 | |
231 | 193 | // テストケースが制約を満たすか |
232 | - boolean isPossible(Testcase test) { | |
194 | + boolean isPossibleOld(Testcase test) { | |
233 | 195 | int node = bddConstraint; |
234 | 196 | boolean[] bv = binarize(test); |
235 | 197 |
@@ -248,6 +210,25 @@ class ConstraintHandler { | ||
248 | 210 | } |
249 | 211 | } |
250 | 212 | |
213 | + boolean isPossible(Testcase test) { | |
214 | + int node = bddConstraint; | |
215 | + boolean[] bv = binarizeReduced(test); | |
216 | + | |
217 | + while (true) { | |
218 | + // 恒真,恒偽 | |
219 | + if (node == 0) | |
220 | + return false; | |
221 | + else if (node == 1) | |
222 | + return true; | |
223 | + | |
224 | + // このposの0, 1はノードなし | |
225 | + if (bv[bdd.getVar(node)] == true) | |
226 | + node = bdd.getHigh(node); | |
227 | + else | |
228 | + node = bdd.getLow(node); | |
229 | + } | |
230 | + } | |
231 | + | |
251 | 232 | private boolean[] binarize(Testcase test) { |
252 | 233 | // assert(testcaseの長さ = parameterの数) |
253 | 234 | boolean[] res = new boolean[numOfBDDvariables]; |
@@ -271,10 +252,49 @@ class ConstraintHandler { | ||
271 | 252 | } |
272 | 253 | pos += p.var.length; |
273 | 254 | } |
274 | - /* | |
275 | - * this.print(); for (int k = 0; k < res.length; k++) | |
276 | - * System.out.print(res[k] ? 1 : 0); System.out.println("<-"); | |
255 | + | |
256 | + /* for debug | |
257 | + for (int k = 0; k < res.length; k++) | |
258 | + System.err.print(res[k] ? 1 : 0); System.err.println("<-"); | |
259 | + */ | |
260 | + | |
261 | + return res; | |
262 | + } | |
263 | + | |
264 | + // TreeSet<Integer> constrainedParameters にあるparameterだけを2値化 | |
265 | + private boolean[] binarizeReduced(Testcase test) { | |
266 | + boolean[] res = new boolean[numOfBDDvariables]; | |
267 | + int pos = 0; | |
268 | + int i = 0; | |
269 | + for (Integer factor: constrainedParameters) { | |
270 | + // VariableAndBDD p = parameters.get(i); <- | |
271 | + // parameters が relevantなものだけになれば,上記に変更 | |
272 | + VariableAndBDD p = parameters.get(i); | |
273 | + | |
274 | + int lv = test.get(factor); | |
275 | + if (lv < 0) { | |
276 | + for (int j = 0; j < p.var.length; j++) | |
277 | + res[pos + j] = true; | |
278 | + } else { | |
279 | + int j0 = 0; | |
280 | + for (int j = p.var.length -1; j >=0; j--) { | |
281 | + if ((lv & (0x01 << j)) > 0) | |
282 | + res[pos + j0] = true; | |
283 | + else | |
284 | + res[pos + j0] = false; | |
285 | + j0++; | |
286 | + } | |
287 | + } | |
288 | + pos += p.var.length; | |
289 | + i++; | |
290 | + } | |
291 | + | |
292 | + | |
293 | + /* for debug | |
294 | + test.print(); for (int k = 0; k < res.length; k++) | |
295 | + System.err.print(res[k] ? 1 : 0); System.err.println("<*"); | |
277 | 296 | */ |
297 | + | |
278 | 298 | return res; |
279 | 299 | } |
280 | 300 | } |
@@ -132,8 +132,9 @@ class Generator2 extends Generator { | ||
132 | 132 | * Random(randomseed); } |
133 | 133 | */ |
134 | 134 | |
135 | -// final int NumOfIterationForEachTest = 20; | |
136 | - final int NumOfIterationForEachTest = 1; | |
135 | + // for regression testing it should be reduced to 1 | |
136 | + final int NumOfIterationForEachTest = 20; | |
137 | +// final int NumOfIterationForEachTest = 1; | |
137 | 138 | |
138 | 139 | Generator2(ParameterModel parametermodel, GList groupList, |
139 | 140 | ConstraintHandler constrainthandler, List<Testcase> seed, |
@@ -40,15 +40,17 @@ public class Main { | ||
40 | 40 | if (errorMessage != null) |
41 | 41 | Error.printError(errorMessage); |
42 | 42 | |
43 | - System.err.println("starting reading model"); | |
44 | 43 | // モデル読み込み |
44 | + // System.err.println("starting reading model"); | |
45 | 45 | InputFileData inputfiledata = Inputer.readModel(modelFile); |
46 | 46 | |
47 | - System.err.println("starting building bdd"); | |
48 | 47 | // 制約処理 BDD作成 |
49 | -// old version where all parameters are considered in BDD | |
48 | + // System.err.println("starting building bdd"); | |
49 | + | |
50 | + // old version where all parameters are considered in BDD | |
50 | 51 | // ConstraintHandler conhndl = new ConstraintHandler( |
51 | -// inputfiledata.parameterList, inputfiledata.constraintList); | |
52 | + // inputfiledata.parameterList, inputfiledata.constraintList); | |
53 | + | |
52 | 54 | // newer version |
53 | 55 | ConstraintHandler conhndl = new ConstraintHandler( |
54 | 56 | inputfiledata.parameterList, inputfiledata.constraintList, inputfiledata.constrainedParameters); |
@@ -58,8 +60,8 @@ public class Main { | ||
58 | 60 | // シード読み込み |
59 | 61 | List<Testcase> seed = Inputer.readSeed(seedFile, inputfiledata); |
60 | 62 | |
61 | - System.err.println("starting test suite construction"); | |
62 | 63 | // テストケース生成 |
64 | + // System.err.println("starting test suite construction"); | |
63 | 65 | List<Testcase> testSet = null; |
64 | 66 | if (strength == -1) { |
65 | 67 | // 全網羅 |
@@ -6,6 +6,7 @@ import java.util.*; | ||
6 | 6 | |
7 | 7 | abstract class Node { |
8 | 8 | abstract int evaluate(BDD bdd, List<VariableAndBDD> parameters); |
9 | + abstract int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted); | |
9 | 10 | } |
10 | 11 | |
11 | 12 | abstract class BooleanOperator extends Node { |
@@ -23,6 +24,14 @@ class NotOperator extends BooleanUnaryOperator { | ||
23 | 24 | bdd.deref(tmp); |
24 | 25 | return res; |
25 | 26 | } |
27 | + | |
28 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
29 | + int tmp = Child.evaluate(bdd, parameters, restricted); | |
30 | + int res = bdd.not(tmp); | |
31 | + bdd.ref(res); | |
32 | + bdd.deref(tmp); | |
33 | + return res; | |
34 | + } | |
26 | 35 | } |
27 | 36 | |
28 | 37 | abstract class BooleanBinaryOperator extends BooleanOperator { |
@@ -39,6 +48,16 @@ class IfOperator extends BooleanBinaryOperator { | ||
39 | 48 | bdd.deref(f2); |
40 | 49 | return f; |
41 | 50 | } |
51 | + | |
52 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
53 | + int f1 = Left.evaluate(bdd, parameters, restricted); | |
54 | + int f2 = Right.evaluate(bdd, parameters, restricted); | |
55 | + int f = bdd.imp(f1, f2); | |
56 | + bdd.ref(f); | |
57 | + bdd.deref(f1); | |
58 | + bdd.deref(f2); | |
59 | + return f; | |
60 | + } | |
42 | 61 | } |
43 | 62 | |
44 | 63 | class EqualityOperator extends BooleanBinaryOperator { |
@@ -51,6 +70,16 @@ class EqualityOperator extends BooleanBinaryOperator { | ||
51 | 70 | bdd.deref(f2); |
52 | 71 | return f; |
53 | 72 | } |
73 | + | |
74 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
75 | + int f1 = Left.evaluate(bdd, parameters, restricted); | |
76 | + int f2 = Right.evaluate(bdd, parameters, restricted); | |
77 | + int f = bdd.not(bdd.xor(f1, f2)); | |
78 | + bdd.ref(f); | |
79 | + bdd.deref(f1); | |
80 | + bdd.deref(f2); | |
81 | + return f; | |
82 | + } | |
54 | 83 | } |
55 | 84 | |
56 | 85 | class InequalityOperator extends BooleanBinaryOperator { |
@@ -63,6 +92,16 @@ class InequalityOperator extends BooleanBinaryOperator { | ||
63 | 92 | bdd.deref(f2); |
64 | 93 | return f; |
65 | 94 | } |
95 | + | |
96 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
97 | + int f1 = Left.evaluate(bdd, parameters, restricted); | |
98 | + int f2 = Right.evaluate(bdd, parameters, restricted); | |
99 | + int f = bdd.xor(f1, f2); | |
100 | + bdd.ref(f); | |
101 | + bdd.deref(f1); | |
102 | + bdd.deref(f2); | |
103 | + return f; | |
104 | + } | |
66 | 105 | } |
67 | 106 | |
68 | 107 | abstract class BooleanTrinaryOperator extends BooleanOperator { |
@@ -81,6 +120,18 @@ class IfthenelseOperator extends BooleanTrinaryOperator { | ||
81 | 120 | bdd.deref(f3); |
82 | 121 | return f; |
83 | 122 | } |
123 | + | |
124 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
125 | + int f1 = Left.evaluate(bdd, parameters, restricted); | |
126 | + int f2 = Middle.evaluate(bdd, parameters, restricted); | |
127 | + int f3 = Right.evaluate(bdd, parameters, restricted); | |
128 | + int f = bdd.ite(f1, f2, f3); | |
129 | + bdd.ref(f); | |
130 | + bdd.deref(f1); | |
131 | + bdd.deref(f2); | |
132 | + bdd.deref(f3); | |
133 | + return f; | |
134 | + } | |
84 | 135 | } |
85 | 136 | |
86 | 137 | abstract class BooleanMultinaryOperator extends BooleanOperator { |
@@ -107,6 +158,25 @@ class OrOperator extends BooleanMultinaryOperator { | ||
107 | 158 | } |
108 | 159 | return f; |
109 | 160 | } |
161 | + | |
162 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
163 | + int f1 = ChildList.get(0).evaluate(bdd, parameters, restricted); | |
164 | + int f2 = ChildList.get(1).evaluate(bdd, parameters, restricted); | |
165 | + int f = bdd.or(f1, f2); | |
166 | + bdd.ref(f); | |
167 | + bdd.deref(f1); | |
168 | + bdd.deref(f2); | |
169 | + | |
170 | + for (int i = 2; i < ChildList.size(); i++) { | |
171 | + f1 = f; | |
172 | + f2 = ChildList.get(i).evaluate(bdd, parameters, restricted); | |
173 | + f = bdd.or(f1, f2); | |
174 | + bdd.ref(f); | |
175 | + bdd.deref(f1); | |
176 | + bdd.deref(f2); | |
177 | + } | |
178 | + return f; | |
179 | + } | |
110 | 180 | } |
111 | 181 | |
112 | 182 | class AndOperator extends BooleanMultinaryOperator { |
@@ -128,6 +198,25 @@ class AndOperator extends BooleanMultinaryOperator { | ||
128 | 198 | } |
129 | 199 | return f; |
130 | 200 | } |
201 | + | |
202 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
203 | + int f1 = ChildList.get(0).evaluate(bdd, parameters, restricted); | |
204 | + int f2 = ChildList.get(1).evaluate(bdd, parameters, restricted); | |
205 | + int f = bdd.and(f1, f2); | |
206 | + bdd.ref(f); | |
207 | + bdd.deref(f1); | |
208 | + bdd.deref(f2); | |
209 | + | |
210 | + for (int i = 2; i < ChildList.size(); i++) { | |
211 | + f1 = f; | |
212 | + f2 = ChildList.get(i).evaluate(bdd, parameters, restricted); | |
213 | + f = bdd.and(f1, f2); | |
214 | + bdd.ref(f); | |
215 | + bdd.deref(f1); | |
216 | + bdd.deref(f2); | |
217 | + } | |
218 | + return f; | |
219 | + } | |
131 | 220 | } |
132 | 221 | |
133 | 222 | abstract class AtomicExpression extends Node { |
@@ -143,6 +232,13 @@ class TrueValue extends Constant { | ||
143 | 232 | bdd.ref(f); |
144 | 233 | return f; |
145 | 234 | } |
235 | + | |
236 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
237 | + | |
238 | + int f = bdd.getOne(); | |
239 | + bdd.ref(f); | |
240 | + return f; | |
241 | + } | |
146 | 242 | } |
147 | 243 | |
148 | 244 | class FalseValue extends Constant { |
@@ -151,6 +247,12 @@ class FalseValue extends Constant { | ||
151 | 247 | bdd.ref(f); |
152 | 248 | return f; |
153 | 249 | } |
250 | + | |
251 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
252 | + int f = bdd.getZero(); | |
253 | + bdd.ref(f); | |
254 | + return f; | |
255 | + } | |
154 | 256 | } |
155 | 257 | |
156 | 258 | abstract class ComparisonOfValueAndValue extends AtomicExpression { |
@@ -178,6 +280,8 @@ class EqualityOfParameterAndValue extends ComparisonOfParameterAndValue { | ||
178 | 280 | int evaluate(BDD bdd, List<VariableAndBDD> parameters) { |
179 | 281 | int res = bdd.getOne(); |
180 | 282 | bdd.ref(res); |
283 | + // pは(絶対値で)パラメータの番号が既にはいっている | |
284 | + // | |
181 | 285 | int[] var = parameters.get(this.p).var; |
182 | 286 | for (int i = var.length - 1; i >= 0; i--) { |
183 | 287 | if ((this.v & (0x01 << i)) > 0) { |
@@ -193,4 +297,32 @@ class EqualityOfParameterAndValue extends ComparisonOfParameterAndValue { | ||
193 | 297 | bdd.ref(res); |
194 | 298 | return res; |
195 | 299 | } |
300 | + | |
301 | + | |
302 | + int evaluate(BDD bdd, List<VariableAndBDD> parameters, Set<Integer> restricted) { | |
303 | + int res = bdd.getOne(); | |
304 | + bdd.ref(res); | |
305 | + // pは(絶対値で)パラメータの番号が既にはいっている | |
306 | + int num = 0; | |
307 | + for (Integer i: restricted) { | |
308 | + if (i == this.p) | |
309 | + break; | |
310 | + num++; | |
311 | + } | |
312 | + | |
313 | + int[] var = parameters.get(num).var; | |
314 | + for (int i = var.length - 1; i >= 0; i--) { | |
315 | + if ((this.v & (0x01 << i)) > 0) { | |
316 | + int tmp = bdd.ref(bdd.and(res, var[i])); | |
317 | + bdd.deref(res); | |
318 | + res = tmp; | |
319 | + } else { | |
320 | + int tmp = bdd.ref(bdd.and(res, bdd.not(var[i]))); | |
321 | + bdd.deref(res); | |
322 | + res = tmp; | |
323 | + } | |
324 | + } | |
325 | + bdd.ref(res); | |
326 | + return res; | |
327 | + } | |
196 | 328 | } |
\ No newline at end of file |
@@ -104,6 +104,24 @@ class PList extends LinkedList<Parameter> { | ||
104 | 104 | } |
105 | 105 | throw new NoParameterNameException(); |
106 | 106 | } |
107 | + | |
108 | + // useless? | |
109 | + int getRestrictedID(String str, TreeSet<Integer> RestrictedParameters) | |
110 | + throws NoParameterNameException { | |
111 | + try { | |
112 | + int parameter = this.getID(str); | |
113 | + int num = 0; | |
114 | + for (Integer i: RestrictedParameters) { | |
115 | + if (i == parameter) | |
116 | + return num; | |
117 | + num++; | |
118 | + } | |
119 | + } catch (NoParameterNameException e) { | |
120 | + throw e; | |
121 | + } | |
122 | + // if the parameter is not a relevant one | |
123 | + throw new NoParameterNameException(); | |
124 | + } | |
107 | 125 | } |
108 | 126 | |
109 | 127 | class NoParameterNameException extends Exception { |