• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.harmony.logging.tests.java.util.logging;
19 
20 import java.io.BufferedInputStream;
21 import java.io.ByteArrayOutputStream;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.io.PrintStream;
30 import java.util.Properties;
31 import java.util.logging.FileHandler;
32 import java.util.logging.Filter;
33 import java.util.logging.Formatter;
34 import java.util.logging.Handler;
35 import java.util.logging.Level;
36 import java.util.logging.LogManager;
37 import java.util.logging.LogRecord;
38 import java.util.logging.XMLFormatter;
39 
40 import junit.framework.TestCase;
41 
42 import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream;
43 import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper;
44 
45 public class FileHandlerTest extends TestCase {
46 
47     final static LogManager manager = LogManager.getLogManager();
48     final static Properties props = new Properties();
49     final static String className = FileHandlerTest.class.getName();
50     final static String USR_HOME_KEY = "user.home";
51     final static String TMP_DIR_KEY = "java.io.tmpdir";
52     final static String SEP = File.separator;
53 
54     private final PrintStream err = System.err;
55     private OutputStream errSubstituteStream = null;
56 
57     String homePath;
58     String tempPath;
59     FileHandler handler;
60     LogRecord r;
61 
setUp()62     protected void setUp() throws Exception {
63         super.setUp();
64         manager.reset();
65         initProps();
66         homePath = System.getProperty(USR_HOME_KEY);
67         tempPath = System.getProperty(TMP_DIR_KEY);
68 
69         File file = new File(tempPath + SEP + "log");
70         file.mkdir();
71         manager.readConfiguration(EnvironmentHelper
72                 .PropertiesToInputStream(props));
73         handler = new FileHandler();
74         r = new LogRecord(Level.CONFIG, "msg");
75         errSubstituteStream = new NullOutputStream();
76         System.setErr(new PrintStream(errSubstituteStream));
77     }
78 
initProps()79     private void initProps() {
80         props.clear();
81         props.put("java.util.logging.FileHandler.level", "FINE");
82         props.put("java.util.logging.FileHandler.filter", className
83                 + "$MockFilter");
84         props.put("java.util.logging.FileHandler.formatter", className
85                 + "$MockFormatter");
86         props.put("java.util.logging.FileHandler.encoding", "iso-8859-1");
87         // limit to only two message
88         props.put("java.util.logging.FileHandler.limit", "1000");
89         // rotation count is 2
90         props.put("java.util.logging.FileHandler.count", "2");
91         // using append mode
92         props.put("java.util.logging.FileHandler.append", "true");
93         props.put("java.util.logging.FileHandler.pattern", "%t/log/java%u.test");
94     }
95 
tearDown()96     protected void tearDown() throws Exception {
97         if (null != handler) {
98             handler.close();
99         }
100         reset(tempPath + SEP + "log", "");
101         System.setErr(err);
102         super.tearDown();
103     }
104 
testConstructor_NoUsrHome()105     public void testConstructor_NoUsrHome() throws IOException {
106         System.clearProperty(USR_HOME_KEY);
107 
108         try {
109             new FileHandler("%h/log_NoUsrHome.log");
110             fail("should throw NullPointerException");
111         } catch (NullPointerException e) {
112             // Expected
113         } finally {
114             if (homePath != null) {
115                 System.setProperty(USR_HOME_KEY, homePath);
116             }
117         }
118     }
119 
testConstructor_NoTmpDir()120     public void testConstructor_NoTmpDir() throws IOException {
121         System.clearProperty(TMP_DIR_KEY);
122 
123         try {
124             new FileHandler("%t/log_NoTmpDir.log");
125         } finally {
126             if (tempPath != null) {
127                 System.setProperty(TMP_DIR_KEY, tempPath);
128             }
129         }
130         assertFalse(new File(tempPath, "log_NoTmpDir.log").exists());
131         assertTrue(new File(homePath, "log_NoTmpDir.log").exists());
132         new File(homePath, "log_NoTmpDir.log").delete();
133     }
134 
testConstructor_NoTmpDir_NoUsrHome()135     public void testConstructor_NoTmpDir_NoUsrHome() throws IOException {
136         System.clearProperty(TMP_DIR_KEY);
137         System.clearProperty(USR_HOME_KEY);
138 
139         try {
140             new FileHandler("%t/log_NoTmpDir_NoUsrHome.log");
141             fail("should throw NullPointerException");
142         } catch (NullPointerException e) {
143             // Expected
144         } finally {
145             if (tempPath != null) {
146                 System.setProperty(TMP_DIR_KEY, tempPath);
147             }
148             if (homePath != null) {
149                 System.setProperty(USR_HOME_KEY, homePath);
150             }
151         }
152     }
153 
testLock()154     public void testLock() throws Exception {
155         FileOutputStream output = new FileOutputStream(tempPath + SEP + "log"
156                 + SEP + "java1.test.0");
157         FileHandler h = new FileHandler();
158         h.publish(r);
159         h.close();
160         assertFileContent(tempPath + SEP + "log", "java1.test.0", h
161                 .getFormatter(), "UTF-8");
162         output.close();
163     }
164 
165     /*
166      * Class under test for void FileHandler()
167      */
testFileHandler()168     public void testFileHandler() throws Exception {
169         assertEquals(handler.getEncoding(), "iso-8859-1");
170         assertTrue(handler.getFilter() instanceof MockFilter);
171         assertTrue(handler.getFormatter() instanceof MockFormatter);
172         assertEquals(handler.getLevel(), Level.FINE);
173         assertNotNull(handler.getErrorManager());
174         handler.publish(r);
175         handler.close();
176         // output 3 times, and all records left
177         // append mode is true
178         for (int i = 0; i < 3; i++) {
179             handler = new FileHandler();
180             handler.publish(r);
181             handler.close();
182         }
183         assertFileContent(tempPath + SEP + "log", "java0.test.0",
184                 new LogRecord[] { r, null, r, null, r, null, r },
185                 new MockFormatter(), "UTF-8");
186     }
187 
testDefaultValue()188     public void testDefaultValue() throws Exception {
189         handler.publish(r);
190         handler.close();
191         props.clear();
192         manager.readConfiguration(EnvironmentHelper
193                 .PropertiesToInputStream(props));
194         handler = new FileHandler();
195         assertNull(handler.getEncoding());
196         assertNull(handler.getFilter());
197         assertTrue(handler.getFormatter() instanceof XMLFormatter);
198         assertEquals(handler.getLevel(), Level.ALL);
199         assertNotNull(handler.getErrorManager());
200         handler.publish(r);
201         handler.close();
202         // output 3 times, and only one record left
203         // default append mode is false
204         for (int i = 0; i < 3; i++) {
205             handler = new FileHandler();
206             handler.publish(r);
207             handler.close();
208         }
209         assertFileContent(homePath, "java0.log", new XMLFormatter(), null);
210     }
211 
assertFileContent(String homepath, String filename, Formatter formatter, String encoding)212     private void assertFileContent(String homepath, String filename,
213             Formatter formatter, String encoding) throws Exception {
214         assertFileContent(homepath, filename, new LogRecord[] { r }, formatter, encoding);
215     }
216 
assertFileContent(String homepath, String filename, LogRecord[] lr, Formatter formatter, String encoding)217     private void assertFileContent(String homepath, String filename,
218             LogRecord[] lr, Formatter formatter, String encoding) throws Exception {
219         handler.close();
220         String msg = "";
221         // if formatter is null, the file content should be empty
222         // else the message should be formatted given records
223         if (null != formatter) {
224             StringBuffer sb = new StringBuffer();
225             sb.append(formatter.getHead(handler));
226             for (int i = 0; i < lr.length; i++) {
227                 if (null == lr[i] && i < lr.length - 1) {
228                     // if one record is null and is not the last record, means
229                     // here is
230                     // output completion point, should output tail, then output
231                     // head
232                     // (ready for next output)
233                     sb.append(formatter.getTail(handler));
234                     sb.append(formatter.getHead(handler));
235                 } else {
236                     sb.append(formatter.format(lr[i]));
237                 }
238             }
239             sb.append(formatter.getTail(handler));
240             msg = sb.toString();
241         }
242         byte[] bytes = new byte[msg.length()];
243         InputStream inputStream = null;
244         try {
245             inputStream = new BufferedInputStream(new FileInputStream(homepath
246                     + SEP + filename));
247             inputStream.read(bytes);
248             if (encoding == null) {
249                 assertEquals(msg, new String(bytes));
250             } else {
251                 assertEquals(msg, new String(bytes, encoding));
252             }
253             // assert has reached the end of the file
254             assertEquals(-1, inputStream.read());
255         } finally {
256             try {
257                 if (inputStream != null) {
258                     inputStream.close();
259                 }
260             } catch (Exception e) {
261                 // ignored
262             }
263             reset(homepath, filename);
264         }
265     }
266 
267     /**
268      * Does a cleanup of given file
269      *
270      * @param homepath
271      * @param filename
272      */
reset(String homepath, String filename)273     private void reset(String homepath, String filename) {
274         File file = null;
275         try {
276             file = new File(homepath + SEP + filename);
277             if (file.isFile()) {
278                 file.delete();
279             } else if (file.isDirectory()) {
280                 File[] files = file.listFiles();
281                 for (int i = 0; i < files.length; i++) {
282                     files[i].delete();
283                 }
284                 file.delete();
285             }
286         } catch (Exception e) {
287             e.printStackTrace();
288         }
289         try {
290             file = new File(homepath + SEP + filename + ".lck");
291             file.delete();
292         } catch (Exception e) {
293             e.printStackTrace();
294         }
295     }
296 
testLimitAndCount()297     public void testLimitAndCount() throws Exception {
298         handler.close();
299         // very small limit value, count=2
300         // output, rename current output file to the second generation file
301         // close it and open a new file as rotation output
302         handler = new FileHandler("%t/testLimitCount%g", 1, 2, false);
303         handler.publish(r);
304         handler.close();
305         assertFileContent(tempPath, "testLimitCount1", handler.getFormatter(), "UTF-8");
306 
307         // very small limit value, count=1
308         // output once, rotate(equals to nothing output)
309         handler = new FileHandler("%t/testLimitCount%g", 1, 1, false);
310         handler.publish(r);
311         handler.close();
312         assertFileContent(tempPath, "testLimitCount0", new LogRecord[0],
313                 handler.getFormatter(), "UTF-8");
314 
315         // normal case, limit is 60(>2*msg length <3*msg length), append is
316         // false
317         handler = new FileHandler("%t/testLimitCount%u", 60, 3, false);
318         LogRecord[] rs = new LogRecord[10];
319         // batch output twice to test the append mode
320         for (int i = 0; i < 5; i++) {
321             rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
322             handler.publish(rs[i]);
323         }
324         handler.close();
325         handler = new FileHandler("%t/testLimitCount%u", 60, 3, false);
326         for (int i = 5; i < 10; i++) {
327             rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
328             handler.publish(rs[i]);
329         }
330 
331         assertFileContent(tempPath, "testLimitCount0.1", new LogRecord[] {
332                 rs[5], rs[6], rs[7] }, handler.getFormatter(), "UTF-8");
333         assertFileContent(tempPath, "testLimitCount0.0", new LogRecord[] {
334                 rs[8], rs[9] }, handler.getFormatter(), "UTF-8");
335 
336         // normal case, limit is 60(>2*msg length <3*msg length), append is true
337         handler = new FileHandler("%t/testLimitCount%u", 60, 3, false);
338         // batch output twice to test the append mode
339         for (int i = 0; i < 5; i++) {
340             rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
341             handler.publish(rs[i]);
342         }
343         handler.close();
344         handler = new FileHandler("%t/testLimitCount%u", 60, 3, true);
345         for (int i = 5; i < 10; i++) {
346             rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
347             handler.publish(rs[i]);
348         }
349         handler.close();
350         assertFileContent(tempPath, "testLimitCount0.2", new LogRecord[] {
351                 rs[3], rs[4], null, rs[5] }, handler.getFormatter(), "UTF-8");
352         assertFileContent(tempPath, "testLimitCount0.1", new LogRecord[] {
353                 rs[6], rs[7], rs[8] }, handler.getFormatter(), "UTF-8");
354         assertFileContent(tempPath, "testLimitCount0.0",
355                 new LogRecord[] { rs[9] }, handler.getFormatter(), "UTF-8");
356 
357         FileHandler h1 = null;
358         FileHandler h2 = null;
359         try {
360             File logDir = new File(tempPath, "log");
361             reset(tempPath, "log");
362             logDir.mkdir();
363             h1 = new FileHandler("%t/log/a", 0, 1);
364             assertNotNull(h1);
365             h2 = new FileHandler("%t/log/a", 0, 1, false);
366             assertNotNull(h2);
367         } finally {
368             try {
369                 h1.close();
370             } catch (Exception e) {
371             }
372             try {
373                 h2.close();
374             } catch (Exception e) {
375             }
376             reset(tempPath, "log");
377         }
378     }
379 
testInvalidProperty()380     public void testInvalidProperty() throws Exception {
381         props.put("java.util.logging.FileHandler.level", "null");
382         props.put("java.util.logging.FileHandler.filter", className
383                 + "$MockFilte");
384         props.put("java.util.logging.FileHandler.formatter", className
385                 + "$MockFormatte");
386         props.put("java.util.logging.FileHandler.encoding", "ut");
387         // limit to only two message
388         props.put("java.util.logging.FileHandler.limit", "-1");
389         // rotation count is 2
390         props.put("java.util.logging.FileHandler.count", "-1");
391         // using append mode
392         props.put("java.util.logging.FileHandler.append", "bad");
393 
394         handler.close();
395 
396         manager.readConfiguration(EnvironmentHelper
397                 .PropertiesToInputStream(props));
398         handler = new FileHandler();
399         assertEquals(Level.ALL, handler.getLevel());
400         assertNull(handler.getFilter());
401         assertTrue(handler.getFormatter() instanceof XMLFormatter);
402         assertNull(handler.getEncoding());
403         handler.close();
404 
405         props.put("java.util.logging.FileHandler.pattern", "");
406         manager.readConfiguration(EnvironmentHelper
407                 .PropertiesToInputStream(props));
408         try {
409             handler = new FileHandler();
410             fail("shouldn't open file with empty name");
411         } catch (NullPointerException e) {
412         }
413     }
414 
testInvalidParams()415     public void testInvalidParams() throws IOException {
416 
417         // %t and %p parsing can add file separator automatically
418         FileHandler h1 = new FileHandler("%taaa");
419         h1.close();
420         File file = new File(tempPath + SEP + "aaa");
421         assertTrue(file.exists());
422         reset(tempPath, "aaa");
423 
424         // On platforms besides Android this test was probably checking a non-existent directory:
425         // i.e. when expanded %t/%h would have been a nonexistent path but would have contained
426         // multiple names separated by path separators. On Android %h is "/" so this test breaks.
427         // Removed for Android.
428         // always parse special pattern
429         // try {
430         //    h1 = new FileHandler("%t/%h");
431         //    fail("should throw null exception");
432         //} catch (FileNotFoundException e) {
433         //}
434 
435         h1 = new FileHandler("%t%g");
436         h1.close();
437         file = new File(tempPath + SEP + "0");
438         assertTrue(file.exists());
439         reset(tempPath, "0");
440         h1 = new FileHandler("%t%u%g");
441         h1.close();
442         file = new File(tempPath + SEP + "00");
443         assertTrue(file.exists());
444         reset(tempPath, "00");
445 
446         // this is normal case
447         h1 = new FileHandler("%t/%u%g%%g");
448         h1.close();
449         file = new File(tempPath + SEP + "00%g");
450         assertTrue(file.exists());
451         reset(tempPath, "00%g");
452 
453         // multi separator has no effect
454         h1 = new FileHandler("//%t//multi%g");
455         h1.close();
456         file = new File(tempPath + SEP + "multi0");
457         assertTrue(file.exists());
458         reset(tempPath, "multi0");
459 
460         // bad directory, IOException
461         try {
462             h1 = new FileHandler("%t/baddir/multi%g");
463             fail("should throw IO exception");
464         } catch (IOException e) {
465         }
466         file = new File(tempPath + SEP + "baddir" + SEP + "multi0");
467         assertFalse(file.exists());
468 
469         try {
470             new FileHandler(null);
471             fail("should throw null exception");
472         } catch (NullPointerException e) {
473         }
474         try {
475             handler.publish(null);
476         } catch (NullPointerException e) {
477             fail("should not throw NPE");
478         }
479         try {
480             new FileHandler(null, false);
481             fail("should throw null exception");
482         } catch (NullPointerException e) {
483         }
484         try {
485             // regression test for Harmony-1299
486             new FileHandler("");
487             fail("should throw IllegalArgumentException");
488         } catch (IllegalArgumentException e) {
489             // expected
490         }
491         try {
492             new FileHandler("%t/java%u", 0, 0);
493             fail("should throw IllegalArgumentException");
494         } catch (IllegalArgumentException e) {
495         }
496         try {
497             new FileHandler("%t/java%u", -1, 1);
498             fail("should throw IllegalArgumentException");
499         } catch (IllegalArgumentException e) {
500         }
501     }
502 
503     // set output stream still works, just like super StreamHandler
testSetOutputStream()504     public void testSetOutputStream() throws Exception {
505         MockFileHandler handler = new MockFileHandler("%t/setoutput.log");
506         handler.setFormatter(new MockFormatter());
507         handler.publish(r);
508 
509         ByteArrayOutputStream out = new ByteArrayOutputStream();
510         handler.publicSetOutputStream(out);
511         handler.publish(r);
512         handler.close();
513         String msg = new String(out.toByteArray());
514         Formatter f = handler.getFormatter();
515         assertEquals(msg, f.getHead(handler) + f.format(r) + f.getTail(handler));
516         assertFileContent(tempPath, "setoutput.log", handler.getFormatter(), null);
517     }
518 
519     /*
520      * Class under test for void FileHandler(String)
521      */
testFileHandlerString()522     public void testFileHandlerString() throws Exception {
523         // test if unique ids not specified, it will append at the end
524         // no generation number is used
525         FileHandler h = new FileHandler("%t/log/string");
526         FileHandler h2 = new FileHandler("%t/log/string");
527         FileHandler h3 = new FileHandler("%t/log/string");
528         FileHandler h4 = new FileHandler("%t/log/string");
529         h.publish(r);
530         h2.publish(r);
531         h3.publish(r);
532         h4.publish(r);
533         h.close();
534         h2.close();
535         h3.close();
536         h4.close();
537         assertFileContent(tempPath + SEP + "log", "string", h.getFormatter(), "UTF-8");
538         assertFileContent(tempPath + SEP + "log", "string.1", h.getFormatter(), "UTF-8");
539         assertFileContent(tempPath + SEP + "log", "string.2", h.getFormatter(), "UTF-8");
540         assertFileContent(tempPath + SEP + "log", "string.3", h.getFormatter(), "UTF-8");
541 
542         // default is append mode
543         FileHandler h6 = new FileHandler("%t/log/string%u.log");
544         h6.publish(r);
545         h6.close();
546         FileHandler h7 = new FileHandler("%t/log/string%u.log");
547         h7.publish(r);
548         h7.close();
549         try {
550             assertFileContent(tempPath + SEP + "log", "string0.log", h
551                     .getFormatter(), "UTF-8");
552             fail("should assertion failed");
553         } catch (Error e) {
554         }
555         File file = new File(tempPath + SEP + "log");
556         assertTrue(file.list().length <= 2);
557 
558         // test unique ids
559         FileHandler h8 = new FileHandler("%t/log/%ustring%u.log");
560         h8.publish(r);
561         FileHandler h9 = new FileHandler("%t/log/%ustring%u.log");
562         h9.publish(r);
563         h9.close();
564         h8.close();
565         assertFileContent(tempPath + SEP + "log", "0string0.log", h
566                 .getFormatter(), "UTF-8");
567         assertFileContent(tempPath + SEP + "log", "1string1.log", h
568                 .getFormatter(), "UTF-8");
569         file = new File(tempPath + SEP + "log");
570         assertTrue(file.list().length <= 2);
571     }
572 
testEmptyPattern_3params()573     public void testEmptyPattern_3params() throws SecurityException,
574             IOException {
575         // regression HARMONY-2421
576         try {
577             new FileHandler(new String(), 1, 1);
578             fail("Expected an IllegalArgumentException");
579         } catch (IllegalArgumentException e) {
580             // Expected
581         }
582     }
583 
testEmptyPattern_2params()584     public void testEmptyPattern_2params() throws SecurityException,
585             IOException {
586         // regression HARMONY-2421
587         try {
588             new FileHandler(new String(), true);
589             fail("Expected an IllegalArgumentException");
590         } catch (IllegalArgumentException e) {
591             // Expected
592         }
593     }
594 
testEmptyPattern_4params()595     public void testEmptyPattern_4params() throws SecurityException,
596             IOException {
597         // regression HARMONY-2421
598         try {
599             new FileHandler(new String(), 1, 1, true);
600             fail("Expected an IllegalArgumentException");
601         } catch (IllegalArgumentException e) {
602             // Expected
603         }
604     }
605 
606     /*
607      * mock classes
608      */
609     public static class MockFilter implements Filter {
isLoggable(LogRecord record)610         public boolean isLoggable(LogRecord record) {
611             return !record.getMessage().equals("false");
612         }
613     }
614 
615     public static class MockFormatter extends Formatter {
format(LogRecord r)616         public String format(LogRecord r) {
617             if (null == r) {
618                 return "";
619             }
620             return r.getMessage() + " by MockFormatter\n";
621         }
622 
getTail(Handler h)623         public String getTail(Handler h) {
624             return "tail\n";
625         }
626 
getHead(Handler h)627         public String getHead(Handler h) {
628             return "head\n";
629         }
630     }
631 
632     public static class MockFileHandler extends FileHandler {
MockFileHandler()633         public MockFileHandler() throws IOException {
634             super();
635         }
636 
MockFileHandler(String pattern)637         public MockFileHandler(String pattern) throws IOException {
638             super(pattern);
639         }
640 
publicSetOutputStream(OutputStream stream)641         public void publicSetOutputStream(OutputStream stream) {
642             super.setOutputStream(stream);
643         }
644     }
645 }
646