PageRenderTime 60ms CodeModel.GetById 17ms app.highlight 35ms RepoModel.GetById 2ms app.codeStats 0ms

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