|
| 1 | +/*BEGIN_COPYRIGHT_BLOCK |
| 2 | + * |
| 3 | + * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/ |
| 4 | + * or http://sourceforge.net/projects/drjava/ |
| 5 | + * |
| 6 | + * DrJava Open Source License |
| 7 | + * |
| 8 | + * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved. |
| 9 | + * |
| 10 | + * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/ |
| 11 | + * |
| 12 | + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated |
| 13 | + * documentation files (the "Software"), to deal with the Software without restriction, including without limitation |
| 14 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and |
| 15 | + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 16 | + * |
| 17 | + * - Redistributions of source code must retain the above copyright notice, this list of conditions and the |
| 18 | + * following disclaimers. |
| 19 | + * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the |
| 20 | + * following disclaimers in the documentation and/or other materials provided with the distribution. |
| 21 | + * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to |
| 22 | + * endorse or promote products derived from this Software without specific prior written permission. |
| 23 | + * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their |
| 24 | + * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu. |
| 25 | + * |
| 26 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO |
| 27 | + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 28 | + * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| 29 | + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 30 | + * WITH THE SOFTWARE. |
| 31 | + * |
| 32 | + *END_COPYRIGHT_BLOCK*/ |
| 33 | + |
| 34 | +package edu.rice.cs.util; |
| 35 | + |
| 36 | +import junit.framework.TestCase; |
| 37 | +import java.io.FileReader; |
| 38 | +import java.io.BufferedReader; |
| 39 | +import java.io.IOException; |
| 40 | +import java.io.FileWriter; |
| 41 | +import java.io.File; |
| 42 | +import java.text.ParseException; |
| 43 | +import java.util.Date; |
| 44 | +import java.util.Random; |
| 45 | + |
| 46 | +import edu.rice.cs.drjava.model.MultiThreadedTestCase; |
| 47 | + |
| 48 | +/** Test cases for {@link Log}. |
| 49 | + * @version $Id: FileOpsTest.java 3896 2006-06-26 21:19:25Z rcartwright $ |
| 50 | + */ |
| 51 | +public class LogTest extends MultiThreadedTestCase { |
| 52 | + |
| 53 | + static final String FILENAME_PREFIX = "$#%#$"; |
| 54 | + static final File FILE1 = new File(FILENAME_PREFIX + "logtest1.txt"); |
| 55 | + static final File FILE2 = new File(FILENAME_PREFIX + "logtest2.txt"); |
| 56 | + static final File FILE3 = new File(FILENAME_PREFIX + "logtest3.txt"); |
| 57 | + |
| 58 | + static final int SHORT_TIME = 10000; // few seconds in milliseconds |
| 59 | + |
| 60 | + static final int DATE_END = 28; // the ending index of the date field in a log entry |
| 61 | + |
| 62 | + /** A thread class that adds a log message after sleeping a given number of milliseconds */ |
| 63 | + private class LogTestThread extends Thread { |
| 64 | + |
| 65 | + Log _log; |
| 66 | + int _millis; |
| 67 | + |
| 68 | + public LogTestThread(Log log, int millis) { |
| 69 | + _log = log; |
| 70 | + _millis = millis; |
| 71 | + } |
| 72 | + |
| 73 | + public void run() { |
| 74 | + try { sleep(_millis); } |
| 75 | + catch (InterruptedException e ) { |
| 76 | + e.printStackTrace(); |
| 77 | + fail("testConcurrent failed: sleep interrupted"); |
| 78 | + } |
| 79 | + _log.log( "Test message" ); |
| 80 | + } |
| 81 | + |
| 82 | + } |
| 83 | + |
| 84 | + public void setUp() throws Exception { |
| 85 | + super.setUp(); |
| 86 | + |
| 87 | + // Clear log files if they exist, so beginning of files are written by these tests |
| 88 | + new FileWriter(FILE1).close(); |
| 89 | + new FileWriter(FILE2).close(); |
| 90 | + new FileWriter(FILE3).close(); |
| 91 | + } |
| 92 | + |
| 93 | + public void tearDown() throws Exception { |
| 94 | + // Delete log files |
| 95 | + /* Note: this code does not currently delete the files. |
| 96 | + * TO DO: Find a way to delete these files so the build directory does not contain more clutter. |
| 97 | + */ |
| 98 | + FILE1.deleteOnExit(); |
| 99 | + FILE2.deleteOnExit(); |
| 100 | + FILE3.deleteOnExit(); |
| 101 | + |
| 102 | + super.tearDown(); |
| 103 | + } |
| 104 | + |
| 105 | + /** Parses a date printed by Date.toString(); returns null if there is a parse error. */ |
| 106 | + @SuppressWarnings("deprecation") |
| 107 | + private static Date parse(String s) { |
| 108 | + try { return new Date(Date.parse(s.substring(0, DATE_END))); } // the undeprecated version of parse DOES NOT WORK |
| 109 | + catch(RuntimeException e) { return null; } // either IllegalArgument or StringIndexOutOfBounds |
| 110 | + } |
| 111 | + |
| 112 | + /** Adds a couple of generic messages to a log, and then tests to make sure they are all correct, in the correct order, |
| 113 | + * and their timestamps are within the past few seconds. |
| 114 | + */ |
| 115 | + public void testLog() throws IOException { |
| 116 | + Log log1 = new Log(FILE1, true); |
| 117 | + log1.log("Message 1"); |
| 118 | + log1.log("Message 2"); |
| 119 | + log1.log("Message 3"); |
| 120 | + |
| 121 | + BufferedReader fin = new BufferedReader(new FileReader(FILE1)); |
| 122 | + Date earlier = new Date(new Date().getTime() - SHORT_TIME); |
| 123 | + Date now = new Date(); |
| 124 | + |
| 125 | + String s0 = fin.readLine(); |
| 126 | +// System.err.println("s0 = " + s0); |
| 127 | +// System.err.println("s0 converted to millis " + parse(s0)); |
| 128 | +// System.err.println("Current time in millis is: " + System.currentTimeMillis()); |
| 129 | + Date time0 = parse(s0); |
| 130 | + assertTrue("Log opened within last few seconds", time0.compareTo(earlier) >= 0 && time0.compareTo(now) <= 0); |
| 131 | + assertEquals("Log open message", "Log '" + FILE1.getName() + "' opened", s0.substring(30, 60)); |
| 132 | + |
| 133 | + String s1 = fin.readLine(); |
| 134 | + Date time1 = parse(s1); |
| 135 | + assertTrue("Date of message 1 within last few seconds", time1.compareTo(earlier) >= 0 && time1.compareTo(now) <= 0); |
| 136 | + assertEquals("Log message 1", "Message 1", s1.substring(30)); |
| 137 | + |
| 138 | + String s2 = fin.readLine(); |
| 139 | + Date time2 = parse(s2); |
| 140 | + assertTrue("Date of message 2 within last few seconds", time2.compareTo(earlier) >= 0 && time2.compareTo(now) <= 0); |
| 141 | + assertEquals("Log message 2", "Message 2", s2.substring(30)); |
| 142 | + |
| 143 | + String s3 = fin.readLine(); |
| 144 | + Date time3 = parse(s3); |
| 145 | + assertTrue("Date of message 3 within last few seconds", time3.compareTo(earlier) >= 0 && time3.compareTo(now) <= 0); |
| 146 | + assertEquals("Log message 3", "Message 3", s3.substring(30)); |
| 147 | + |
| 148 | + fin.close(); |
| 149 | + } |
| 150 | + |
| 151 | + /** Tests the Exception printing methods in the Log file by throwing two exceptions and using the two types of log |
| 152 | + * methods (one with the Throwable itself and the other with the the StackTraceElement[]) |
| 153 | + */ |
| 154 | + public void testExceptionPrinting() throws IOException { |
| 155 | + Log log2 = new Log(FILE2, true); |
| 156 | +// System.err.println("Starting testExceptionPrinting"); |
| 157 | + |
| 158 | + // Throw a couple of exceptions and log them |
| 159 | + try { throw new ArrayIndexOutOfBoundsException(); } |
| 160 | + catch (ArrayIndexOutOfBoundsException e) { |
| 161 | + //e.printStackTrace(); |
| 162 | + log2.log("Message 1", e); |
| 163 | + } |
| 164 | + |
| 165 | + try { throw new NullPointerException(); } |
| 166 | + catch (NullPointerException e) { |
| 167 | + //e.printStackTrace(); |
| 168 | + log2.log("Message 2", e.getStackTrace()); |
| 169 | + } |
| 170 | + |
| 171 | + BufferedReader fin = new BufferedReader(new FileReader(FILE2)); |
| 172 | + Date earlier = new Date(new Date().getTime() - SHORT_TIME); |
| 173 | + Date now = new Date(); |
| 174 | + |
| 175 | + String s0 = fin.readLine(); |
| 176 | + Date time0 = parse(s0); |
| 177 | + assertTrue("Log opened within last few seconds", time0.compareTo(earlier) >= 0 && time0.compareTo(now) <= 0); |
| 178 | + assertEquals("Log open message", "Log '" + FILE2.getName() + "' opened", s0.substring(30, 60)); |
| 179 | + |
| 180 | + String s1 = fin.readLine(); |
| 181 | + Date time1 = parse(s1); |
| 182 | + assertTrue("Date of message 1 within last few seconds", time1.compareTo(earlier) >= 0 && time1.compareTo(now) <= 0); |
| 183 | + assertEquals("Log message 1", "Message 1", s1.substring(30)); |
| 184 | + assertEquals("Log exception 1", "java.lang.ArrayIndexOutOfBoundsException", fin.readLine()); |
| 185 | + |
| 186 | + // Since it's difficult to test the rest of the stack trace, just skip over it |
| 187 | + String s2; |
| 188 | + Date time2; |
| 189 | + do { |
| 190 | + s2 = fin.readLine(); |
| 191 | +// System.err.println("traceback line = " + s2); |
| 192 | + time2 = parse(s2); // returns null if there is a parse error |
| 193 | + } |
| 194 | + while (time2 == null); |
| 195 | + |
| 196 | +// System.err.println("Skipped over traceback"); |
| 197 | + |
| 198 | + assertTrue("Date of message 2 within last few seconds", time2.compareTo(earlier) >= 0 && time2.compareTo(now) <= 0); |
| 199 | + assertEquals("Log message 2", "Message 2", s2.substring(30)); |
| 200 | + assertEquals("Log exception 2 (trace line 1)", |
| 201 | + "edu.rice.cs.util.LogTest.testExceptionPrinting", fin.readLine().substring(0,46)); |
| 202 | + |
| 203 | + fin.close(); |
| 204 | + } |
| 205 | + |
| 206 | + private static final int NUM_THREADS = 50; |
| 207 | + private static final int DELAY = 100; |
| 208 | + |
| 209 | + /** Attempts to test Log's behavior when called concurrently from several sources. Spawns NUM_THREADS LogTestThreads |
| 210 | + * (see above)that wait a random number between 0 and DELAY milliseconds and then log a message. The function tests |
| 211 | + * to make sure that the messages and dates are all intact (if the Log was not handling concurrent requests properly, |
| 212 | + * the entries in the log may be corrupted). |
| 213 | + */ |
| 214 | + public void testConcurrentWrites() throws IOException, InterruptedException { |
| 215 | + |
| 216 | + Log log3 = new Log(FILE3, true); |
| 217 | + Random r = new Random(); |
| 218 | + Thread[] threads = new Thread[NUM_THREADS]; |
| 219 | + for (int i = 0; i < NUM_THREADS; i++) threads[i] = new LogTestThread(log3, r.nextInt(DELAY)); |
| 220 | + for (int i = 0; i < NUM_THREADS; i++) threads[i].start(); |
| 221 | + for (int i = 0; i < NUM_THREADS; i++) threads[i].join(); |
| 222 | + |
| 223 | + BufferedReader fin = new BufferedReader(new FileReader(FILE3)); |
| 224 | + Date earlier = new Date(new Date().getTime() - SHORT_TIME); |
| 225 | + Date now = new Date(); |
| 226 | + |
| 227 | + String s0 = fin.readLine(); |
| 228 | + Date time0 = parse(s0); |
| 229 | + assertTrue("Log opened within last 10 seconds", time0.compareTo(earlier) >= 0 && time0.compareTo(now) <= 0); |
| 230 | + assertEquals("Log open message", "Log '" + FILE3.getName() + "' opened", s0.substring(30, 60)); |
| 231 | + |
| 232 | + for (int i = 0; i < NUM_THREADS; i++) { |
| 233 | + String s1 = fin.readLine(); |
| 234 | + Date time1 = parse(s1); |
| 235 | + assertTrue("Date of message within last 10 seconds", time1.compareTo(earlier) >= 0 && time1.compareTo(now) <= 0); |
| 236 | + assertEquals("Log message", "Test message", s1.substring(30)); |
| 237 | + } |
| 238 | + |
| 239 | + fin.close(); |
| 240 | + } |
| 241 | + |
| 242 | +} |
| 243 | + |
0 commit comments