public class InstrumenterServiceTest {
  private InstrumenterService service = new InstrumenterService();
  private CompilerEnvirons compilerEnvirons = new CompilerEnvirons();
  private IoUtils ioUtils = IoUtils.getInstance();
  private File src = new File("target/src.js");

  @Before
  public void setUp() {
    src.delete();
    ioUtils.copy("x++;", src);
  }

  @Test
  public void shouldInstrumentForFileSystem() {
    File dest = new File("target/dest.js");
    dest.deleteOnExit();
    service.instrumentJSForFileSystem(compilerEnvirons, src, dest, "/src.js", false, false);
    String jsInstrumented = ioUtils.loadFromFileSystem(dest);

    assertThat(jsInstrumented, containsString("x++;"));
    assertThat(jsInstrumented, containsString("_$jscoverage['/src.js'].lineData[1]++;"));
  }

  @Test
  public void shouldInstrumentForWebServer() {
    File dest = new File("target/dest.js");
    dest.deleteOnExit();
    String jsInstrumented =
        service.instrumentJSForWebServer(compilerEnvirons, src, "/src.js", false, false);

    assertThat(jsInstrumented, containsString("x++;"));
    assertThat(jsInstrumented, containsString("_$jscoverage['/src.js'].lineData[1]++;"));
  }
}
 @AfterClass
 public static void tearDown() throws Exception {
   main.stop();
   IoUtils.getInstance().closeQuietly(serverSocket);
 }
public class PersistentProxyTest {
  private static Thread webServer;
  private static Thread proxyServer;
  private static Main main = new Main();
  private static ServerSocket serverSocket;
  private static int proxyPort = 3129;

  protected WebClient webClient = new WebClient();
  protected IoUtils ioUtils = IoUtils.getInstance();

  private static String CONTENT = "Some content";

  private static String[] args =
      new String[] {
        "-ws",
        "--port=" + proxyPort,
        "--proxy",
        "--no-branch",
        "--no-function",
        "--no-instrument-reg=.*",
      };

  @BeforeClass
  public static void setUpOnce() throws IOException {
    proxyServer =
        new Thread(
            new Runnable() {
              public void run() {
                main.runMain(args);
              }
            });
    proxyServer.start();
    webServer =
        new Thread(
            new Runnable() {
              public void run() {
                try {
                  serverSocket = new ServerSocket(9001);
                  while (true) {
                    final Socket socket = serverSocket.accept();
                    new Thread(new PersistentStaticHttpServer(socket, CONTENT)).start();
                  }
                } catch (IOException e) {
                  // throw new RuntimeException(e);
                }
              }
            });
    webServer.start();
  }

  @AfterClass
  public static void tearDown() throws Exception {
    main.stop();
    IoUtils.getInstance().closeQuietly(serverSocket);
  }

  @Before
  public void setUp() {
    ProxyConfig proxyConfig = new ProxyConfig("localhost", proxyPort);
    proxyConfig.addHostsToProxyBypass("127.0.0.1");
    webClient.getOptions().setProxyConfig(proxyConfig);
    webClient.getOptions().setTimeout(2000);
  }

  protected String getTestUrl() {
    return "http://localhost:9001/anything";
  }

  protected void doTestRequests(HttpMethod... methods) throws Exception {
    URL testURL = new URL(getTestUrl());
    for (HttpMethod method : methods) {
      WebRequest request = new WebRequest(testURL, method);
      Page page = webClient.getPage(request);
      assertEquals("Unexpected response", CONTENT, page.getWebResponse().getContentAsString());
    }
  }

  @Test
  public void testSingleGet() throws Exception {
    doTestRequests(HttpMethod.GET);
  }

  @Test
  public void testSinglePost() throws Exception {
    doTestRequests(HttpMethod.POST);
  }

  @Test
  public void testConsecutiveGets() throws Exception {
    doTestRequests(HttpMethod.GET, HttpMethod.GET);
  }

  @Test
  public void testConsecutivePosts() throws Exception {
    doTestRequests(HttpMethod.POST, HttpMethod.POST);
  }
}
public class HtmlServerUnloadedJSTest {
  private static Thread server;

  protected WebClient webClient = new WebClient();
  private IoUtils ioUtils = IoUtils.getInstance();
  private String reportDir = "target/ws-report";
  private String[] args =
      new String[] {
        "-ws",
        "--document-root=src/test-integration/resources/jsSearch",
        "--port=9001",
        "--no-instrument=noInstrument",
        "--include-unloaded-js",
        "--report-dir=" + reportDir
      };

  @Before
  public void setUp() throws IOException {
    if (server == null) {
      server =
          new Thread(
              new Runnable() {
                public void run() {
                  try {
                    Main.main(args);
                  } catch (IOException e) {
                    throw new RuntimeException(e);
                  }
                }
              });
      server.start();
    }
    webClient.getOptions().setTimeout(30000);
  }

  @Test
  public void shouldIncludeUnloadJSInSavedReport() throws Exception {
    File jsonFile = new File(reportDir + "/jscoverage.json");
    if (jsonFile.exists()) jsonFile.delete();

    HtmlPage page = webClient.getPage("http://*****:*****@id='row-" + uri + "']/td[8]/span").getTextContent(),
        equalTo(linePercentage));
    assertThat(
        getHtmlElement(page, "//tr[@id='row-" + uri + "']/td[9]/span").getTextContent(),
        equalTo(branchPercentage));
    assertThat(
        getHtmlElement(page, "//tr[@id='row-" + uri + "']/td[10]/span").getTextContent(),
        equalTo(functionPercentage));
  }

  private HtmlElement getHtmlElement(HtmlPage page, String xpathExpr) {
    return (HtmlElement) ((ArrayList) page.getByXPath(xpathExpr)).get(0);
  }
}
public class JSONDataSaver {
  private static final Logger logger = Logger.getLogger(JSONDataSaver.class.getName());
  protected static Set<File> files = new HashSet<File>();
  private JSONDataMerger jsonDataMerger = new JSONDataMerger();
  private IoUtils ioUtils = IoUtils.getInstance();

  public void saveJSONData(
      File reportDir,
      String data,
      List<ScriptCoverageCount> unloadJSData,
      UriFileTranslator uriFileTranslator) {
    try {
      lockOnReportDir(reportDir);
      reportDir.mkdirs();
      File jsonFile = new File(reportDir, "jscoverage.json");
      SortedMap<String, FileData> dataMap = new TreeMap<String, FileData>();
      if (jsonFile.exists()) {
        logger.info("Saving/merging JSON with existing JSON");
        String existingJSON = ioUtils.toString(jsonFile);
        if (uriFileTranslator.mutates()) {
          translateUris(data, uriFileTranslator, dataMap);
          dataMap =
              jsonDataMerger.mergeJSONCoverageMaps(dataMap, jsonDataMerger.jsonToMap(existingJSON));
        } else dataMap.putAll(jsonDataMerger.mergeJSONCoverageStrings(existingJSON, data));
        ioUtils.copy(jsonDataMerger.toJSON(dataMap), jsonFile);
      } else if (unloadJSData != null) {
        logger.info("Saving/merging JSON with unloaded JavaScript JSON");
        // Only scan for unloaded JS if JSON not saved before
        dataMap.putAll(jsonDataMerger.createEmptyJSON(unloadJSData));
        if (uriFileTranslator.mutates()) translateUris(data, uriFileTranslator, dataMap);
        else dataMap.putAll(jsonDataMerger.jsonToMap(data));
        ioUtils.copy(jsonDataMerger.toJSON(dataMap), jsonFile);
      } else {
        logger.info("Saving JSON");
        if (uriFileTranslator.mutates()) {
          translateUris(data, uriFileTranslator, dataMap);
          ioUtils.copy(jsonDataMerger.toJSON(dataMap), jsonFile);
        } else ioUtils.copy(data, jsonFile);
      }
    } finally {
      unlockOnReportDir(reportDir);
    }
  }

  private void translateUris(
      String data, UriFileTranslator uriFileTranslator, SortedMap<String, FileData> map) {
    SortedMap<String, FileData> coverageData = jsonDataMerger.jsonToMap(data);
    for (String uri : coverageData.keySet())
      map.put(uriFileTranslator.convertUriToFile(uri), coverageData.get(uri));
  }

  private void lockOnReportDir(File reportDir) {
    synchronized (files) {
      while (files.contains(reportDir))
        try {
          files.wait();
        } catch (InterruptedException ex) {
          logger.log(SEVERE, Thread.currentThread().getName() + " INTERRUPTED", ex);
        }
      files.add(reportDir);
      files.notifyAll(); // must own the lock
    }
  }

  private void unlockOnReportDir(File reportDir) {
    synchronized (files) {
      files.remove(reportDir);
      files.notifyAll();
    }
  }
}