FileHandlerTest.java revision 89c1feb0a69a7707b271086e749975b3f7acacf7
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
18package org.apache.harmony.logging.tests.java.util.logging;
19
20import dalvik.annotation.TestTargetClass;
21import dalvik.annotation.TestInfo;
22import dalvik.annotation.TestLevel;
23import dalvik.annotation.TestTarget;
24
25import java.io.BufferedReader;
26import java.io.ByteArrayOutputStream;
27import java.io.File;
28import java.io.FileOutputStream;
29import java.io.FilePermission;
30import java.io.FileReader;
31import java.io.IOException;
32import java.io.OutputStream;
33import java.io.PrintStream;
34import java.io.Reader;
35import java.io.StringWriter;
36import java.security.Permission;
37import java.util.Properties;
38import java.util.logging.FileHandler;
39import java.util.logging.Filter;
40import java.util.logging.Formatter;
41import java.util.logging.Handler;
42import java.util.logging.Level;
43import java.util.logging.LogManager;
44import java.util.logging.LogRecord;
45import java.util.logging.LoggingPermission;
46import java.util.logging.XMLFormatter;
47
48import junit.framework.TestCase;
49
50import org.apache.harmony.logging.tests.java.util.logging.HandlerTest.NullOutputStream;
51import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper;
52
53/**
54 */
55@TestTargetClass(FileHandler.class)
56public class FileHandlerTest extends TestCase {
57
58    static LogManager manager = LogManager.getLogManager();
59
60    final static Properties props = new Properties();
61
62    final static String className = FileHandlerTest.class.getName();
63
64    final static StringWriter writer = new StringWriter();
65
66    final static SecurityManager securityManager = new MockLogSecurityManager();
67
68    final static String HOMEPATH = System.getProperty("user.home");
69
70    final static String TEMPPATH = System.getProperty("java.io.tmpdir");
71
72    final static String SEP = File.separator;
73
74    private final PrintStream err = System.err;
75
76    private OutputStream errSubstituteStream = null;
77
78    FileHandler handler;
79
80    LogRecord r;
81
82    /*
83     * @see TestCase#setUp()
84     */
85    protected void setUp() throws Exception {
86        super.setUp();
87        manager.reset();
88
89        //initProp
90        props.clear();
91        props.put("java.util.logging.FileHandler.level", "FINE");
92        props.put("java.util.logging.FileHandler.filter", className
93                + "$MockFilter");
94        props.put("java.util.logging.FileHandler.formatter", className
95                + "$MockFormatter");
96        props.put("java.util.logging.FileHandler.encoding", "iso-8859-1");
97        // limit to only two message
98        props.put("java.util.logging.FileHandler.limit", "1000");
99        // rotation count is 2
100        props.put("java.util.logging.FileHandler.count", "2");
101        // using append mode
102        props.put("java.util.logging.FileHandler.append", "true");
103        props.put("java.util.logging.FileHandler.pattern",
104                        "%t/log/java%u.test");
105
106
107        File file = new File(TEMPPATH + SEP + "log");
108        file.mkdir();
109        manager.readConfiguration(EnvironmentHelper
110                .PropertiesToInputStream(props));
111        handler = new FileHandler();
112        r = new LogRecord(Level.CONFIG, "msg");
113        errSubstituteStream = new NullOutputStream();
114        System.setErr(new PrintStream(errSubstituteStream));
115    }
116
117
118    /*
119     * @see TestCase#tearDown()
120     */
121
122    protected void tearDown() throws Exception {
123        if (null != handler) {
124            handler.close();
125        }
126        reset(TEMPPATH + SEP + "log", "");
127        System.setErr(err);
128        super.tearDown();
129    }
130    @TestInfo(
131      level = TestLevel.COMPLETE,
132      purpose = "Verifies getFormatter() method after close.",
133      targets = {
134        @TestTarget(
135          methodName = "getFormatter",
136          methodArgs = {}
137        )
138    })
139    public void _testLock() throws Exception {
140        FileOutputStream output = new FileOutputStream(TEMPPATH + SEP + "log"
141                + SEP + "java1.test.Lock");
142        FileHandler h = new FileHandler();
143        h.publish(r);
144        h.close();
145        assertFileContent(TEMPPATH + SEP + "log", "java1.test.Lock", h.getFormatter());
146        output.close();
147    }
148
149    /*
150     * test for constructor void FileHandler()
151     */
152    @TestInfo(
153      level = TestLevel.PARTIAL_OK,
154      purpose = "Doesn't verify exceptions.",
155      targets = {
156        @TestTarget(
157          methodName = "FileHandler",
158          methodArgs = {}
159        )
160    })
161    public void testFileHandler() throws Exception {
162        assertEquals("character encoding is non equal to actual value",
163                "iso-8859-1", handler.getEncoding());
164        assertNotNull("Filter is null", handler.getFilter());
165        assertNotNull("Formatter is null", handler.getFormatter());
166        assertEquals("is non equal to actual value", Level.FINE, handler
167                .getLevel());
168        assertNotNull("ErrorManager is null", handler.getErrorManager());
169        handler.publish(r);
170        handler.close();
171        // output 3 times, and all records left
172        // append mode is true
173        for (int i = 0; i < 3; i++) {
174            handler = new FileHandler();
175            handler.publish(r);
176            handler.close();
177        }
178        assertFileContent(TEMPPATH + SEP + "log", "java0.test.0",
179                new LogRecord[] { r, null, r, null, r, null, r },
180                new MockFormatter());
181    }
182
183    /*
184     * test for constructor void FileHandler(String)
185     */
186    @TestInfo(
187      level = TestLevel.PARTIAL,
188      purpose = "Doesn't verify exceptions.",
189      targets = {
190        @TestTarget(
191          methodName = "FileHandler",
192          methodArgs = {java.lang.String.class}
193        )
194    })
195    public void testFileHandler_1params() throws Exception {
196
197        handler = new FileHandler("%t/log/string");
198        assertEquals("character encoding is non equal to actual value",
199                "iso-8859-1", handler.getEncoding());
200        assertNotNull("Filter is null", handler.getFilter());
201        assertNotNull("Formatter is null", handler.getFormatter());
202        assertEquals("is non equal to actual value", Level.FINE, handler
203                .getLevel());
204        assertNotNull("ErrorManager is null", handler.getErrorManager());
205        handler.publish(r);
206        handler.close();
207
208        // output 3 times, and all records left
209        // append mode is true
210        for (int i = 0; i < 3; i++) {
211            handler = new FileHandler("%t/log/string");
212            handler.publish(r);
213            handler.close();
214        }
215        assertFileContent(TEMPPATH + SEP + "log", "/string", new LogRecord[] {
216                r, null, r, null, r, null, r }, new MockFormatter());
217
218        // test if unique ids not specified, it will append at the end
219        // no generation number is used
220        FileHandler h = new FileHandler("%t/log/string");
221        FileHandler h2 = new FileHandler("%t/log/string");
222        FileHandler h3 = new FileHandler("%t/log/string");
223        FileHandler h4 = new FileHandler("%t/log/string");
224        h.publish(r);
225        h2.publish(r);
226        h3.publish(r);
227        h4.publish(r);
228        h.close();
229        h2.close();
230        h3.close();
231        h4.close();
232        assertFileContent(TEMPPATH + SEP + "log", "string", h.getFormatter());
233        assertFileContent(TEMPPATH + SEP + "log", "string.1", h.getFormatter());
234        assertFileContent(TEMPPATH + SEP + "log", "string.2", h.getFormatter());
235        assertFileContent(TEMPPATH + SEP + "log", "string.3", h.getFormatter());
236
237        // default is append mode
238        FileHandler h6 = new FileHandler("%t/log/string%u.log");
239        h6.publish(r);
240        h6.close();
241        FileHandler h7 = new FileHandler("%t/log/string%u.log");
242        h7.publish(r);
243        h7.close();
244        try {
245            assertFileContent(TEMPPATH + SEP + "log", "string0.log", h
246                    .getFormatter());
247            fail("should assertion failed");
248        } catch (Error e) {
249        }
250        File file = new File(TEMPPATH + SEP + "log");
251        assertTrue("length list of file is incorrect", file.list().length <= 2);
252
253        // test unique ids
254        FileHandler h8 = new FileHandler("%t/log/%ustring%u.log");
255        h8.publish(r);
256        FileHandler h9 = new FileHandler("%t/log/%ustring%u.log");
257        h9.publish(r);
258        h9.close();
259        h8.close();
260        assertFileContent(TEMPPATH + SEP + "log", "0string0.log", h
261                .getFormatter());
262        assertFileContent(TEMPPATH + SEP + "log", "1string1.log", h
263                .getFormatter());
264        file = new File(TEMPPATH + SEP + "log");
265        assertTrue("length list of file is incorrect", file.list().length <= 2);
266    }
267
268    /*
269     * test for constructor void FileHandler(String pattern, boolean append)
270     */
271    @TestInfo(
272      level = TestLevel.PARTIAL,
273      purpose = "Doesn't verify exceptions.",
274      targets = {
275        @TestTarget(
276          methodName = "FileHandler",
277          methodArgs = {java.lang.String.class, boolean.class}
278        )
279    })
280    public void testFileHandler_2params() throws Exception {
281        boolean append = false;
282        do {
283            append = !append;
284            handler = new FileHandler("%t/log/string", append);
285            assertEquals("character encoding is non equal to actual value",
286                    "iso-8859-1", handler.getEncoding());
287            assertNotNull("Filter is null", handler.getFilter());
288            assertNotNull("Formatter is null", handler.getFormatter());
289            assertEquals("is non equal to actual value", Level.FINE, handler
290                    .getLevel());
291            assertNotNull("ErrorManager is null", handler.getErrorManager());
292            handler.publish(r);
293            handler.close();
294            // output 3 times, and all records left
295            // append mode is true
296            for (int i = 0; i < 3; i++) {
297                handler = new FileHandler("%t/log/string", append);
298                handler.publish(r);
299                handler.close();
300            }
301            if (append) {
302                assertFileContent(TEMPPATH + SEP + "log", "/string",
303                        new LogRecord[] { r, null, r, null, r, null, r },
304                        new MockFormatter());
305            } else {
306                assertFileContent(TEMPPATH + SEP + "log", "/string",
307                        new LogRecord[] { r }, new MockFormatter());
308            }
309        } while (append);
310    }
311
312    /*
313     * test for constructor void FileHandler(String pattern, int limit, int
314     * count)
315     */
316    @TestInfo(
317      level = TestLevel.PARTIAL,
318      purpose = "Doesn't verify exceptions.",
319      targets = {
320        @TestTarget(
321          methodName = "FileHandler",
322          methodArgs = {java.lang.String.class, int.class, int.class}
323        )
324    })
325    public void testFileHandler_3params() throws Exception {
326        int limit = 120;
327        int count = 1;
328        handler = new FileHandler("%t/log/string", limit, count);
329        assertEquals("character encoding is non equal to actual value",
330                "iso-8859-1", handler.getEncoding());
331        assertNotNull("Filter is null", handler.getFilter());
332        assertNotNull("Formatter is null", handler.getFormatter());
333        assertEquals("is non equal to actual value", Level.FINE, handler
334                .getLevel());
335        assertNotNull("ErrorManager is null", handler.getErrorManager());
336        handler.publish(r);
337        handler.close();
338        // output 3 times, and all records left
339        // append mode is true
340        for (int i = 0; i < 3; i++) {
341            handler = new FileHandler("%t/log/string", limit, count);
342            handler.publish(r);
343            handler.close();
344        }
345        assertFileContent(TEMPPATH + SEP + "log", "/string", new LogRecord[] {
346                r, null, r, null, r, null, r }, new MockFormatter());
347    }
348
349    /*
350     * test for constructor public FileHandler(String pattern, int limit, int
351     * count, boolean append)
352     */
353    @TestInfo(
354      level = TestLevel.PARTIAL,
355      purpose = "Doesn't verify exceptions.",
356      targets = {
357        @TestTarget(
358          methodName = "FileHandler",
359          methodArgs = {java.lang.String.class, int.class, int.class, boolean.class}
360        )
361    })
362    public void testFileHandler_4params() throws Exception {
363        int limit = 120;
364        int count = 1;
365        boolean append = false;
366        do {
367            append = !append;
368            handler = new FileHandler("%t/log/string", limit, count, append);
369            assertEquals("character encoding is non equal to actual value",
370                    "iso-8859-1", handler.getEncoding());
371            assertNotNull("Filter is null", handler.getFilter());
372            assertNotNull("Formatter is null", handler.getFormatter());
373            assertEquals("is non equal to actual value", Level.FINE, handler
374                    .getLevel());
375            assertNotNull("ErrorManager is null", handler.getErrorManager());
376            handler.publish(r);
377            handler.close();
378            // output 3 times, and all records left
379            // append mode is true
380            for (int i = 0; i < 3; i++) {
381                handler = new FileHandler("%t/log/string", limit, count, append);
382                handler.publish(r);
383                handler.close();
384            }
385            if (append) {
386                assertFileContent(TEMPPATH + SEP + "log", "/string",
387                        new LogRecord[] { r, null, r, null, r, null, r },
388                        new MockFormatter());
389            } else {
390                assertFileContent(TEMPPATH + SEP + "log", "/string",
391                        new LogRecord[] { r }, new MockFormatter());
392            }
393        } while (append);
394    }
395    @TestInfo(
396      level = TestLevel.PARTIAL,
397      purpose = "",
398      targets = {
399        @TestTarget(
400          methodName = "getEncoding",
401          methodArgs = {}
402        ),
403        @TestTarget(
404          methodName = "getFilter",
405          methodArgs = {}
406        ),
407        @TestTarget(
408          methodName = "getFormatter",
409          methodArgs = {}
410        ),
411        @TestTarget(
412          methodName = "getLevel",
413          methodArgs = {}
414        ),
415        @TestTarget(
416          methodName = "getErrorManager",
417          methodArgs = {}
418        )
419    })
420    public void testDefaultValue() throws Exception {
421        handler.publish(r);
422        handler.close();
423        props.clear();
424        manager.readConfiguration(EnvironmentHelper
425                .PropertiesToInputStream(props));
426        handler = new FileHandler();
427        assertNull(handler.getEncoding());
428        assertNull(handler.getFilter());
429        assertTrue(handler.getFormatter() instanceof XMLFormatter);
430        assertEquals(handler.getLevel(), Level.ALL);
431        assertNotNull(handler.getErrorManager());
432        handler.publish(r);
433        handler.close();
434        // output 3 times, and only one record left
435        // default append mode is false
436        for (int i = 0; i < 3; i++) {
437            handler = new FileHandler();
438            handler.publish(r);
439            handler.close();
440        }
441        assertFileContent(HOMEPATH, "java0.log", new XMLFormatter());
442    }
443
444    private void assertFileContent(String homepath, String filename,
445            Formatter formatter) throws Exception {
446        assertFileContent(homepath, filename, new LogRecord[] { r }, formatter);
447    }
448
449    private void assertFileContent(String homepath, String filename,
450            LogRecord[] lr, Formatter formatter) throws Exception {
451        handler.close();
452        String msg = "";
453        // if formatter is null, the file content should be empty
454        // else the message should be formatted given records
455        if (null != formatter) {
456            StringBuffer sb = new StringBuffer();
457            sb.append(formatter.getHead(handler));
458            for (int i = 0; i < lr.length; i++) {
459                if (null == lr[i] && i < lr.length - 1) {
460                    // if one record is null and is not the last record, means
461                    // here is
462                    // output completion point, should output tail, then output
463                    // head
464                    // (ready for next output)
465                    sb.append(formatter.getTail(handler));
466                    sb.append(formatter.getHead(handler));
467                } else {
468                    sb.append(formatter.format(lr[i]));
469                }
470            }
471            sb.append(formatter.getTail(handler));
472            msg = sb.toString();
473        }
474        char[] chars = new char[msg.length()];
475        Reader reader = null;
476        try {
477            reader = new BufferedReader(new FileReader(homepath + SEP
478                    + filename));
479            reader.read(chars);
480            assertEquals(msg, new String(chars));
481            // assert has reached the end of the file
482            assertEquals(-1, reader.read());
483        } finally {
484            try {
485                if (reader != null) {
486                    reader.close();
487                }
488            } catch (Exception e) {
489                // don't care
490            }
491            reset(homepath, filename);
492        }
493    }
494
495    /**
496     * Does a cleanup of given file
497     *
498     * @param homepath
499     * @param filename
500     */
501    private void reset(String homepath, String filename) {
502        File file = null;
503        try {
504            file = new File(homepath + SEP + filename);
505            if (file.isFile()) {
506                file.delete();
507            } else if (file.isDirectory()) {
508                File[] files = file.listFiles();
509                for (int i = 0; i < files.length; i++) {
510                    files[i].delete();
511                }
512                file.delete();
513            }
514        } catch (Exception e) {
515            e.printStackTrace();
516        }
517        try {
518            file = new File(homepath + SEP + filename + ".lck");
519            file.delete();
520        } catch (Exception e) {
521            e.printStackTrace();
522        }
523    }
524    @TestInfo(
525      level = TestLevel.COMPLETE,
526      purpose = "",
527      targets = {
528        @TestTarget(
529          methodName = "FileHandler",
530          methodArgs = {java.lang.String.class, int.class, int.class, boolean.class}
531        )
532    })
533    public void testLimitAndCount() throws Exception {
534        handler.close();
535        // very small limit value, count=2
536        // output, rename current output file to the second generation file
537        // close it and open a new file as rotation output
538        handler = new FileHandler("%t/testLimitCount%g", 1, 2, false);
539        handler.publish(r);
540        handler.close();
541        assertFileContent(TEMPPATH, "testLimitCount1", handler.getFormatter());
542
543        // very small limit value, count=1
544        // output once, rotate(equals to nothing output)
545        handler = new FileHandler("%t/testLimitCount%g", 1, 1, false);
546        handler.publish(r);
547        handler.close();
548        assertFileContent(TEMPPATH, "testLimitCount0", new LogRecord[0],
549                handler.getFormatter());
550
551        // normal case, limit is 60(>2*msg length <3*msg length), append is
552        // false
553        handler = new FileHandler("%t/testLimitCount%u", 60, 3, false);
554        LogRecord[] rs = new LogRecord[10];
555        // batch output twice to test the append mode
556        for (int i = 0; i < 5; i++) {
557            rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
558            handler.publish(rs[i]);
559        }
560        handler.close();
561        handler = new FileHandler("%t/testLimitCount%u", 60, 3, false);
562        for (int i = 5; i < 10; i++) {
563            rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
564            handler.publish(rs[i]);
565        }
566
567        assertFileContent(TEMPPATH, "testLimitCount0.1", new LogRecord[] {
568                rs[5], rs[6], rs[7] }, handler.getFormatter());
569        assertFileContent(TEMPPATH, "testLimitCount0.0", new LogRecord[] {
570                rs[8], rs[9] }, handler.getFormatter());
571
572        // normal case, limit is 60(>2*msg length <3*msg length), append is true
573        handler = new FileHandler("%t/testLimitCount%u", 60, 3, false);
574        // batch output twice to test the append mode
575        for (int i = 0; i < 5; i++) {
576            rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
577            handler.publish(rs[i]);
578        }
579        handler.close();
580        handler = new FileHandler("%t/testLimitCount%u", 60, 3, true);
581        for (int i = 5; i < 10; i++) {
582            rs[i] = new LogRecord(Level.SEVERE, "msg" + i);
583            handler.publish(rs[i]);
584        }
585        handler.close();
586        assertFileContent(TEMPPATH, "testLimitCount0.2", new LogRecord[] {
587                rs[3], rs[4], null, rs[5] }, handler.getFormatter());
588        assertFileContent(TEMPPATH, "testLimitCount0.1", new LogRecord[] {
589                rs[6], rs[7], rs[8] }, handler.getFormatter());
590        assertFileContent(TEMPPATH, "testLimitCount0.0",
591                new LogRecord[] { rs[9] }, handler.getFormatter());
592
593        FileHandler h1 = null;
594        FileHandler h2 = null;
595        try {
596            File logDir = new File("log");
597            reset("log", "");
598            logDir.mkdir();
599            h1 = new FileHandler("log/a", 0, 1);
600            assertNotNull(h1);
601            h2 = new FileHandler("log/a", 0, 1, false);
602            assertNotNull(h2);
603        } finally {
604            try {
605                h1.close();
606            } catch (Exception e) {
607            }
608            try {
609                h2.close();
610            } catch (Exception e) {
611            }
612            reset("log", "");
613        }
614    }
615    @TestInfo(
616      level = TestLevel.PARTIAL,
617      purpose = "",
618      targets = {
619        @TestTarget(
620          methodName = "FileHandler",
621          methodArgs = {}
622        ),
623        @TestTarget(
624          methodName = "FileHandler",
625          methodArgs = {java.lang.String.class}
626        ),
627        @TestTarget(
628          methodName = "FileHandler",
629          methodArgs = {java.lang.String.class, boolean.class}
630        ),
631        @TestTarget(
632          methodName = "FileHandler",
633          methodArgs = {java.lang.String.class, int.class, int.class}
634        ),
635        @TestTarget(
636          methodName = "FileHandler",
637          methodArgs = {java.lang.String.class, int.class, int.class, boolean.class}
638        )
639    })
640    public void testSecurity() throws IOException {
641        SecurityManager currentManager = System.getSecurityManager();
642
643        try {
644            System.setSecurityManager(new MockLogSecurityManager());
645            try {
646                handler.close();
647                fail("should throw security exception");
648            } catch (SecurityException e) {
649            }
650
651            handler.publish(new LogRecord(Level.SEVERE, "msg"));
652            try {
653                handler = new FileHandler();
654                fail("should throw security exception");
655            } catch (SecurityException e) {
656            }
657
658            try {
659                handler = new FileHandler("pattern1");
660                fail("should throw security exception");
661            } catch (SecurityException e) {
662            }
663            try {
664                handler = new FileHandler("pattern2", true);
665                fail("should throw security exception");
666            } catch (SecurityException e) {
667            }
668            try {
669                handler = new FileHandler("pattern3", 1000, 1);
670                fail("should throw security exception");
671            } catch (SecurityException e) {
672            }
673            try {
674                handler = new FileHandler("pattern4", 1000, 1, true);
675                fail("should throw security exception");
676            } catch (SecurityException e) {
677            }
678        } finally {
679            System.setSecurityManager(currentManager);
680        }
681
682    }
683    @TestInfo(
684      level = TestLevel.PARTIAL,
685      purpose = "Verifies SecurityException.",
686      targets = {
687        @TestTarget(
688          methodName = "close",
689          methodArgs = {}
690        ),
691        @TestTarget(
692          methodName = "FileHandler",
693          methodArgs = {}
694        ),
695        @TestTarget(
696          methodName = "FileHandler",
697          methodArgs = {java.lang.String.class}
698        ),
699        @TestTarget(
700          methodName = "FileHandler",
701          methodArgs = {java.lang.String.class, boolean.class}
702        ),
703        @TestTarget(
704          methodName = "FileHandler",
705          methodArgs = {java.lang.String.class, int.class, int.class}
706        ),
707        @TestTarget(
708          methodName = "FileHandler",
709          methodArgs = {java.lang.String.class, int.class, int.class, boolean.class}
710        )
711    })
712    public void testFileSecurity() throws IOException {
713        SecurityManager currentManager = System.getSecurityManager();
714
715        try {
716            System.setSecurityManager(new MockFileSecurityManager());
717            handler.publish(new LogRecord(Level.SEVERE, "msg"));
718            try {
719                handler.close();
720                fail("should throw security exception");
721            } catch (SecurityException e) {
722            }
723
724            try {
725                handler = new FileHandler();
726                fail("should throw security exception");
727            } catch (SecurityException e) {
728            }
729
730            try {
731                handler = new FileHandler("pattern1");
732                fail("should throw security exception");
733            } catch (SecurityException e) {
734            }
735            try {
736                handler = new FileHandler("pattern2", true);
737                fail("should throw security exception");
738            } catch (SecurityException e) {
739            }
740            try {
741                handler = new FileHandler("pattern3", 1000, 1);
742                fail("should throw security exception");
743            } catch (SecurityException e) {
744            }
745            try {
746                handler = new FileHandler("pattern4", 1000, 1, true);
747                fail("should throw security exception");
748            } catch (SecurityException e) {
749            }
750        } finally {
751            System.setSecurityManager(currentManager);
752        }
753    }
754    @TestInfo(
755      level = TestLevel.PARTIAL_OK,
756      purpose = "Verifies FileHandler when configuration file is invalid.",
757      targets = {
758        @TestTarget(
759          methodName = "FileHandler",
760          methodArgs = {}
761        )
762    })
763    public void testInvalidProperty() throws Exception {
764        props.put("java.util.logging.FileHandler.level", "null");
765        props.put("java.util.logging.FileHandler.filter", className
766                + "$MockFilte");
767        props.put("java.util.logging.FileHandler.formatter", className
768                + "$MockFormatte");
769        props.put("java.util.logging.FileHandler.encoding", "ut");
770        // limit to only two message
771        props.put("java.util.logging.FileHandler.limit", "-1");
772        // rotation count is 2
773        props.put("java.util.logging.FileHandler.count", "-1");
774        // using append mode
775        props.put("java.util.logging.FileHandler.append", "bad");
776
777        handler.close();
778
779        manager.readConfiguration(EnvironmentHelper
780                .PropertiesToInputStream(props));
781        handler = new FileHandler();
782        assertEquals(Level.ALL, handler.getLevel());
783        assertNull(handler.getFilter());
784        assertTrue(handler.getFormatter() instanceof XMLFormatter);
785        assertNull(handler.getEncoding());
786        handler.close();
787
788        props.put("java.util.logging.FileHandler.pattern", "");
789        manager.readConfiguration(EnvironmentHelper
790                .PropertiesToInputStream(props));
791        try {
792            handler = new FileHandler();
793            fail("shouldn't open file with empty name");
794        } catch (NullPointerException e) {
795        }
796    }
797    @TestInfo(
798      level = TestLevel.COMPLETE,
799      purpose = "Verifies illegal parameters and exceptions: " +
800            "IOException, NullPointerException, IllegalArgumentException.",
801      targets = {
802        @TestTarget(
803          methodName = "FileHandler",
804          methodArgs = {java.lang.String.class}
805        ),
806        @TestTarget(
807          methodName = "FileHandler",
808          methodArgs = {java.lang.String.class, boolean.class}
809        ),
810        @TestTarget(
811          methodName = "FileHandler",
812          methodArgs = {java.lang.String.class, int.class, int.class}
813        ),
814        @TestTarget(
815          methodName = "publish",
816          methodArgs = {java.util.logging.LogRecord.class}
817        )
818    })
819    public void _testInvalidParams() throws IOException {
820
821        // %t and %p parsing can add file separator automatically
822        FileHandler h1 = new FileHandler("%taaa");
823        h1.close();
824        File file = new File(TEMPPATH + SEP + "aaa");
825        assertTrue(file.exists());
826        reset(TEMPPATH, "aaa");
827
828        // always parse special pattern
829        try {
830            h1 = new FileHandler("%t/%h");
831        } catch (Exception e) {
832            fail("Unexpected exception " + e.toString());
833        }
834        h1 = new FileHandler("%t%g");
835        h1.close();
836        file = new File(TEMPPATH + SEP + "0");
837        assertTrue(file.exists());
838        reset(TEMPPATH, "0");
839        h1 = new FileHandler("%t%u%g");
840        h1.close();
841        file = new File(TEMPPATH + SEP + "00");
842        assertTrue(file.exists());
843        reset(TEMPPATH, "00");
844
845        // this is normal case
846        h1 = new FileHandler("%t/%u%g%%g");
847        h1.close();
848        file = new File(TEMPPATH + SEP + "00%g");
849        assertTrue(file.exists());
850        reset(TEMPPATH, "00%g");
851
852        // multi separator has no effect
853        h1 = new FileHandler("//%t//multi%g");
854        h1.close();
855        file = new File(TEMPPATH + SEP + "multi0");
856        assertTrue(file.exists());
857        reset(TEMPPATH, "multi0");
858
859        // bad directory, IOException
860        try {
861            h1 = new FileHandler("%t/baddir/multi%g");
862            fail("should throw IO exception");
863        } catch (IOException e) {
864        }
865        file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
866        assertFalse(file.exists());
867
868     // bad directory, IOException, append
869        try {
870            h1 = new FileHandler("%t/baddir/multi%g", true);
871            fail("should throw IO exception");
872        } catch (IOException e) {
873        }
874        file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
875        assertFalse(file.exists());
876        try {
877            h1 = new FileHandler("%t/baddir/multi%g", false);
878            fail("should throw IO exception");
879        } catch (IOException e) {
880        }
881        file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
882        assertFalse(file.exists());
883
884        try {
885            h1 = new FileHandler("%t/baddir/multi%g", 12, 4);
886            fail("should throw IO exception");
887        } catch (IOException e) {
888        }
889        file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
890        assertFalse(file.exists());
891
892        try {
893            h1 = new FileHandler("%t/baddir/multi%g", 12, 4, true);
894            fail("should throw IO exception");
895        } catch (IOException e) {
896        }
897        file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
898        assertFalse(file.exists());
899
900
901        try {
902            new FileHandler(null);
903            fail("should throw null exception");
904        } catch (NullPointerException e) {
905        }
906        try {
907            handler.publish(null);
908        } catch (NullPointerException e) {
909            fail("should not throw NPE");
910        }
911        try {
912            new FileHandler(null, false);
913            fail("should throw null exception");
914        } catch (NullPointerException e) {
915        }
916        try {
917            new FileHandler("");
918            fail("should throw IllegalArgumentException");
919        } catch (IllegalArgumentException e) {
920            // expected
921        }
922        try {
923            new FileHandler("%t/java%u", 0, 0);
924            fail("should throw IllegalArgumentException");
925        } catch (IllegalArgumentException e) {
926        }
927        try {
928            new FileHandler("%t/java%u", -1, 1);
929            fail("should throw IllegalArgumentException");
930        } catch (IllegalArgumentException e) {
931        }
932
933        try {
934            new FileHandler("%t/java%u", -1, -1);
935            fail("should throw IllegalArgumentException");
936        } catch (IllegalArgumentException e) {
937        }
938    }
939
940    /*
941     * test for method public void publish(LogRecord record)
942     */
943    @TestInfo(
944      level = TestLevel.COMPLETE,
945      purpose = "",
946      targets = {
947        @TestTarget(
948          methodName = "publish",
949          methodArgs = {java.util.logging.LogRecord.class}
950        )
951    })
952    public void testPublish() throws Exception {
953        LogRecord[] r = new LogRecord[] { new LogRecord(Level.CONFIG, "msg__"),
954                new LogRecord(Level.WARNING, "message"),
955                new LogRecord(Level.INFO, "message for"),
956                new LogRecord(Level.FINE, "message for test") };
957        for (int i = 0; i < r.length; i++) {
958            handler = new FileHandler("%t/log/stringPublish");
959            handler.publish(r[i]);
960            handler.close();
961            assertFileContent(TEMPPATH + SEP + "log", "stringPublish",
962                    new LogRecord[] { r[i] }, handler.getFormatter());
963        }
964    }
965
966    /*
967     * test for method public void close()
968     */
969    @TestInfo(
970      level = TestLevel.COMPLETE,
971      purpose = "",
972      targets = {
973        @TestTarget(
974          methodName = "close",
975          methodArgs = {}
976        )
977    })
978    public void testClose() throws Exception {
979        FileHandler h = new FileHandler("%t/log/stringPublish");
980        h.publish(r);
981        h.close();
982        assertFileContent(TEMPPATH + SEP + "log", "stringPublish", h
983                .getFormatter());
984    }
985    @TestInfo(
986          level = TestLevel.PARTIAL,
987          purpose = "Doesn't verify SecurityException.",
988          targets = {
989            @TestTarget(
990              methodName = "setOutputStream",
991              methodArgs = {java.io.OutputStream.class}
992            )
993        })
994    // set output stream still works, just like super StreamHandler
995    public void testSetOutputStream() throws Exception {
996        MockFileHandler handler = new MockFileHandler("%h/setoutput.log");
997        handler.setFormatter(new MockFormatter());
998        handler.publish(r);
999
1000        ByteArrayOutputStream out = new ByteArrayOutputStream();
1001        handler.publicSetOutputStream(out);
1002        handler.publish(r);
1003        handler.close();
1004        String msg = new String(out.toByteArray());
1005        Formatter f = handler.getFormatter();
1006        assertEquals(msg, f.getHead(handler) + f.format(r) + f.getTail(handler));
1007        assertFileContent(HOMEPATH, "setoutput.log", handler.getFormatter());
1008    }
1009
1010    @TestInfo(
1011      level = TestLevel.PARTIAL,
1012      purpose = "Verifies IllegalArgumentException.",
1013      targets = {
1014        @TestTarget(
1015          methodName = "FileHandler",
1016          methodArgs = {java.lang.String.class, int.class, int.class}
1017        )
1018    })
1019    public void testEmptyPattern_3params() throws SecurityException,
1020            IOException {
1021        try {
1022            new FileHandler(new String(), 1, 1);
1023            fail("Expected an IllegalArgumentException");
1024        } catch (IllegalArgumentException e) {
1025            // Expected
1026        }
1027    }
1028    @TestInfo(
1029      level = TestLevel.PARTIAL,
1030      purpose = "Verifies IllegalArgumentException.",
1031      targets = {
1032        @TestTarget(
1033          methodName = "FileHandler",
1034          methodArgs = {java.lang.String.class, boolean.class}
1035        )
1036    })
1037    public void testEmptyPattern_2params() throws SecurityException,
1038            IOException {
1039        try {
1040            new FileHandler(new String(), true);
1041            fail("Expected an IllegalArgumentException");
1042        } catch (IllegalArgumentException e) {
1043            // Expected
1044        }
1045    }
1046    @TestInfo(
1047      level = TestLevel.PARTIAL,
1048      purpose = "Verifies IllegalArgumentException.",
1049      targets = {
1050        @TestTarget(
1051          methodName = "FileHandler",
1052          methodArgs = {java.lang.String.class, int.class, int.class, boolean.class}
1053        )
1054    })
1055    public void testEmptyPattern_4params() throws SecurityException,
1056            IOException {
1057        try {
1058            new FileHandler(new String(), 1, 1, true);
1059            fail("Expected an IllegalArgumentException");
1060        } catch (IllegalArgumentException e) {
1061            // Expected
1062        }
1063    }
1064
1065    /*
1066     * mock classes
1067     */
1068    public static class MockFilter implements Filter {
1069        public boolean isLoggable(LogRecord record) {
1070            return !record.getMessage().equals("false");
1071        }
1072    }
1073
1074    public static class MockFormatter extends Formatter {
1075        public String format(LogRecord r) {
1076            if (null == r) {
1077                return "";
1078            }
1079            return r.getMessage() + " by MockFormatter\n";
1080        }
1081
1082        public String getTail(Handler h) {
1083            return "tail\n";
1084        }
1085
1086        public String getHead(Handler h) {
1087            return "head\n";
1088        }
1089    }
1090
1091    public static class MockLogSecurityManager extends SecurityManager {
1092        public void checkPermission(Permission perm) {
1093            if (perm instanceof LoggingPermission) {
1094                throw new SecurityException();
1095            }
1096            return;
1097        }
1098    }
1099
1100    public static class MockFileSecurityManager extends SecurityManager {
1101        public void checkPermission(Permission perm) {
1102            if (perm instanceof FilePermission) {
1103                throw new SecurityException();
1104            }
1105        }
1106    }
1107
1108    public static class MockFileHandler extends FileHandler {
1109        public MockFileHandler() throws IOException {
1110            super();
1111        }
1112
1113        public MockFileHandler(String pattern) throws IOException {
1114            super(pattern);
1115        }
1116
1117        public void publicSetOutputStream(OutputStream stream) {
1118            super.setOutputStream(stream);
1119        }
1120    }
1121}
1122