/**************************************************************** * Copyright (C) 2006 LAMS Foundation (http://lamsfoundation.org) * ============================================================= * License Information: http://lamsfoundation.org/licensing/lams/2.0/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2.0 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * http://www.gnu.org/licenses/gpl.txt * **************************************************************** */ package org.lamsfoundation.testharness; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.BufferedReader; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.lamsfoundation.testharness.Call.CallRecord; import org.lamsfoundation.testharness.learner.LearnerTest; import edu.stanford.ejalbert.BrowserLauncher; import edu.stanford.ejalbert.exception.BrowserLaunchingExecutionException; import edu.stanford.ejalbert.exception.BrowserLaunchingInitializingException; import edu.stanford.ejalbert.exception.UnsupportedOperatingSystemException; /** * @version * *

* View Source *

* * @author Fei Yang */ public class TestReporter { private static final Logger log = Logger.getLogger(TestReporter.class); private static List callRecords = new LinkedList(); private static String fileName; private static String fileTemplate; public static boolean initialized(){ return ((fileName!=null)&&(fileTemplate!=null)); } public static List getCallRecords() { return callRecords; } public static void setCallRecords(List callRecords) { TestReporter.callRecords = callRecords; } public static String getFileName() { return fileName; } public static void setFileName(String fileName) { TestReporter.fileName = fileName; } public static String getFileTemplate() { return fileTemplate; } public static void setFileTemplate(String fileTemplate) { TestReporter.fileTemplate = fileTemplate; } public static synchronized void addCallRecord(CallRecord callRecord){ callRecords.add(callRecord); } public static void report(AbstractTestManager manager) { final String NEW_LINE = "\n* "; final String NEW_LINE_INDENT = "\n* "; StringBuilder report = new StringBuilder(); report.append("See below\n\n**********************************Brief Report*******************************************"); //disclaimer report.append(NEW_LINE); report.append(NEW_LINE).append("Disclaimer:"); report.append(NEW_LINE_INDENT).append("This program is created in the hope that it will help estimate how many concurrent"); report.append(NEW_LINE_INDENT).append("users a LAMS 2.x server can handle, but WITHOUT ANY GARANTEE the server can support"); report.append(NEW_LINE_INDENT).append("that number of users in service use."); report.append(NEW_LINE); report.append(NEW_LINE_INDENT).append("This program is more a load test tool than a functional test tool, "); report.append(NEW_LINE_INDENT).append("so it does NOT GARANTEE there is no functional bug in the target server."); report.append(NEW_LINE); report.append(NEW_LINE).append("Test Result Summary:"); report.append(NEW_LINE_INDENT).append(manager.testSuites.size()).append(" test suite(s) launched. "); report.append(manager.testSuites.size()-manager.countAborted()).append(" test suite(s) finished, and ").append(manager.countAborted()).append(" test suite(s) aborted."); for (TestSuite testSuite : manager.testSuites){ report.append(NEW_LINE_INDENT).append("Test Suite ").append(testSuite.getSuiteIndex()).append(testSuite.isFinished()? " finished" : " aborted").append(", in which"); report.append(NEW_LINE_INDENT); AbstractTest[] tests = new AbstractTest[]{testSuite.getAdminTest(),testSuite.getAuthorTest(),testSuite.getMonitorTest(),testSuite.getLearnerTest()}; boolean first = true; for(AbstractTest test : tests){ if(test!=null){ if(!first) report.append(", "); report.append(test.getTestName()).append(test.isFinished()? " finished" : " aborted"); first = false; } } report.append(NEW_LINE_INDENT); LearnerTest learnerTest = testSuite.getLearnerTest(); report.append("In ").append(learnerTest.getTestName()).append(", "); report.append(learnerTest.countLearners()).append(" learner(s) attended, "); report.append(learnerTest.countLearners()-learnerTest.countAborted()).append(" finished and "); report.append(learnerTest.countAborted()).append(" aborted."); report.append(NEW_LINE); } report.append(NEW_LINE).append("Refer to the formal test report document for the details."); report.append(NEW_LINE).append("\n*****************************************************************************************\n"); log.info(report.toString()); } public static void generateReport(AbstractTestManager manager) { report(manager); log.info("Generating the formal test report document..."); TemplateCompiler.init(manager.testSuites, callRecords); String filename = generateFileName(); try { String report = TemplateCompiler.compile(TemplateCompiler.load()); BufferedWriter out = new BufferedWriter(new FileWriter(filename)); out.write(report); out.close(); BrowserLauncher launcher = new BrowserLauncher(null); launcher.openURLinBrowser(new File(filename).toURL().toString()); } catch (MalformedURLException e) { log.debug(e.getMessage(),e); } catch (IOException e) { log.debug(e.getMessage(), e); }catch (BrowserLaunchingInitializingException e) { log.debug(e.getMessage(),e); } catch (UnsupportedOperatingSystemException e) { log.debug(e.getMessage(),e); } catch (BrowserLaunchingExecutionException e) { log.debug(e.getMessage(),e); } } private static String generateFileName(){ return fileName + "_" + new SimpleDateFormat("MMM-d-HH'h-'mm'm'").format(new Date())+".html"; } public static void main(String[] args){ String[] results = "testSuite.suiteIndex".split("\\."); System.out.println(results.length); } private static class TemplateCompiler{ static Map context; static final int LIST_FIRST = 0; static final int IF_FIRST = 1; static final int EL_FIRST = 2; static final int TEXT_FIRST = 3; static final String EL_START = "${"; static final char EL_END = '}'; static final String LIST_START = "<#list"; static final String LIST_AS = "as"; //static final String LIST_GROUP_BY = "group by"; static final String LIST_END = ""; static final String IF_START = "<#if"; static final String IF_ELSE = "<#else>"; static final String IF_END = ""; static final char TAG_END = '>'; //static final String AVG = "avg"; //static final String SUM = "sum"; //static final String COUNT = "count"; //static final char PARAM_START = '('; //static final char PARAM_END = ')'; static void init(List testSuites, List callRecords){ context = new HashMap(); context.put("callRecords", callRecords); context.put("testSuites", testSuites); context.put("time", new SimpleDateFormat("HH:mm:ss dd MMM yyyy").format(new Date())); } static String load() throws IOException{ StringBuilder source = new StringBuilder(); BufferedReader lnReader = new BufferedReader(new FileReader(fileTemplate)); String line = lnReader.readLine(); while (line != null){ source.append(line).append('\n'); line = lnReader.readLine(); } return source.toString(); } private static String compile(String source) { int listStartIndex = source.indexOf(LIST_START); int ifStartIndex = source.indexOf(IF_START); int elStartIndex = source.indexOf(EL_START); switch(whichFirst(convert(listStartIndex,source), convert(ifStartIndex, source), convert(elStartIndex, source), source.length())){ case LIST_FIRST: int listEndIndex = source.indexOf(LIST_END, listStartIndex); int listStartTagIndex = source.indexOf(TAG_END, listStartIndex); int listAsIndex = source.indexOf(LIST_AS, listStartIndex); if(listStartTagIndex == -1) throw new TestHarnessException("'list' tag missing '>'"); if(listAsIndex == -1) throw new TestHarnessException("'as' is required for 'list'"); if(listEndIndex == -1) throw new TestHarnessException("'list' tag unclosed"); StringBuilder middle = new StringBuilder(); String middlePart = source.substring(listStartTagIndex+1,listEndIndex); String collection = extract(source.substring(listStartIndex + LIST_START.length(), listAsIndex)); String element = extract(source.substring(listAsIndex + LIST_AS.length(), listStartTagIndex)).trim(); for(Object o : (List)compileEL(collection)){ //log.debug("Put " + o + " into context as "+element); context.put(element, o); middle.append(compile(middlePart)); } String frontEnd = source.substring(0, listStartIndex); String backEnd = source.substring(listEndIndex + LIST_END.length()); return compile(frontEnd) + middle.toString() + compile(backEnd); case IF_FIRST: int ifEndIndex = source.indexOf(IF_END, ifStartIndex); int ifStartTagIndex = source.indexOf(TAG_END, ifStartIndex); int elseIndex = source.indexOf(IF_ELSE, ifStartIndex); if(ifStartTagIndex == -1) throw new TestHarnessException("'if' tag missing '>'"); if(ifEndIndex == -1) throw new TestHarnessException("'if' tag unclosed"); String condition = extract(source.substring(ifStartIndex + IF_START.length(), ifStartTagIndex)); Boolean b = (Boolean)compileEL(condition); String ifBlock; if(elseIndex != -1){ String middlePart1 = source.substring(ifStartTagIndex+1, elseIndex); String middlePart2 = source.substring(elseIndex + IF_ELSE.length(), ifEndIndex); ifBlock = b? middlePart1 : middlePart2; }else{ String middlePart1 = source.substring(ifStartTagIndex+1, ifEndIndex); ifBlock = b? middlePart1:""; } String ifFrontEnd = source.substring(0, ifStartIndex); String ifBackEnd = source.substring(ifEndIndex + IF_END.length()); return compile(ifFrontEnd) + compile(ifBlock) + compile(ifBackEnd); case EL_FIRST: int elEndIndex = source.indexOf(EL_END, elStartIndex); if(elEndIndex == -1) throw new TestHarnessException("'}' expected"); String elBlock = compileEL(source.substring(elStartIndex + EL_START.length(), elEndIndex)).toString(); String elFrontEnd = source.substring(0, elStartIndex); String elBackEnd = source.substring(elEndIndex+1); return compile(elFrontEnd) + elBlock + compile(elBackEnd); case TEXT_FIRST: return source; default: throw new TestHarnessException("unexpected error happened!"); } } private static int whichFirst(int listStartIndex, int ifStartIndex, int elStartIndex, int textIndex){ int[] indexes = {listStartIndex, ifStartIndex, elStartIndex, textIndex}; return whichMinimum(indexes); } private static int whichMinimum(int[] nums) { if(nums.length == 0){ return -1; } int min = nums[0]; int minIndex = 0; for(int i=1; i