// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.htmlmonitor; import static org.junit.Assert.*; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import de.ugoe.cs.util.console.TextConsole; /** *

* TODO comment *

* * @author Patrick Harms */ public class HtmlMonitorTest { /** * */ public static final TextConsole CONSOLE = new TextConsole(); /** * */ private final static String LOG_FILE_DIR = "target/tmp/logfiles/"; /** * */ private static final int PORT = 19098; /** * */ private HtmlMonitor htmlMonitor; /** * */ @Before public void setUp() throws Exception { htmlMonitor = new HtmlMonitor(new String[] { LOG_FILE_DIR, Integer.toString(PORT) }); htmlMonitor.init(); htmlMonitor.start(); } /** * */ @After public void tearDown() throws Exception { if (htmlMonitor != null) { try { htmlMonitor.stop(); } finally { htmlMonitor = null; } } deleteFiles(new File(LOG_FILE_DIR)); } /** * */ @Test public void testOneSimpleMessage() throws Exception { String clientId = "123"; String message = "{" + " \"message\": {" + " \"clientInfos\": {" + " \"clientId\":\"" + clientId + "\"," + " \"userAgent\":\"Agent\"," + " \"title\":\"Title\"," + " \"url\":\"http://host/path\"" + " }," + " \"events\":" + " [ {" + " \"time\":\"12345\"," + " \"path\":\"/html[0]/body(id=gsr)\"," + " \"eventType\":\"onunload\"" + " }" + " ]" + " }" + "}"; sendMessageAndAssertResponse(message); File logFile = new File(LOG_FILE_DIR + File.separator + clientId + File.separator + "htmlmonitor_" + clientId + ".log"); assertTrue(logFile.exists()); String[] logEntries = readLogEntries(logFile); assertEquals(1, logEntries.length); assertLogMessage(logEntries[0], clientId, "12345", "Title", "http://host/path", "Agent", "onunload", "/html[0]/body(id=gsr)"); } /** * */ @Test public void testSeveralMessagesInOneSession() throws Exception { String clientId = "123"; String message = "{" + " \"message\": {" + " \"clientInfos\": {" + " \"clientId\":\"" + clientId + "\"," + " \"userAgent\":\"Agent\"," + " \"title\":\"Title\"," + " \"url\":\"http://host/path\"" + " }," + " \"events\":" + " [" + " {" + " \"time\":\"1\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input1)\"," + " \"eventType\":\"onclick\"," + " \"coordinates\": [\"194\", \"7\"]" + " }," + " {" + " \"time\":\"2\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input2)\"," + " \"eventType\":\"ondblclick\"," + " \"coordinates\": [\"194\", \"7\"]" + " }," + " {" + " \"time\":\"3\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input3)\"," + " \"eventType\":\"onfocus\"" + " }," + " {" + " \"time\":\"4\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input4)\"," + " \"eventType\":\"onclick\"," + " \"coordinates\": [\"125\", \"14\"]" + " }," + " {" + " \"time\":\"5\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input5)\"," + " \"eventType\":\"onfocus\"" + " }," + " {" + " \"time\":\"6\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input6)\"," + " \"eventType\":\"onfocus\"" + " }," + " {" + " \"time\":\"7\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input7)\"," + " \"eventType\":\"onfocus\"" + " }," + " {" + " \"time\":\"8\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input8)\"," + " \"eventType\":\"onclick\"," + " \"coordinates\": [\"255\", \"4\"]" + " }," + " {" + " \"time\":\"9\"," + " \"path\":\"/html[0]/body(id=gsr)\"," + " \"eventType\":\"onscroll\"," + " \"scrollPosition\": [\"23\", \"567\"]" + " }," + " {" + " \"time\":\"10\"," + " \"path\":\"/html[0]/body(id=gsr)/input(id=input10)\"," + " \"eventType\":\"onclick\"," + " \"coordinates\": [\"516\", \"154\"]" + " }" + " ]" + " }" + "}"; sendMessageAndAssertResponse(message); File logFile = new File(LOG_FILE_DIR + File.separator + clientId + File.separator + "htmlmonitor_" + clientId + ".log"); assertTrue(logFile.exists()); String[] logEntries = readLogEntries(logFile); assertEquals(10, logEntries.length); assertLogMessage(logEntries[0], clientId, "1", "Title", "http://host/path", "Agent", "onclick", "/html[0]/body(id=gsr)/input(id=input1)", "194,7"); assertLogMessage(logEntries[1], clientId, "2", "Title", "http://host/path", "Agent", "ondblclick", "/html[0]/body(id=gsr)/input(id=input2)", "194,7"); assertLogMessage(logEntries[2], clientId, "3", "Title", "http://host/path", "Agent", "onfocus", "/html[0]/body(id=gsr)/input(id=input3)"); assertLogMessage(logEntries[3], clientId, "4", "Title", "http://host/path", "Agent", "onclick", "/html[0]/body(id=gsr)/input(id=input4)", "125,14"); assertLogMessage(logEntries[4], clientId, "5", "Title", "http://host/path", "Agent", "onfocus", "/html[0]/body(id=gsr)/input(id=input5)"); assertLogMessage(logEntries[5], clientId, "6", "Title", "http://host/path", "Agent", "onfocus", "/html[0]/body(id=gsr)/input(id=input6)"); assertLogMessage(logEntries[6], clientId, "7", "Title", "http://host/path", "Agent", "onfocus", "/html[0]/body(id=gsr)/input(id=input7)"); assertLogMessage(logEntries[7], clientId, "8", "Title", "http://host/path", "Agent", "onclick", "/html[0]/body(id=gsr)/input(id=input8)", "255,4"); assertLogMessage(logEntries[8], clientId, "9", "Title", "http://host/path", "Agent", "onscroll", "/html[0]/body(id=gsr)", "23,567"); assertLogMessage(logEntries[9], clientId, "10", "Title", "http://host/path", "Agent", "onclick", "/html[0]/body(id=gsr)/input(id=input10)", "516,154"); } /** * */ @Test public void testSeveralSessions() throws Exception { String clientId = "123"; String message = "{" + " \"message\": {" + " \"clientInfos\": {" + " \"clientId\":\"" + clientId + "\"," + " \"userAgent\":\"Agent\"," + " \"title\":\"Title\"," + " \"url\":\"http://host/path\"" + " }," + " \"events\":" + " [ {" + " \"time\":\"12345\"," + " \"path\":\"/html[0]/body(id=gsr)\"," + " \"eventType\":\"onunload\"" + " }" + " ]" + " }" + "}"; sendMessageAndAssertResponse(message); int numberOfSessions = 10; for (int i = 0; i < numberOfSessions; i++) { htmlMonitor.stop(); htmlMonitor = new HtmlMonitor(new String[] { LOG_FILE_DIR, Integer.toString(PORT) }); htmlMonitor.init(); htmlMonitor.start(); sendMessageAndAssertResponse(message); } // assert 9 already rotated log files for (int i = 0; i < (numberOfSessions - 1); i++) { File logFile = new File(LOG_FILE_DIR + File.separator + clientId + File.separator + "htmlmonitor_" + clientId + "_00" + i + ".log"); assertTrue(logFile.exists()); String[] logEntries = readLogEntries(logFile); assertEquals(1, logEntries.length); assertLogMessage(logEntries[0], clientId, "12345", "Title", "http://host/path", "Agent", "onunload", "/html[0]/body(id=gsr)"); } // and now the last but current one File logFile = new File(LOG_FILE_DIR + File.separator + clientId + File.separator + "htmlmonitor_" + clientId + ".log"); assertTrue(logFile.exists()); String[] logEntries = readLogEntries(logFile); assertEquals(1, logEntries.length); assertLogMessage(logEntries[0], clientId, "12345", "Title", "http://host/path", "Agent", "onunload", "/html[0]/body(id=gsr)"); } /** *

* TODO: comment *

* * @param message */ private void sendMessageAndAssertResponse(String message) throws Exception { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("http://localhost:" + PORT + "/"); HttpEntity entity = new StringEntity(message, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); try { HttpResponse response = httpclient.execute(httpPost); // the monitor always returns 200 without any additional information. The client must // never get more or less information. This is especially important for preventing // hackers from finding out more assertEquals(200, response.getStatusLine().getStatusCode()); assertTrue ((response.getEntity() == null) || (response.getEntity().getContentLength() == 0)); } finally { httpPost.releaseConnection(); } } /** *

* TODO: comment *

* * @param logFile * @return */ private String[] readLogEntries(File logFile) throws Exception { List logEntries = new ArrayList(); BufferedReader reader = null; try { reader = new BufferedReader (new InputStreamReader(new FileInputStream(logFile))); String line = null; while ((line = reader.readLine()) != null) { logEntries.add(line); } } finally { if (reader != null) { reader.close(); } } return logEntries.toArray(new String[logEntries.size()]); } /** * */ private void assertLogMessage(String logMessage, String... assertedMessageContent) { StringBuffer assertedMessage = new StringBuffer(); for (int i = 0; i < assertedMessageContent.length; i++) { if (i > 0) { assertedMessage.append(' '); } assertedMessage.append('"'); assertedMessage.append(assertedMessageContent[i]); assertedMessage.append('"'); } assertEquals(assertedMessage.toString(), logMessage); } /** *

* TODO: comment *

* * @param file */ private void deleteFiles(File file) { if (file.exists()) { if (file.isDirectory()) { for (File child : file.listFiles()) { deleteFiles(child); } } try { file.delete(); } catch (Exception e) { // ignore and delete as much as possible } } } }