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 libcore.java.util.logging;
19
20import java.io.BufferedReader;
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.File;
24import java.io.FileReader;
25import java.io.IOException;
26import java.io.InputStream;
27import java.io.Reader;
28import java.util.Properties;
29import java.util.logging.FileHandler;
30import java.util.logging.Filter;
31import java.util.logging.Formatter;
32import java.util.logging.Handler;
33import java.util.logging.Level;
34import java.util.logging.LogManager;
35import java.util.logging.LogRecord;
36import junit.framework.AssertionFailedError;
37import junit.framework.TestCase;
38
39public class OldFileHandlerTest extends TestCase {
40
41    static LogManager manager = LogManager.getLogManager();
42    final static Properties props = new Properties();
43    final static String className = OldFileHandlerTest.class.getName();
44    final static String SEP = File.separator;
45    String HOMEPATH;
46    String TEMPPATH;
47    FileHandler handler;
48    LogRecord r;
49
50    protected void setUp() throws Exception {
51        super.setUp();
52        manager.reset();
53
54        //initProp
55        props.clear();
56        props.put("java.util.logging.FileHandler.level", "FINE");
57        props.put("java.util.logging.FileHandler.filter", className
58                + "$MockFilter");
59        props.put("java.util.logging.FileHandler.formatter", className
60                + "$MockFormatter");
61        props.put("java.util.logging.FileHandler.encoding", "iso-8859-1");
62        // limit to only two message
63        props.put("java.util.logging.FileHandler.limit", "1000");
64        // rotation count is 2
65        props.put("java.util.logging.FileHandler.count", "2");
66        // using append mode
67        props.put("java.util.logging.FileHandler.append", "true");
68        props.put("java.util.logging.FileHandler.pattern",
69                        "%t/log/java%u.test");
70
71        HOMEPATH = System.getProperty("user.home");
72        TEMPPATH = System.getProperty("java.io.tmpdir");
73
74        File file = new File(TEMPPATH + SEP + "log");
75        file.mkdir();
76        manager.readConfiguration(propertiesToInputStream(props));
77        handler = new FileHandler();
78        r = new LogRecord(Level.CONFIG, "msg");
79    }
80
81    protected void tearDown() throws Exception {
82        if (null != handler) {
83            handler.close();
84        }
85        reset(TEMPPATH + SEP + "log", "");
86        super.tearDown();
87    }
88
89    public static InputStream propertiesToInputStream(Properties p) throws IOException {
90        ByteArrayOutputStream bos = new ByteArrayOutputStream();
91        p.store(bos, "");
92        return new ByteArrayInputStream(bos.toByteArray());
93    }
94
95    public void testFileHandler() throws Exception {
96        assertEquals("character encoding is non equal to actual value",
97                "iso-8859-1", handler.getEncoding());
98        assertNotNull("Filter is null", handler.getFilter());
99        assertNotNull("Formatter is null", handler.getFormatter());
100        assertEquals("is non equal to actual value", Level.FINE, handler
101                .getLevel());
102        assertNotNull("ErrorManager is null", handler.getErrorManager());
103        handler.publish(r);
104        handler.close();
105        // output 3 times, and all records left
106        // append mode is true
107        for (int i = 0; i < 3; i++) {
108            handler = new FileHandler();
109            handler.publish(r);
110            handler.close();
111        }
112        assertFileContent(TEMPPATH + SEP + "log", "java0.test.0",
113                new LogRecord[] { r, null, r, null, r, null, r },
114                new MockFormatter());
115    }
116
117    public void testFileHandler_1params() throws Exception {
118
119        handler = new FileHandler("%t/log/string");
120        assertEquals("character encoding is non equal to actual value",
121                "iso-8859-1", handler.getEncoding());
122        assertNotNull("Filter is null", handler.getFilter());
123        assertNotNull("Formatter is null", handler.getFormatter());
124        assertEquals("is non equal to actual value", Level.FINE, handler
125                .getLevel());
126        assertNotNull("ErrorManager is null", handler.getErrorManager());
127        handler.publish(r);
128        handler.close();
129
130        // output 3 times, and all records left
131        // append mode is true
132        for (int i = 0; i < 3; i++) {
133            handler = new FileHandler("%t/log/string");
134            handler.publish(r);
135            handler.close();
136        }
137        assertFileContent(TEMPPATH + SEP + "log", "/string", new LogRecord[] {
138                r, null, r, null, r, null, r }, new MockFormatter());
139
140        // test if unique ids not specified, it will append at the end
141        // no generation number is used
142        FileHandler h = new FileHandler("%t/log/string");
143        FileHandler h2 = new FileHandler("%t/log/string");
144        FileHandler h3 = new FileHandler("%t/log/string");
145        FileHandler h4 = new FileHandler("%t/log/string");
146        h.publish(r);
147        h2.publish(r);
148        h3.publish(r);
149        h4.publish(r);
150        h.close();
151        h2.close();
152        h3.close();
153        h4.close();
154        assertFileContent(TEMPPATH + SEP + "log", "string", h.getFormatter());
155        assertFileContent(TEMPPATH + SEP + "log", "string.1", h.getFormatter());
156        assertFileContent(TEMPPATH + SEP + "log", "string.2", h.getFormatter());
157        assertFileContent(TEMPPATH + SEP + "log", "string.3", h.getFormatter());
158
159        // default is append mode
160        FileHandler h6 = new FileHandler("%t/log/string%u.log");
161        h6.publish(r);
162        h6.close();
163        FileHandler h7 = new FileHandler("%t/log/string%u.log");
164        h7.publish(r);
165        h7.close();
166        boolean assertionPassed = false;
167        try {
168            assertFileContent(TEMPPATH + SEP + "log", "string0.log", h.getFormatter());
169            assertionPassed = true;
170        } catch (AssertionFailedError e) {
171            // Assertion failed as expected.
172        }
173        if (assertionPassed) {
174            fail("assertion should have failed");
175        }
176        File file = new File(TEMPPATH + SEP + "log");
177        assertTrue("length list of file is incorrect", file.list().length <= 2);
178
179        // test unique ids
180        FileHandler h8 = new FileHandler("%t/log/%ustring%u.log");
181        h8.publish(r);
182        FileHandler h9 = new FileHandler("%t/log/%ustring%u.log");
183        h9.publish(r);
184        h9.close();
185        h8.close();
186        assertFileContent(TEMPPATH + SEP + "log", "0string0.log", h
187                .getFormatter());
188        assertFileContent(TEMPPATH + SEP + "log", "1string1.log", h
189                .getFormatter());
190        file = new File(TEMPPATH + SEP + "log");
191        assertTrue("length list of file is incorrect", file.list().length <= 2);
192
193        try {
194            new FileHandler("");
195            fail("IllegalArgumentException expected");
196        } catch (IllegalArgumentException e) {
197            //expected
198        }
199    }
200
201    public void testFileHandler_2params() throws Exception {
202        boolean append = false;
203        do {
204            append = !append;
205            handler = new FileHandler("%t/log/string", append);
206            assertEquals("character encoding is non equal to actual value",
207                    "iso-8859-1", handler.getEncoding());
208            assertNotNull("Filter is null", handler.getFilter());
209            assertNotNull("Formatter is null", handler.getFormatter());
210            assertEquals("is non equal to actual value", Level.FINE, handler
211                    .getLevel());
212            assertNotNull("ErrorManager is null", handler.getErrorManager());
213            handler.publish(r);
214            handler.close();
215            // output 3 times, and all records left
216            // append mode is true
217            for (int i = 0; i < 3; i++) {
218                handler = new FileHandler("%t/log/string", append);
219                handler.publish(r);
220                handler.close();
221            }
222            if (append) {
223                assertFileContent(TEMPPATH + SEP + "log", "/string",
224                        new LogRecord[] { r, null, r, null, r, null, r },
225                        new MockFormatter());
226            } else {
227                assertFileContent(TEMPPATH + SEP + "log", "/string",
228                        new LogRecord[] { r }, new MockFormatter());
229            }
230        } while (append);
231
232        try {
233            new FileHandler("", true);
234            fail("IllegalArgumentException expected");
235        } catch (IllegalArgumentException e) {
236            //expected
237        }
238    }
239
240    public void testFileHandler_3params() throws Exception {
241        int limit = 120;
242        int count = 1;
243        handler = new FileHandler("%t/log/string", limit, count);
244        assertEquals("character encoding is non equal to actual value",
245                "iso-8859-1", handler.getEncoding());
246        assertNotNull("Filter is null", handler.getFilter());
247        assertNotNull("Formatter is null", handler.getFormatter());
248        assertEquals("is non equal to actual value", Level.FINE, handler
249                .getLevel());
250        assertNotNull("ErrorManager is null", handler.getErrorManager());
251        handler.publish(r);
252        handler.close();
253        // output 3 times, and all records left
254        // append mode is true
255        for (int i = 0; i < 3; i++) {
256            handler = new FileHandler("%t/log/string", limit, count);
257            handler.publish(r);
258            handler.close();
259        }
260        assertFileContent(TEMPPATH + SEP + "log", "/string", new LogRecord[] {
261                r, null, r, null, r, null, r }, new MockFormatter());
262
263        try {
264            new FileHandler("", limit, count);
265            fail("IllegalArgumentException expected");
266        } catch (IllegalArgumentException e) {
267            //expected
268        }
269
270        try {
271            new FileHandler("%t/log/string", -1, count);
272            fail("IllegalArgumentException expected");
273        } catch (IllegalArgumentException e) {
274            //expected
275        }
276
277        try {
278            new FileHandler("%t/log/string", limit, 0);
279            fail("IllegalArgumentException expected");
280        } catch (IllegalArgumentException e) {
281            //expected
282        }
283    }
284
285    public void testFileHandler_4params() throws Exception {
286        int limit = 120;
287        int count = 1;
288        boolean append = false;
289        do {
290            append = !append;
291            handler = new FileHandler("%t/log/string", limit, count, append);
292            assertEquals("character encoding is non equal to actual value",
293                    "iso-8859-1", handler.getEncoding());
294            assertNotNull("Filter is null", handler.getFilter());
295            assertNotNull("Formatter is null", handler.getFormatter());
296            assertEquals("is non equal to actual value", Level.FINE, handler
297                    .getLevel());
298            assertNotNull("ErrorManager is null", handler.getErrorManager());
299            handler.publish(r);
300            handler.close();
301            // output 3 times, and all records left
302            // append mode is true
303            for (int i = 0; i < 3; i++) {
304                handler = new FileHandler("%t/log/string", limit, count, append);
305                handler.publish(r);
306                handler.close();
307            }
308            if (append) {
309                assertFileContent(TEMPPATH + SEP + "log", "/string",
310                        new LogRecord[] { r, null, r, null, r, null, r },
311                        new MockFormatter());
312            } else {
313                assertFileContent(TEMPPATH + SEP + "log", "/string",
314                        new LogRecord[] { r }, new MockFormatter());
315            }
316        } while (append);
317
318        try {
319            new FileHandler("", limit, count, true);
320            fail("IllegalArgumentException expected");
321        } catch (IllegalArgumentException e) {
322            //expected
323        }
324
325        try {
326            new FileHandler("%t/log/string", -1, count, false);
327            fail("IllegalArgumentException expected");
328        } catch (IllegalArgumentException e) {
329            //expected
330        }
331
332        try {
333            new FileHandler("%t/log/string", limit, 0, true);
334            fail("IllegalArgumentException expected");
335        } catch (IllegalArgumentException e) {
336            //expected
337        }
338    }
339
340    private void assertFileContent(String homepath, String filename,
341            Formatter formatter) throws Exception {
342        assertFileContent(homepath, filename, new LogRecord[] { r }, formatter);
343    }
344
345    private void assertFileContent(String homepath, String filename,
346            LogRecord[] lr, Formatter formatter) throws Exception {
347        handler.close();
348        String msg = "";
349        // if formatter is null, the file content should be empty
350        // else the message should be formatted given records
351        if (null != formatter) {
352            StringBuffer sb = new StringBuffer();
353            sb.append(formatter.getHead(handler));
354            for (int i = 0; i < lr.length; i++) {
355                if (null == lr[i] && i < lr.length - 1) {
356                    // if one record is null and is not the last record, means
357                    // here is
358                    // output completion point, should output tail, then output
359                    // head
360                    // (ready for next output)
361                    sb.append(formatter.getTail(handler));
362                    sb.append(formatter.getHead(handler));
363                } else {
364                    sb.append(formatter.format(lr[i]));
365                }
366            }
367            sb.append(formatter.getTail(handler));
368            msg = sb.toString();
369        }
370        char[] chars = new char[msg.length()];
371        Reader reader = null;
372        try {
373            reader = new BufferedReader(new FileReader(homepath + SEP
374                    + filename));
375            reader.read(chars);
376            assertEquals(msg, new String(chars));
377            // assert has reached the end of the file
378            assertEquals(-1, reader.read());
379        } finally {
380            try {
381                if (reader != null) {
382                    reader.close();
383                }
384            } catch (Exception e) {
385                // don't care
386            }
387            reset(homepath, filename);
388        }
389    }
390
391    /**
392     * Does a cleanup of given file
393     */
394    private void reset(String homepath, String filename) {
395        File file;
396        try {
397            file = new File(homepath + SEP + filename);
398            if (file.isFile()) {
399                file.delete();
400            } else if (file.isDirectory()) {
401                File[] files = file.listFiles();
402                for (int i = 0; i < files.length; i++) {
403                    files[i].delete();
404                }
405                file.delete();
406            }
407        } catch (Exception e) {
408            e.printStackTrace();
409        }
410        try {
411            file = new File(homepath + SEP + filename + ".lck");
412            file.delete();
413        } catch (Exception e) {
414            e.printStackTrace();
415        }
416    }
417
418    // This test fails on RI. Doesn't parse special pattern \"%t/%h."
419    public void testInvalidParams() throws IOException {
420
421        // %t and %p parsing can add file separator automatically
422
423        // bad directory, IOException, append
424        try {
425            new FileHandler("%t/baddir/multi%g", true);
426            fail("should throw IO exception");
427        } catch (IOException e) {
428        }
429        File file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
430        assertFalse(file.exists());
431        try {
432            new FileHandler("%t/baddir/multi%g", false);
433            fail("should throw IO exception");
434        } catch (IOException e) {
435        }
436        file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
437        assertFalse(file.exists());
438
439        try {
440            new FileHandler("%t/baddir/multi%g", 12, 4);
441            fail("should throw IO exception");
442        } catch (IOException e) {
443        }
444        file = new File(TEMPPATH + SEP + "baddir" + SEP + "multi0");
445        assertFalse(file.exists());
446
447        try {
448            new FileHandler("%t/java%u", -1, -1);
449            fail("should throw IllegalArgumentException");
450        } catch (IllegalArgumentException e) {
451        }
452    }
453
454    public void testPublish() throws Exception {
455        LogRecord[] r = new LogRecord[] { new LogRecord(Level.CONFIG, "msg__"),
456                new LogRecord(Level.WARNING, "message"),
457                new LogRecord(Level.INFO, "message for"),
458                new LogRecord(Level.FINE, "message for test") };
459        for (int i = 0; i < r.length; i++) {
460            handler = new FileHandler("%t/log/stringPublish");
461            handler.publish(r[i]);
462            handler.close();
463            assertFileContent(TEMPPATH + SEP + "log", "stringPublish",
464                    new LogRecord[] { r[i] }, handler.getFormatter());
465        }
466    }
467
468    public void testClose() throws Exception {
469        FileHandler h = new FileHandler("%t/log/stringPublish");
470        h.publish(r);
471        h.close();
472        assertFileContent(TEMPPATH + SEP + "log", "stringPublish", h
473                .getFormatter());
474    }
475
476    /*
477     * mock classes
478     */
479    public static class MockFilter implements Filter {
480        public boolean isLoggable(LogRecord record) {
481            return !record.getMessage().equals("false");
482        }
483    }
484
485    public static class MockFormatter extends Formatter {
486        public String format(LogRecord r) {
487            if (null == r) {
488                return "";
489            }
490            return r.getMessage() + " by MockFormatter\n";
491        }
492
493        public String getTail(Handler h) {
494            return "tail\n";
495        }
496
497        public String getHead(Handler h) {
498            return "head\n";
499        }
500    }
501}
502