| package org.junit.tests.experimental.theories.extendingwithstubs; |
| |
| import java.lang.reflect.InvocationHandler; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Proxy; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map.Entry; |
| import java.util.Random; |
| |
| import org.hamcrest.BaseDescription; |
| import org.hamcrest.Description; |
| import org.junit.internal.AssumptionViolatedException; |
| |
| public class Guesser<T> extends ReguessableValue { |
| static class GuessMap extends HashMap<MethodCall, Object> implements |
| InvocationHandler { |
| private static final long serialVersionUID = 1L; |
| |
| public GuessMap(GuessMap guesses) { |
| super(guesses); |
| } |
| |
| public GuessMap() { |
| } |
| |
| GuessMap replaceGuess(Object oldValue, Object newValue) { |
| GuessMap newGuesses = new GuessMap(this); |
| for (Entry<MethodCall, Object> entry : newGuesses.entrySet()) { |
| if (entry.getValue().equals(oldValue)) { |
| entry.setValue(newValue); |
| } |
| } |
| return newGuesses; |
| } |
| |
| protected Object generateGuess(Class<?> returnType) { |
| if (returnType.equals(String.class)) { |
| return "GUESS" + new Random().nextInt(); |
| } |
| if (returnType.equals(Integer.class) |
| || returnType.equals(int.class)) { |
| return new Random().nextInt(); |
| } |
| return null; |
| } |
| |
| Object getGuess(MethodCall call) { |
| if (!containsKey(call)) { |
| put(call, generateGuess(call.getReturnType())); |
| } |
| return get(call); |
| } |
| |
| public Object invoke(Object proxy, Method method, Object[] args) |
| throws Throwable { |
| return getGuess(new MethodCall(method, args)); |
| } |
| } |
| |
| private final GuessMap guesses; |
| |
| private final Class<? extends T> type; |
| |
| public Guesser(Class<? extends T> type) { |
| this(type, new GuessMap()); |
| } |
| |
| public Guesser(Class<? extends T> type2, GuessMap guesses) { |
| this.type = type2; |
| this.guesses = guesses; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public T getProxy() { |
| return (T) Proxy.newProxyInstance(getClass().getClassLoader(), |
| new Class[]{getType()}, guesses); |
| } |
| |
| @Override |
| public List<ReguessableValue> reguesses(AssumptionViolatedException e) { |
| final ArrayList<ReguessableValue> returnThis = new ArrayList<ReguessableValue>(); |
| e.describeTo(new BaseDescription() { |
| @Override |
| protected void append(char arg0) { |
| } |
| |
| boolean expectedSeen = false; |
| Object expected = null; |
| |
| @Override |
| public Description appendValue(Object value) { |
| noteValue(value); |
| return super.appendValue(value); |
| } |
| |
| private void noteValue(Object value) { |
| if (!expectedSeen) { |
| expected = value; |
| expectedSeen = true; |
| return; |
| } |
| |
| GuessMap newGuesses = guesses.replaceGuess(expected, value); |
| returnThis.add(new Guesser<T>(getType(), newGuesses)); |
| } |
| }); |
| return returnThis; |
| } |
| |
| @Override |
| public Object getValue() throws CouldNotGenerateValueException { |
| return getProxy(); |
| } |
| |
| public Class<? extends T> getType() { |
| return type; |
| } |
| |
| @Override |
| public String getDescription() throws CouldNotGenerateValueException { |
| return "guesser[" + type + "]"; |
| } |
| |
| } |