package fr.inria.diversify.sosie.logger; import java.io.*; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; /** * Verbose log for humans to understand * <p/> * Created by marodrig on 25/06/2014. */ public class InstruVerboseLog extends InstruLogWriter { ///File writer for each thread. Each one saved in a different file private Map<Thread, PrintWriter> fileWriters; private String separator = ":;:"; private String simpleSeparator = ";"; //TPs called in this test protected HashSet<Integer> transplantPointCalledInThisTest; /** * Constructor of the verbose log * * @param logDir Directory of the logger * @param parentLog Parent log (the logger of the thread launching the test) */ public InstruVerboseLog(String logDir, InstruLogWriter parentLog) { super(logDir, parentLog); previousVarLog = new HashMap(); fileWriters = new HashMap<Thread, PrintWriter>(); } public InstruVerboseLog(String logDir) { super(logDir); previousVarLog = new HashMap(); fileWriters = new HashMap<Thread, PrintWriter>(); } public void methodCall(Thread thread, String methodSignatureId) { String semaphore = ""; if (getLogMethod(thread) && log(thread)) { try { incCallDepth(thread); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("$$$\n"); stringBuilder.append("M"); //new method call stringBuilder.append(callDeep.get(thread)); stringBuilder.append(simpleSeparator); stringBuilder.append(methodSignatureId); String string = stringBuilder.toString(); PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string); } catch (Exception e) { e.printStackTrace(); } finally { releaseFileWriter(semaphore); } } } public void methodOut(Thread thread) { decCallDepth(thread); } public void writeTestStart(Thread thread, String testSignature) { super.writeTestStart(thread, testSignature); String semaphore = ""; try { partialLoggingThread = null; if(previousVarLog.get(thread) != null) { previousVarLog.get(thread).clear(); } resetCallDepth(thread); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("$$$\n"); stringBuilder.append("NewTest"); stringBuilder.append(simpleSeparator); stringBuilder.append(testSignature); String string = stringBuilder.toString(); PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string); } catch (Exception e) { e.printStackTrace(); } finally { releaseFileWriter(semaphore); } } public void writeAssert(int id, Thread thread, String className, String methodSignature, String assertName, Object... var) { String semaphore = ""; try { StringBuilder string = new StringBuilder(); string.append("$$$\n"); string.append("A"); string.append(simpleSeparator); string.append(id + ""); string.append(simpleSeparator); string.append(className); string.append(simpleSeparator); string.append(methodSignature); string.append(simpleSeparator); string.append(assertName); StringBuilder vars = new StringBuilder(); for (int i = 0; i < var.length; i++) { try { vars.append(separator); vars.append(printString(var[i])); } catch (Exception e) { } string.append(vars.toString()); } PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string.toString()); } catch (Exception e) { e.printStackTrace(); } finally { releaseFileWriter(semaphore); } } protected void writeStartLogging(Thread thread, String id) { String semaphore = ""; if (getLogMethod(thread)) { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("$$$\n"); stringBuilder.append("S"); //start logging stringBuilder.append(simpleSeparator); stringBuilder.append(id); String string = stringBuilder.toString(); PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string); } catch (Exception e) { e.printStackTrace(); } finally { startLogMethod(thread); releaseFileWriter(semaphore); } } } public void writeVar(int id, Thread thread, String methodSignatureId, Object... var) { String semaphore = ""; if (getLogMethod(thread) && log(thread)) { try { StringBuilder string = new StringBuilder(); string.append("$$$\n"); string.append("V"); string.append(getCallDeep(thread)); string.append(simpleSeparator); string.append(id + ""); string.append(simpleSeparator); string.append(methodSignatureId); String varsString = buildVars(thread, id+methodSignatureId, var); if(varsString.isEmpty()) return; string.append(varsString); startLogMethod(thread); PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string.toString()); } catch (Exception e) { e.printStackTrace(); } finally { startLogMethod(thread); releaseFileWriter(semaphore); } } } public void writeSourcePositionCall(String id) { if (getTransplantPointCallCount().containsKey(id)) { int k = getTransplantPointCallCount().get(id); getTransplantPointCallCount().put(id, k + 1); } else { getTransplantPointCallCount().put(id, 1); writeStartLogging(Thread.currentThread(), id); } } @Override public void countAssert(String id) { Thread thread = getParent() == null ? Thread.currentThread() : getParent().getThread(); if (getAssertCallCount().containsKey(id)) { int k = getAssertCallCount().get(id); getAssertCallCount().put(id, k + 1); } else { String semaphore = ""; if (getLogMethod(thread)) { try { getAssertCallCount().put(id, 1); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("$$$\n"); stringBuilder.append("SA"); //start logging stringBuilder.append(simpleSeparator); stringBuilder.append(id); stringBuilder.append(simpleSeparator); stringBuilder.append(System.currentTimeMillis()); String string = stringBuilder.toString(); PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string); } catch (Exception e) { e.printStackTrace(); } finally { startLogMethod(thread); releaseFileWriter(semaphore); } } } } static long nbVar = 0; static long tooBigVar = 0; protected String buildVars(Thread thread, String methodSignatureId, Object[] vars) { StringBuilder varsString = new StringBuilder(); stopLogMethod(thread); Map<String, String> previousVars = previousVarLog.get(thread); for (int i = 0; i < vars.length / 2; i = i + 2) { try { String varName = vars[i].toString(); String value; if (vars[i + 1] == null) { value = "null"; } else { value = vars[i + 1].toString(); } if(value.length() > 1000) { value = vars[i + 1].getClass().getCanonicalName() + value.length(); tooBigVar++; } String varId = methodSignatureId + ":" + varName; String previousValue = previousVars.get(varId); if (!value.equals(previousValue)) { nbVar++; previousVars.put(varId, value); varsString.append(separator); varsString.append(varName); varsString.append(simpleSeparator); varsString.append(value); } } catch (Exception e) { } } startLogMethod(thread); return varsString.toString(); } public void writeException(int id, Thread thread, Object exception) { String semaphore = ""; if (getLogMethod(thread) && log(thread)) { try { StringBuilder string = new StringBuilder(); string.append("$$$\n"); string.append("E"); string.append(callDeep.get(thread)); string.append(simpleSeparator); string.append(id + ""); string.append(simpleSeparator); if (exception != null) string.append(exception.toString()); else string.append("NullException"); PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string.toString()); } catch (Exception e) { e.printStackTrace(); } finally { releaseFileWriter(semaphore); } } } static long testCount = 0; static long assertCount = 0; public void testCount(String signature) { System.out.println("test: "+ ++testCount); } public void assertCount(String signature) { System.out.println("assert: "+ ++assertCount); } public void writeCatch(int id, Thread thread, Object exception) { String semaphore = ""; if (getLogMethod(thread) && log(thread)) { try { StringBuilder string = new StringBuilder(); string.append("$$$\n"); string.append("C"); string.append(callDeep.get(thread)); string.append(simpleSeparator); string.append(id + ""); string.append(simpleSeparator); if (exception != null) string.append(exception.toString()); else string.append("NullException"); PrintWriter fileWriter = getFileWriter(thread); semaphore = fileWriter.toString() + fileWriter.hashCode(); fileWriter.append(string.toString()); } catch (Exception e) { e.printStackTrace(); } finally { releaseFileWriter(semaphore); } } } @Override public void writeTestFinish() { // System.err.println("var: "+nbVar); // System.err.println("too big var: "+tooBigVar); for (Thread thread : fileWriters.keySet()) { String semaphore = ""; try { PrintWriter flw = getFileWriter(thread); //Writes the subtotal of transplantation points called writeSubTotal("TPC", flw, getTransplantPointCallCount()); //Writes the subtotal of assertions called writeSubTotal("ASC", flw, getAssertCallCount()); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("$$$\n"); stringBuilder.append("TE"); stringBuilder.append(simpleSeparator); stringBuilder.append(System.currentTimeMillis()); semaphore = flw.toString() + flw.hashCode(); flw.append(stringBuilder.toString()); flw.flush(); } catch (Exception e) { e.printStackTrace(); } releaseFileWriter(semaphore); } } public void close() { for (Thread thread : fileWriters.keySet()) { String semaphore = ""; try { PrintWriter flw = getFileWriter(thread); semaphore = flw.toString() + flw.hashCode(); flw.close(); } catch (Exception e) { e.printStackTrace(); } releaseFileWriter(semaphore); } } /** * Writes a sub-total count to the PrintWriter * * @param flw PrintWriter where the data is going to be printed * @param map Map containing the subtotals */ private void writeSubTotal(String subTotalId, PrintWriter flw, HashMap<String, Integer> map) { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, Integer> e : map.entrySet()) { if (e.getValue() > 1) { //Don't spend more space in login an occurrence of something we already log sb.append("\n"). append(subTotalId). append(simpleSeparator). append(e.getKey()). append(simpleSeparator). append(e.getValue()). append(simpleSeparator). append(System.currentTimeMillis()); } } flw.write(sb.toString()); } protected Map<String, String> loadIdMap(String file) throws IOException { Map<String, String> map = new HashMap<String, String>(); BufferedReader reader = new BufferedReader(new FileReader(file)); reader.readLine(); String line = reader.readLine(); while (line != null) { String[] tmp = line.split(" "); map.put(tmp[1], tmp[0]); line = reader.readLine(); } return map; } protected synchronized PrintWriter getFileWriter(Thread thread) throws IOException, InterruptedException { if (!fileWriters.containsKey(thread)) { String fileName = getThreadLogFilePath(thread) + "_" + System.currentTimeMillis(); previousVarLog.put(thread,new HashMap<String, String>()); PrintWriter f = new PrintWriter(new BufferedWriter(new FileWriter(fileName))); fileWriters.put(thread, f); semaphores.put(f.toString() + f.hashCode(), new Semaphore(1)); } PrintWriter f = fileWriters.get(thread); semaphores.get(f.toString() + f.hashCode()).tryAcquire(50, TimeUnit.MILLISECONDS); return f; } protected void releaseFileWriter(String id) { if (semaphores.containsKey(id)) semaphores.get(id).release(); } }