1 5 package com.tctest; 6 7 import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier; 8 9 import com.tc.object.config.ConfigVisitor; 10 import com.tc.object.config.DSOClientConfigHelper; 11 import com.tc.object.config.TransparencyClassSpec; 12 import com.tc.object.config.spec.CyclicBarrierSpec; 13 import com.tc.simulator.app.ApplicationConfig; 14 import com.tc.simulator.listener.ListenerProvider; 15 import com.tctest.runner.AbstractTransparentApp; 16 17 import java.lang.reflect.InvocationTargetException ; 18 import java.lang.reflect.Method ; 19 import java.util.ArrayList ; 20 import java.util.Collections ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 public abstract class GenericTestApp extends AbstractTransparentApp { 27 28 private static final String METHOD_PREFIX = "test"; 29 private static final String METHOD_PATTERN = "^" + METHOD_PREFIX + ".*$"; 30 31 private final CyclicBarrier barrier; 33 private final CyclicBarrier barrier2; 34 private final Exit exit = new Exit(); 35 protected final Map sharedMap = new HashMap (); 36 37 private final Class type; 38 private final List tests; 39 40 public GenericTestApp(String appId, ApplicationConfig cfg, ListenerProvider listenerProvider, Class type) { 41 super(appId, cfg, listenerProvider); 42 43 final int count = getParticipantCount(); 44 if (count < 2) { throw new RuntimeException ("wrong number of nodes: " + count); } 45 46 this.barrier = new CyclicBarrier(getParticipantCount()); 47 this.barrier2 = new CyclicBarrier(getParticipantCount()); 48 49 this.type = type; 50 this.tests = getTestNames(); 51 } 52 53 public final void run() { 54 try { 55 runTest(); 56 } catch (Throwable t) { 57 notifyError(t); 58 } 59 } 60 61 protected abstract Object getTestObject(String testName); 62 63 protected abstract void setupTestObject(String testName); 64 65 private void makeTestObject(String test) { 66 synchronized (sharedMap) { 67 sharedMap.clear(); setupTestObject(test); 69 } 70 } 71 72 private void runTest() throws Throwable { 73 int num = barrier.barrier(); 74 boolean mutator = (num == 0); 75 76 if (mutator) { 77 doMutate(); 78 } else { 79 doValidate(); 80 } 81 } 82 83 private void doValidate() throws Throwable { 84 Thread.currentThread().setName("VALIDATOR " + getApplicationId()); 85 for (Iterator i = tests.iterator(); i.hasNext();) { 86 String name = (String ) i.next(); 87 barrier.barrier(); 88 89 if (exit.shouldExit()) { return; } 90 91 try { 92 runOp(name, true); 93 } catch (Throwable t) { 94 exit.toggle(); 95 throw t; 96 } finally { 97 barrier2.barrier(); 98 } 99 100 if (exit.shouldExit()) { return; } 101 } 102 } 103 104 private void doMutate() throws Throwable { 105 Thread.currentThread().setName("MUTATOR " + getApplicationId()); 106 for (Iterator i = tests.iterator(); i.hasNext();) { 107 String name = (String ) i.next(); 108 System.err.print("Running test: " + name + " ... "); 109 long start = System.currentTimeMillis(); 110 111 try { 112 runOp(name, false); 113 runOp(name, true); 114 } catch (Throwable t) { 115 exit.toggle(); 116 throw t; 117 } finally { 118 barrier.barrier(); 119 120 if (!exit.shouldExit()) { 121 barrier2.barrier(); 122 } 123 } 124 125 System.err.println(" took " + (System.currentTimeMillis() - start) + " millis"); 126 127 if (exit.shouldExit()) { return; } 128 } 129 } 130 131 private void runOp(String op, boolean validate) throws Throwable { 132 Method m = findMethod(op); 133 134 if (!validate) { 135 makeTestObject(op); 136 } 137 138 Object object = getTestObject(op); 139 140 if (object instanceof Iterator ) { 141 for (Iterator i = (Iterator ) object; i.hasNext();) { 143 runMethod(m, i.next(), validate); 144 } 145 } else { 146 runMethod(m, object, validate); 147 } 148 } 149 150 private void runMethod(Method m, Object object, boolean validate) throws Throwable { 151 try { 152 m.invoke(this, new Object [] { object, Boolean.valueOf(validate) }); 153 } catch (InvocationTargetException ite) { 154 throw ite.getTargetException(); 155 } 156 } 157 158 private Method findMethod(String name) throws NoSuchMethodException { 159 Method method = getClass().getDeclaredMethod(METHOD_PREFIX + name, new Class [] { type, Boolean.TYPE }); 160 method.setAccessible(true); 161 return method; 162 } 163 164 private List getTestNames() { 165 List rv = new ArrayList (); 166 Class klass = getClass(); 167 Method [] methods = klass.getDeclaredMethods(); 168 for (int i = 0; i < methods.length; i++) { 169 Method m = methods[i]; 170 if (m.getName().matches(METHOD_PATTERN)) { 171 Class [] args = m.getParameterTypes(); 172 if ((args.length == 2) && args[0].equals(type) && args[1].equals(Boolean.TYPE)) { 173 rv.add(m.getName().replaceFirst(METHOD_PREFIX, "")); 174 } else { 175 throw new RuntimeException ("bad method: " + m); 176 } 177 } 178 } 179 180 if (rv.size() <= 0) { throw new RuntimeException ("Didn't find any operations"); } 181 182 Collections.sort(rv); 184 185 return rv; 186 } 187 188 public static void visitL1DSOConfig(ConfigVisitor visitor, DSOClientConfigHelper config) { 189 String testClass = GenericTestApp.class.getName(); 190 TransparencyClassSpec spec = config.getOrCreateSpec(testClass); 191 config.getOrCreateSpec(Exit.class.getName()); 192 193 spec.addRoot("sharedMap", "sharedMap"); 194 spec.addRoot("barrier", "barrier"); 195 spec.addRoot("barrier2", "barrier2"); 196 spec.addRoot("exit", "exit"); 197 198 String methodExpression = "* " + testClass + "*.*(..)"; 199 config.addWriteAutolock(methodExpression); 200 201 new CyclicBarrierSpec().visit(visitor, config); 202 } 203 204 private static class Exit { 205 private boolean exit = false; 206 207 synchronized boolean shouldExit() { 208 return exit; 209 } 210 211 synchronized void toggle() { 212 exit = true; 213 } 214 } 215 216 } 217 | Popular Tags |