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

http://testability-explorer.googlecode.com/ · Java · 173 lines · 135 code · 16 blank · 22 comment · 22 complexity · 67887d406cbf87fb0c3958c69e56099f 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. */
  16. package com.google.test.metric.method;
  17. import static java.util.Arrays.asList;
  18. import java.util.ArrayList;
  19. import java.util.HashSet;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.Set;
  23. import com.google.test.metric.JavaType;
  24. import com.google.test.metric.Variable;
  25. import com.google.test.metric.collection.KeyedMultiStack;
  26. import com.google.test.metric.collection.PopClosure;
  27. import com.google.test.metric.collection.KeyedMultiStack.ValueCompactor;
  28. import com.google.test.metric.method.op.stack.JSR;
  29. import com.google.test.metric.method.op.stack.StackOperation;
  30. import com.google.test.metric.method.op.turing.Operation;
  31. public class Stack2Turing {
  32. public static final Object EMPTY = new Object();
  33. public static class VariableCompactor extends ValueCompactor<Variable> {
  34. @Override
  35. public List<List<Variable>> compact(List<List<Variable>> pushValues) {
  36. if (pushValues.size() < 2) {
  37. return pushValues;
  38. }
  39. ArrayList<List<Variable>> compacted = new ArrayList<List<Variable>>();
  40. Set<Object> equivalent = new HashSet<Object>();
  41. Iterator<List<Variable>> iter;
  42. for (iter = pushValues.iterator(); iter.hasNext();) {
  43. List<Variable> values = iter.next();
  44. Object key = computeKey(values);
  45. if (equivalent.add(key)) {
  46. compacted.add(values);
  47. }
  48. }
  49. return compacted;
  50. }
  51. private Object computeKey(List<Variable> variables) {
  52. int size = variables.size();
  53. if (size == 0) {
  54. return EMPTY;
  55. } else if (size == 1) {
  56. return computeKey(variables.get(0));
  57. } else {
  58. ArrayList<Object> keys = new ArrayList<Object>();
  59. for (Variable variable : variables) {
  60. keys.add(computeKey(variable));
  61. }
  62. return keys;
  63. }
  64. }
  65. private Object computeKey(Variable variable) {
  66. Object key;
  67. if (variable instanceof Constant) {
  68. Constant constant = (Constant) variable;
  69. key = constant.getType();
  70. } else {
  71. key = variable;
  72. }
  73. return key;
  74. }
  75. }
  76. private final Block rootBlock;
  77. private final List<Operation> operations = new ArrayList<Operation>();
  78. private final ValueCompactor<Variable> pathCompactor = new VariableCompactor();
  79. public KeyedMultiStack<Block, Variable> stack = new KeyedMultiStack<Block, Variable>(
  80. pathCompactor);
  81. public Stack2Turing(Block block) {
  82. this.rootBlock = block;
  83. }
  84. public List<Operation> translate() {
  85. stack.init(rootBlock);
  86. translate(rootBlock, new ArrayList<Block>());
  87. return operations;
  88. }
  89. private Block translate(Block block, List<Block> parentProcessed) {
  90. List<Block> blocks = new ArrayList<Block>();
  91. List<Block> processed = parentProcessed;
  92. blocks.add(block);
  93. while (!blocks.isEmpty()) {
  94. block = blocks.remove(0);
  95. processed.add(block);
  96. for (StackOperation operation : block.getOperations()) {
  97. translateStackOperation(block, operation);
  98. if (operation instanceof JSR) {
  99. JSR jsr = (JSR) operation;
  100. Block jsrBlock = jsr.getBlock();
  101. stack.split(block, asList(jsrBlock));
  102. Block terminalBlock = translate(jsrBlock, processed);
  103. stack.join(asList(terminalBlock), block);
  104. processed.add(jsrBlock);
  105. }
  106. }
  107. List<Block> nextBlocks = new ArrayList<Block>(block.getNextBlocks());
  108. nextBlocks.removeAll(processed); // Don't visit already visited
  109. // blocks
  110. if (nextBlocks.size() > 0) {
  111. stack.split(block, nextBlocks);
  112. }
  113. blocks.addAll(nextBlocks);
  114. blocks.removeAll(processed);
  115. }
  116. // It appears that when exceptions are involved a method might have
  117. // paths where stacks are not emptied. So we can't assert this.
  118. // Verdict is still out.
  119. // stack.assertEmpty();
  120. return block;
  121. }
  122. private void translateStackOperation(Block block,
  123. final StackOperation operation) {
  124. stack.apply(block, new PopClosure<Block, Variable>() {
  125. @Override
  126. public List<Variable> pop(Block key, List<Variable> input) {
  127. List<Variable> variables = operation.apply(input);
  128. // For performance reasons the line is commented out.
  129. // assertValid(variables);
  130. Operation turingOp = operation.toOperation(input);
  131. if (turingOp != null) {
  132. operations.add(turingOp);
  133. }
  134. return variables;
  135. }
  136. @Override
  137. public int getSize() {
  138. return operation.getOperatorCount();
  139. }
  140. });
  141. }
  142. protected void assertValid(List<Variable> variables) {
  143. Iterator<Variable> iter = variables.iterator();
  144. while (iter.hasNext()) {
  145. final Variable variable = iter.next();
  146. if (JavaType.isDoubleSlot(variable.getType())) {
  147. Variable varNext = iter.hasNext() ? iter.next() : null;
  148. if (variable != varNext) {
  149. throw new IllegalStateException("Variable list '" + variables
  150. + "' contanins variable '" + variable
  151. + "' which is a double but the next "
  152. + "variable in the list is not a duplicate.");
  153. }
  154. }
  155. }
  156. }
  157. }