PageRenderTime 33ms CodeModel.GetById 2ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 0ms

/testability-explorer/src/test/java/com/google/test/metric/method/BlockDecomposerTest.java

http://testability-explorer.googlecode.com/
Java | 452 lines | 313 code | 53 blank | 86 comment | 0 complexity | d04ccbc5713cf5036cf872a781227710 MD5 | raw file
  1/*
  2 * Copyright 2007 Google Inc.
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5 * use this file except in compliance with the License. You may obtain a copy of
  6 * the License at
  7 *
  8 * http://www.apache.org/licenses/LICENSE-2.0
  9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 13 * License for the specific language governing permissions and limitations under
 14 * the License.
 15 */
 16package com.google.test.metric.method;
 17
 18import static com.google.test.metric.JavaType.VOID;
 19
 20import java.util.Arrays;
 21import java.util.List;
 22
 23import junit.framework.TestCase;
 24
 25import org.objectweb.asm.Label;
 26
 27import com.google.test.metric.JavaClassRepository;
 28import com.google.test.metric.JavaType;
 29import com.google.test.metric.LocalVariableInfo;
 30import com.google.test.metric.Variable;
 31import com.google.test.metric.method.op.stack.JSR;
 32import com.google.test.metric.method.op.stack.Load;
 33import com.google.test.metric.method.op.stack.RetSub;
 34import com.google.test.metric.method.op.stack.Return;
 35import com.google.test.metric.method.op.stack.StackOperation;
 36import com.google.test.metric.method.op.stack.Store;
 37import com.google.test.metric.method.op.stack.Throw;
 38import com.google.test.metric.method.op.turing.Operation;
 39
 40public class BlockDecomposerTest extends TestCase {
 41
 42
 43  public void testSimpleLinearMethod() throws Exception {
 44    BlockDecomposer decomposer = new BlockDecomposer();
 45    Return ret = new Return(0, VOID);
 46    decomposer.addOp(ret);
 47    decomposer.decomposeIntoBlocks();
 48
 49    Block block = decomposer.getMainBlock();
 50    assertEquals(list(ret), block.getOperations());
 51  }
 52
 53  public void testUnconditionalBackwardGoto() throws Exception {
 54    BlockDecomposer decomposer = new BlockDecomposer();
 55    Label label = new Label();
 56    Load l1 = load(1);
 57    Load l2 = load(2);
 58    decomposer.addOp(l1);
 59    decomposer.label(label);
 60    decomposer.addOp(l2);
 61    decomposer.unconditionalGoto(label);
 62    decomposer.decomposeIntoBlocks();
 63
 64    Block main = decomposer.getMainBlock();
 65    assertEquals(list(l1), main.getOperations());
 66
 67    assertEquals(1, main.getNextBlocks().size());
 68    Block next = main.getNextBlocks().get(0);
 69    assertEquals(list(l2), next.getOperations());
 70  }
 71
 72
 73  public void testUnconditionalForwardGoto() throws Exception {
 74    BlockDecomposer decomposer = new BlockDecomposer();
 75    Label label = new Label();
 76    Load l1 = load(1);
 77    Load l2 = load(2);
 78    decomposer.addOp(l1);
 79    decomposer.unconditionalGoto(label);
 80    decomposer.label(label);
 81    decomposer.addOp(l2);
 82    decomposer.decomposeIntoBlocks();
 83
 84    Block main = decomposer.getMainBlock();
 85    assertEquals(list(l1), main.getOperations());
 86
 87    assertEquals(1, main.getNextBlocks().size());
 88    Block next = main.getNextBlocks().get(0);
 89    assertEquals(list(l2), next.getOperations());
 90  }
 91
 92
 93  public void testConditionalBackwardGoto() throws Exception {
 94    BlockDecomposer decomposer = new BlockDecomposer();
 95    Label label = new Label();
 96    Load l1 = load(1);
 97    Load l2 = load(2);
 98    Load l3 = load(3);
 99    decomposer.addOp(l1);
100    decomposer.label(label);
101    decomposer.addOp(l2);
102    decomposer.conditionalGoto(label);
103    decomposer.addOp(l3);
104    decomposer.decomposeIntoBlocks();
105
106    Block main = decomposer.getMainBlock();
107    Block nextTrue = decomposer.getBlock(label);
108    Block nextFlase = nextTrue.getNextBlocks().get(0);
109    assertEquals(list(l1), main.getOperations());
110    assertEquals(list(l2), nextTrue.getOperations());
111    assertEquals(list(l3), nextFlase.getOperations());
112  }
113
114
115  public void testConditionalForwardGoto() throws Exception {
116    BlockDecomposer decomposer = new BlockDecomposer();
117    Label label = new Label();
118    Load l1 = load(1);
119    Load l2 = load(2);
120    Load l3 = load(3);
121    decomposer.addOp(l1); // main
122    decomposer.conditionalGoto(label);
123    decomposer.addOp(l2); // nextFalse
124    decomposer.label(label);
125    decomposer.addOp(l3); // nextTrue
126    decomposer.decomposeIntoBlocks();
127
128    Block main = decomposer.getMainBlock();
129    Block nextFlase = main.getNextBlocks().get(0);
130    Block nextTrue = decomposer.getBlock(label);
131    assertEquals(list(l1), main.getOperations());
132    assertEquals(list(l2), nextFlase.getOperations());
133    assertEquals(list(l3), nextTrue.getOperations());
134  }
135
136
137
138  private <T> List<T> list(T...items) {
139    return Arrays.asList(items);
140  }
141
142  public void testIgnoreExtraLabels() throws Exception {
143    BlockDecomposer decomposer = new BlockDecomposer();
144    Load l1 = load(1);
145    Load l2 = load(2);
146    decomposer.label(new Label());
147    decomposer.addOp(l1);
148    decomposer.addOp(l2);
149    decomposer.label(new Label());
150    decomposer.decomposeIntoBlocks();
151
152    assertEquals(list(l1, l2), decomposer.getMainBlock().getOperations());
153  }
154
155  /**
156   * load 1
157   * jsr mySub
158   * load 2
159   * return
160   *
161   * mySub:
162   * load 3
163   * return;
164   */
165  public void testJSR() throws Exception {
166    BlockDecomposer decomposer = new BlockDecomposer();
167    decomposer.addOp(load(1));
168    Label sub = new Label();
169    decomposer.jumpSubroutine(sub, 0);
170    decomposer.addOp(load(2));
171    decomposer.addOp(new Return(0, VOID));
172    decomposer.label(sub);
173    decomposer.addOp(load(3));
174    decomposer.addOp(new RetSub(0));
175    decomposer.decomposeIntoBlocks();
176
177    Block mainBlock = decomposer.getMainBlock();
178    assertEquals(0, mainBlock.getNextBlocks().size());
179    List<StackOperation> operations = mainBlock.getOperations();
180    assertEquals("[load 1{int}, JSR sub_0, load 2{int}, return void]",
181        operations.toString());
182    JSR jsr = (JSR) operations.get(1);
183    Block subBlock = jsr.getBlock();
184    assertEquals("[load 3{int}, RETSUB]", subBlock.getOperations().toString());
185  }
186
187  private Load load(int value) {
188    return new Load(0, new Constant(value, JavaType.INT));
189  }
190
191  public void testSwitch() throws Exception {
192    BlockDecomposer decomposer = new BlockDecomposer();
193    Load l1 = load(1);
194    Label c1Label = new Label();
195    Load c1 = load(2);
196    Label defLabel = new Label();
197    Load def = load(3);
198    decomposer.addOp(l1);
199    decomposer.tableSwitch(defLabel, c1Label);
200    decomposer.label(c1Label);
201    decomposer.addOp(c1);
202    decomposer.label(defLabel);
203    decomposer.addOp(def);
204    decomposer.decomposeIntoBlocks();
205
206    Block main = decomposer.getMainBlock();
207    Block c1Block = decomposer.getBlock(c1Label);
208    Block defBlock = decomposer.getBlock(defLabel);
209    assertEquals(list(l1), main.getOperations());
210    assertEquals(list(c1), c1Block.getOperations());
211    assertEquals(list(def), defBlock.getOperations());
212    assertEquals(list(c1Block, defBlock), main.getNextBlocks());
213  }
214
215  public void testTryCatchReturn() throws Exception {
216    /*
217     * try {        | label:lTry
218     *   return 1;  | label:lTryEnd
219     * } catch {    | label:lHandle
220     *   return 2;
221     * }
222     */
223    Label lTry = new Label();
224    Load l1 = load(1);
225    Load l2 = load(2);
226    Return ret = new Return(1, JavaType.INT);
227    Label lTryEnd = new Label();
228    Label lHandle = new Label();
229
230    BlockDecomposer decomposer = new BlockDecomposer();
231    decomposer.tryCatchBlock(lTry, lTryEnd, lHandle, null);
232    decomposer.label(lTry);
233    decomposer.addOp(l1);
234    decomposer.label(lTryEnd); // the catch label comes before the last instruction.
235    decomposer.addOp(ret);
236    decomposer.label(lHandle);
237    decomposer.addOp(l2);
238    decomposer.addOp(ret);
239    decomposer.decomposeIntoBlocks();
240
241    Block tryBlock = decomposer.getBlock(lTry);
242    Block handleBlock = decomposer.getBlock(lHandle);
243    assertEquals(list(), tryBlock.getNextBlocks());
244    assertEquals(list(l1, ret), tryBlock.getOperations());
245    assertEquals("[load ?{java.lang.Throwable}, load 2{int}, return int]",
246        handleBlock.getOperations().toString());
247  }
248
249  public void testGetExceptionHandlerBlocks() throws Exception {
250    /*
251     * try {        | label:lTry
252     *   a = 1;
253     *   return 1;  | label:lTryEnd
254     * } catch {    | label:lHandle
255     *   a = 2;
256     *   return 2;
257     * }
258     */
259    Label lTry = new Label();
260    Load l1 = load(1);
261    Load l2 = load(2);
262    Store store = new Store(-1, new Variable("a", JavaType.INT, false, false));
263    Return ret = new Return(1, JavaType.INT);
264    Label lTryEnd = new Label();
265    Label lHandle = new Label();
266
267    BlockDecomposer decomposer = new BlockDecomposer();
268    decomposer.tryCatchBlock(lTry, lTryEnd, lHandle, null);
269    decomposer.label(lTry);
270    decomposer.addOp(l1);
271    decomposer.addOp(store);
272    decomposer.label(lTryEnd); // the catch label comes before the last instruction.
273    decomposer.addOp(l1);
274    decomposer.addOp(ret);
275    decomposer.label(lHandle);
276    decomposer.addOp(l2);
277    decomposer.addOp(store);
278    decomposer.addOp(l2);
279    decomposer.addOp(ret);
280    decomposer.decomposeIntoBlocks();
281
282    Block mainBlock = decomposer.getMainBlock();
283    assertEquals(0, mainBlock.getNextBlocks().size());
284    assertEquals(list(l1, store, l1, ret), mainBlock.getOperations());
285
286    Block catchBlock = decomposer.getBlock(lHandle);
287    assertEquals(0, catchBlock.getNextBlocks().size());
288    assertEquals(
289        "[load ?{java.lang.Throwable}, load 2{int}, store a{int}, load 2{int}, return int]",
290        catchBlock.getOperations().toString());
291
292    assertEquals(
293        "[a{int} <- 1{int}, return 1{int}, a{int} <- 2{int}, return 2{int}]",
294        decomposer.getOperations().toString());
295  }
296
297  /**
298   *   public static class TryCatchFinally {
299   *   public void method() {
300   *     int b = 1;
301   *     try {
302   *       b = 2;
303   *       return;
304   *     } catch (RuntimeException e) {
305   *       b = 3;
306   *     } finally {
307   *       b = 4;
308   *     }
309   *     b = 5;
310   *   }
311   *  }
312   *
313   *
314   *  public void method();
315   *  Code:
316   *   0:   iconst_1
317   *   1:   istore_1
318   *   2:   iconst_2
319   *   3:   istore_1
320   *   4:   goto    20
321   *   7:   astore_2
322   *   8:   iconst_3
323   *   9:   istore_1
324   *   10:  iconst_4
325   *   11:  istore_1
326   *   12:  goto    22
327   *   15:  astore_3
328   *   16:  iconst_4
329   *   17:  istore_1
330   *   18:  aload_3
331   *   19:  athrow
332   *   20:  iconst_4
333   *   21:  istore_1
334   *   22:  iconst_5
335   *   23:  istore_1
336   *   24:  return
337   *  Exception table:
338   *   from   to  target type
339   *     2     4     7   Class java/lang/RuntimeException
340   *     2    10    15   any
341   */
342  public void testTryCatchFinally() throws Exception {
343    BlockDecomposer decomposer = new BlockDecomposer();
344    Label tryStart = new Label();
345    Label tryEnd = new Label();
346    Label runtimeHandler = new Label();
347    Label catchEnd = new Label();
348    Label finallyHandler = new Label();
349    Label l20 = new Label();
350    Label l22 = new Label();
351    Variable b = new LocalVariableInfo("b", JavaType.INT);
352    Variable e = new LocalVariableInfo("e", JavaType.OBJECT);
353    Variable any = new LocalVariableInfo("any", JavaType.OBJECT);
354    decomposer.tryCatchBlock(tryStart, tryEnd, runtimeHandler, "java/lang/RuntimeException");
355    decomposer.tryCatchBlock(tryStart, catchEnd, finallyHandler, null);
356
357    /* 0*/ decomposer.addOp(new Load(0, new Constant(1, JavaType.INT)));
358    /* 1*/ decomposer.addOp(new Store(1, b));
359    decomposer.label(tryStart);
360    /* 2*/ decomposer.addOp(new Load(2, new Constant(2, JavaType.INT)));
361    decomposer.label(tryEnd);
362    /* 3*/ decomposer.addOp(new Store(3, b));
363    /* 4*/ decomposer.unconditionalGoto(l20);
364    decomposer.label(runtimeHandler);
365    /* 7*/ decomposer.addOp(new Store(7, e));
366    /* 8*/ decomposer.addOp(new Load(8, new Constant(3, JavaType.INT)));
367    /* 9*/ decomposer.addOp(new Store(9, b));
368    decomposer.label(catchEnd);
369    /*10*/ decomposer.addOp(new Load(10, new Constant(4, JavaType.INT)));
370    /*11*/ decomposer.addOp(new Store(11, b));
371    /*12*/ decomposer.unconditionalGoto(l22);
372    decomposer.label(finallyHandler);
373    /*15*/ decomposer.addOp(new Store(15, any));
374    /*16*/ decomposer.addOp(new Load(16, new Constant(4, JavaType.INT)));
375    /*17*/ decomposer.addOp(new Store(17, b));
376    /*18*/ decomposer.addOp(new Load(18, any));
377    /*19*/ decomposer.addOp(new Throw(19));
378    decomposer.label(l20);
379    /*20*/ decomposer.addOp(new Load(20, new Constant(4, JavaType.INT)));
380    /*21*/ decomposer.addOp(new Store(21, b));
381    decomposer.label(l22);
382    /*22*/ decomposer.addOp(new Load(22, new Constant(4, JavaType.INT)));
383    /*23*/ decomposer.addOp(new Store(23, b));
384    /*24*/ decomposer.addOp(new Return(24, JavaType.VOID));
385
386    decomposer.decomposeIntoBlocks();
387
388    assertEquals("[load 1{int}, store b{int}, load 2{int}, store b{int}]",
389        decomposer.getBlock(tryStart).getOperations().toString());
390  }
391
392  public void testMethodWithNothing() throws Exception {
393    BlockDecomposer decomposer = new BlockDecomposer();
394    decomposer.decomposeIntoBlocks();
395    List<Operation> operations = decomposer.getOperations();
396    assertEquals(0, operations.size());
397  }
398
399  public void testTwoJsrSameLabel() throws Exception {
400    BlockDecomposer decomposer = new BlockDecomposer();
401    Label label = new Label();
402    decomposer.jumpSubroutine(label, 0);
403    decomposer.jumpSubroutine(label, 0);
404    decomposer.decomposeIntoBlocks();
405
406    Block main = decomposer.getMainBlock();
407    assertEquals("[JSR sub_0, JSR sub_0]", main.getOperations().toString());
408  }
409
410  public void testMultipleHandlersSingleExceptionLoad() throws Exception {
411    BlockDecomposer decomposer = new BlockDecomposer();
412    Label start = new Label();
413    Label end = new Label();
414    Label handler = new Label();
415    decomposer.tryCatchBlock(start, end, handler, null);
416    decomposer.tryCatchBlock(start, end, handler, null);
417    decomposer.label(start);
418    decomposer.addOp(load(1));
419    decomposer.label(end);
420    decomposer.addOp(load(2));
421    decomposer.label(handler);
422    decomposer.addOp(load(3));
423    decomposer.decomposeIntoBlocks();
424
425    assertEquals(
426        "[load ?{java.lang.Throwable}, load 1{int}, load 2{int}, load 3{int}]",
427        decomposer.getMainBlock().getOperations().toString());
428  }
429
430  public static class TestClass {
431    int value;
432    int method() {
433      value = 0;
434      try {
435        value = 1;
436        return -1;
437      } catch (NullPointerException e) {
438        value = 2;
439        return -2;
440      } finally {
441        value = 3;
442      }
443
444    }
445  }
446
447  public void testExperiment() throws Exception {
448    JavaClassRepository repo = new JavaClassRepository();
449    repo.getClass(TestClass.class.getCanonicalName());
450  }
451
452}