1 /* 2 * Copyright (C) 2014 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.caliper.runner; 16 17 import com.google.caliper.bridge.LogMessage; 18 import com.google.caliper.bridge.LogMessageVisitor; 19 import com.google.caliper.bridge.OpenedSocket; 20 import com.google.caliper.config.CaliperConfig; 21 import com.google.caliper.config.InvalidConfigurationException; 22 import com.google.caliper.platform.Platform; 23 import com.google.caliper.platform.jvm.JvmPlatform; 24 import com.google.caliper.util.Util; 25 import com.google.common.annotations.VisibleForTesting; 26 import com.google.common.collect.ImmutableMap; 27 28 import java.io.IOException; 29 import java.io.Serializable; 30 import java.net.InetAddress; 31 import java.net.Socket; 32 import java.util.Collections; 33 import java.util.List; 34 import java.util.concurrent.CountDownLatch; 35 36 import javax.annotation.concurrent.GuardedBy; 37 38 /** 39 * A collection of Simple java executables and a helper method for creating process builders for 40 * them. 41 */ 42 final class FakeWorkers { 43 44 @GuardedBy("FakeWorkers.class") 45 private static VirtualMachine jvm; 46 47 /** 48 * Try to find the currently executing jvm binary, N.B. This isn't guaranteed to be cross 49 * platform. 50 */ init()51 private static synchronized VirtualMachine init() { 52 if (jvm == null) { 53 try { 54 Platform platform = new JvmPlatform(); 55 jvm = new VirtualMachine("default", 56 new CaliperConfig(ImmutableMap.<String, String>of()).getDefaultVmConfig(platform)); 57 } catch (InvalidConfigurationException e) { 58 throw new RuntimeException(); 59 } 60 } 61 return jvm; 62 } 63 64 /** 65 * Returns a ProcessBuilder that attempts to invoke the given class as main in a JVM configured 66 * with a classpath equivalent to the currently executing JVM. 67 */ createProcessBuilder(Class<?> mainClass, String ...mainArgs)68 static ProcessBuilder createProcessBuilder(Class<?> mainClass, String ...mainArgs) { 69 VirtualMachine jvm = init(); 70 List<String> args; 71 try { 72 args = WorkerProcess.getJvmArgs(jvm, BenchmarkClass.forClass(mainClass)); 73 } catch (InvalidBenchmarkException e) { 74 throw new RuntimeException(e); 75 } 76 args.add(mainClass.getName()); 77 Collections.addAll(args, mainArgs); 78 return new ProcessBuilder().command(args); 79 } 80 getVirtualMachine()81 public static VirtualMachine getVirtualMachine() { 82 return init(); 83 } 84 85 /** 86 * A simple main method that will sleep for the number of milliseconds specified in the first 87 * argument. 88 */ 89 static final class Sleeper { main(String[] args)90 public static void main(String[] args) throws NumberFormatException, InterruptedException { 91 Thread.sleep(Long.parseLong(args[0])); 92 } 93 } 94 95 /** 96 * A simple main method that exits immediately with the code provided by the first argument 97 */ 98 static final class Exit { main(String[] args)99 public static void main(String[] args) { 100 System.exit(Integer.parseInt(args[0])); 101 } 102 } 103 104 /** 105 * A simple main method that exits immediately with the code provided by the first argument 106 */ 107 static final class CloseAndSleep { main(String[] args)108 public static void main(String[] args) throws IOException, InterruptedException { 109 System.err.close(); 110 System.in.close(); 111 System.out.close(); 112 new CountDownLatch(1).await(); // wait forever 113 } 114 } 115 116 /** 117 * Prints alternating arguments to standard out and standard error. 118 */ 119 static final class PrintClient { main(String[] args)120 public static void main(String[] args) { 121 for (int i = 0; i < args.length; i++) { 122 if (i % 2 == 0) { 123 System.out.println(args[i]); 124 System.out.flush(); 125 } else { 126 System.err.println(args[i]); 127 System.err.flush(); 128 } 129 } 130 } 131 } 132 133 /** 134 * Prints alternating arguments to standard out and standard error. 135 */ 136 @VisibleForTesting 137 static final class LoadBenchmarkClass { 138 main(String[] args)139 public static void main(String[] args) throws ClassNotFoundException { 140 String benchmarkClassName = args[0]; 141 Util.loadClass(benchmarkClassName); 142 } 143 } 144 145 static final class DummyLogMessage extends LogMessage implements Serializable { 146 private final String content; 147 DummyLogMessage(String content)148 DummyLogMessage(String content) { 149 this.content = content; 150 } 151 accept(LogMessageVisitor visitor)152 @Override public void accept(LogMessageVisitor visitor) {} 153 toString()154 @Override public String toString() { 155 return content; 156 } 157 equals(Object obj)158 @Override public boolean equals(Object obj) { 159 return obj instanceof DummyLogMessage && ((DummyLogMessage) obj).content.equals(content); 160 } 161 hashCode()162 @Override public int hashCode() { 163 return content.hashCode(); 164 } 165 } 166 167 /** 168 * Connects to a socket on localhost on the port provided as the first argument and echos all 169 * data. 170 * 171 * <p>Once the connection has been closed it prints the remaining args to stdout 172 */ 173 static final class SocketEchoClient { main(String[] args)174 public static void main(String[] args) throws Exception { 175 int port = Integer.parseInt(args[0]); 176 OpenedSocket openedSocket = OpenedSocket.fromSocket( 177 new Socket(InetAddress.getLocalHost(), port)); 178 OpenedSocket.Reader reader = openedSocket.reader(); 179 OpenedSocket.Writer writer = openedSocket.writer(); 180 writer.write(new DummyLogMessage("start")); 181 writer.flush(); 182 Serializable obj; 183 while ((obj = reader.read()) != null) { 184 writer.write(obj); 185 writer.flush(); 186 } 187 writer.close(); 188 reader.close(); 189 for (int i = 1; i < args.length; i++) { 190 System.out.println(args[i]); 191 System.out.flush(); 192 } 193 } 194 } 195 } 196