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 java.io.Serializable;
21import java.util.Locale;
22import java.util.ResourceBundle;
23import java.util.logging.Handler;
24import java.util.logging.Level;
25import java.util.logging.LogRecord;
26import java.util.logging.Logger;
27
28import junit.framework.TestCase;
29
30import org.apache.harmony.testframework.serialization.SerializationTest;
31import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
32
33public class LogRecordTest extends TestCase {
34
35    static final String MSG = "test msg, pls. ignore itb";
36
37    private LogRecord lr;
38
39    private static String className = LogRecordTest.class.getName();
40
41    protected void setUp() throws Exception {
42        super.setUp();
43        lr = new LogRecord(Level.CONFIG, MSG);
44
45    }
46
47    public void testLogRecordWithNullPointers() {
48        try {
49            new LogRecord(null, null);
50            fail("should throw NullPointerException");
51        } catch (NullPointerException e) {
52        }
53        try {
54            new LogRecord(null, MSG);
55            fail("should throw NullPointerException");
56        } catch (NullPointerException e) {
57        }
58        LogRecord r = new LogRecord(Level.WARNING, null);
59        assertSame(r.getLevel(), Level.WARNING);
60        assertNull(r.getMessage());
61    }
62
63    public void testGetSetLoggerName() {
64        assertNull(lr.getLoggerName());
65        lr.setLoggerName(null);
66        assertNull(lr.getLoggerName());
67        lr.setLoggerName("test logger name");
68        assertEquals("test logger name", lr.getLoggerName());
69    }
70
71    public void testGetSetResourceBundle() {
72        assertNull(lr.getResourceBundleName());
73        assertNull(lr.getResourceBundle());
74
75        lr.setResourceBundle(null);
76        assertNull(lr.getResourceBundle());
77
78        lr.setResourceBundleName("bundles/com/android/java/util/logging/res");
79        assertNull(lr.getResourceBundle());
80
81        lr.setResourceBundleName(null);
82        ResourceBundle rb = ResourceBundle
83                .getBundle("bundles/com/android/java/util/logging/res");
84        lr.setResourceBundle(rb);
85        assertEquals(rb, lr.getResourceBundle());
86        assertNull(lr.getResourceBundleName());
87    }
88
89    public void testGetSetResourceBundleName() {
90        assertNull(lr.getResourceBundleName());
91        lr.setResourceBundleName(null);
92        assertNull(lr.getResourceBundleName());
93        lr.setResourceBundleName("test");
94        assertEquals("test", lr.getResourceBundleName());
95    }
96
97    public void testGetSetLevel() {
98        try {
99            lr.setLevel(null);
100            fail("should throw NullPointerException");
101        } catch (NullPointerException e) {
102        }
103        assertSame(lr.getLevel(), Level.CONFIG);
104    }
105
106    public void testGetSetSequenceNumber() {
107        long l = lr.getSequenceNumber();
108        lr.setSequenceNumber(-111);
109        assertEquals(lr.getSequenceNumber(), -111L);
110        lr.setSequenceNumber(0);
111        assertEquals(lr.getSequenceNumber(), 0L);
112        lr = new LogRecord(Level.ALL, null);
113        assertEquals(lr.getSequenceNumber(), l + 1);
114    }
115
116    public void testGetSetSourceClassName() {
117        lr.setSourceClassName(null);
118        assertNull(lr.getSourceClassName());
119        lr.setSourceClassName("bad class name");
120        assertEquals("bad class name", lr.getSourceClassName());
121        lr.setSourceClassName(this.getClass().getName());
122        assertEquals(this.getClass().getName(), lr.getSourceClassName());
123    }
124
125    public void testGetSetSourceMethodName() {
126        lr.setSourceMethodName(null);
127        assertNull(lr.getSourceMethodName());
128        lr.setSourceMethodName("bad class name");
129        assertEquals("bad class name", lr.getSourceMethodName());
130        lr.setSourceMethodName(this.getClass().getName());
131        assertEquals(this.getClass().getName(), lr.getSourceMethodName());
132    }
133
134    public void testGetSourceDefaultValue() {
135        assertNull(lr.getSourceMethodName());
136        assertNull(lr.getSourceClassName());
137
138        // find class and method who called logger
139        Logger logger = Logger.global;
140        MockHandler handler = new MockHandler();
141        logger.addHandler(handler);
142        logger.log(Level.SEVERE, MSG);
143        assertEquals(this.getClass().getName(), handler.getSourceClassName());
144        assertEquals("testGetSourceDefaultValue", handler.getSourceMethodName());
145
146        // only set source method to null
147        lr = new LogRecord(Level.SEVERE, MSG);
148        lr.setSourceMethodName(null);
149        logger.log(lr);
150        assertNull(handler.getSourceClassName());
151        assertNull(handler.getSourceMethodName());
152
153        // only set source class to null
154        lr = new LogRecord(Level.SEVERE, MSG);
155        lr.setSourceClassName(null);
156        logger.log(lr);
157        assertNull(handler.getSourceClassName());
158        assertNull(handler.getSourceMethodName());
159
160        // set both
161        lr = new LogRecord(Level.SEVERE, MSG);
162        lr.setSourceClassName("className");
163        lr.setSourceMethodName(null);
164        logger.log(lr);
165        assertEquals("className", handler.getSourceClassName());
166        assertNull(handler.getSourceMethodName());
167
168        // test if LogRecord is constructed in another class, and is published
169        // by Logger
170        logger.log(RecordFactory.getDefaultRecord());
171        assertEquals(this.getClass().getName(), handler.getSourceClassName());
172        assertEquals("testGetSourceDefaultValue", handler.getSourceMethodName());
173
174        lr = RecordFactory.getDefaultRecord();
175        // assertNull(lr.getSourceClassName());
176        // assertNull(lr.getSourceMethodName());
177        RecordFactory.log(logger, lr);
178        assertEquals(RecordFactory.class.getName(), handler
179                .getSourceClassName());
180        assertEquals("log", handler.getSourceMethodName());
181
182        // only try once to get the default value
183        lr = RecordFactory.getDefaultRecord();
184        assertNull(lr.getSourceClassName());
185        assertNull(lr.getSourceMethodName());
186        RecordFactory.log(logger, lr);
187        assertNull(handler.getSourceClassName());
188        assertNull(handler.getSourceMethodName());
189
190        // it cannot find correct default value when logger is subclass
191        MockLogger ml = new MockLogger("foo", null);
192        ml.addHandler(handler);
193        ml.info(MSG);
194        assertEquals(className + "$MockLogger", handler.getSourceClassName());
195        assertEquals("info", handler.getSourceMethodName());
196
197        // it can find nothing when only call Subclass
198        ml = new MockLogger("foo", null);
199        ml.addHandler(handler);
200        ml.log(Level.SEVERE, MSG);
201        assertNull(handler.getSourceClassName());
202        assertNull(handler.getSourceMethodName());
203
204        // test if don't call logger, what is the default value
205        lr = new LogRecord(Level.SEVERE, MSG);
206        handler.publish(lr);
207        assertNull(handler.getSourceClassName());
208        assertNull(handler.getSourceMethodName());
209        logger.removeHandler(handler);
210    }
211
212    public void testGetSetMessage() {
213        assertEquals(MSG, lr.getMessage());
214        lr.setMessage(null);
215        assertNull(lr.getMessage());
216        lr.setMessage("");
217        assertEquals("", lr.getMessage());
218    }
219
220    public void testGetSetParameters() {
221        assertNull(lr.getParameters());
222        lr.setParameters(null);
223        assertNull(lr.getParameters());
224        Object[] oa = new Object[0];
225        lr.setParameters(oa);
226        assertEquals(oa, lr.getParameters());
227        oa = new Object[] { new Object(), new Object() };
228        lr.setParameters(oa);
229        assertSame(oa, lr.getParameters());
230    }
231
232    public void testGetSetMillis() {
233        long milli = lr.getMillis();
234        assertTrue(milli > 0);
235        lr.setMillis(-1);
236        assertEquals(-1, lr.getMillis());
237        lr.setMillis(0);
238        assertEquals(0, lr.getMillis());
239    }
240
241    public void testGetSetThreadID() {
242        // TODO how to test the different thread
243        int id = lr.getThreadID();
244        lr = new LogRecord(Level.ALL, "a1");
245        assertEquals(id, lr.getThreadID());
246        lr.setThreadID(id + 10);
247        assertEquals(id + 10, lr.getThreadID());
248        lr = new LogRecord(Level.ALL, "a1");
249        assertEquals(id, lr.getThreadID());
250    }
251
252    public void testGetSetThrown() {
253        assertNull(lr.getThrown());
254        lr.setThrown(null);
255        assertNull(lr.getThrown());
256        Throwable e = new Exception();
257        lr.setThrown(e);
258        assertEquals(e, lr.getThrown());
259    }
260
261    // comparator for LogRecord objects
262    private static final SerializableAssert LOGRECORD_COMPARATOR = new SerializableAssert() {
263        public void assertDeserialized(Serializable initial,
264                Serializable deserialized) {
265
266            LogRecord init = (LogRecord) initial;
267            LogRecord dser = (LogRecord) deserialized;
268
269            assertEquals("Class", init.getClass(), dser.getClass());
270            assertEquals("Level", init.getLevel(), dser.getLevel());
271            assertEquals("LoggerName", init.getLoggerName(), dser
272                    .getLoggerName());
273            assertEquals("Message", init.getMessage(), dser.getMessage());
274            assertEquals("Millis", init.getMillis(), dser.getMillis());
275
276            // compare parameters
277            Object[] paramInit = init.getParameters();
278            Object[] paramDser = dser.getParameters();
279            assertEquals("Parameters length", paramInit.length,
280                    paramDser.length);
281            for (int i = 0; i < paramInit.length; i++) {
282                assertEquals("Param: " + i, paramInit[i].toString(),
283                        paramDser[i]);
284            }
285
286            // don't check ResourceBundle object
287            // verify only bundle's name
288            assertEquals("ResourceBundleName", init.getResourceBundleName(),
289                    dser.getResourceBundleName());
290            assertEquals("SequenceNumber", init.getSequenceNumber(), dser
291                    .getSequenceNumber());
292            assertEquals("SourceClassName", init.getSourceClassName(), dser
293                    .getSourceClassName());
294            assertEquals("SourceMethodName", init.getSourceMethodName(), dser
295                    .getSourceMethodName());
296            assertEquals("ThreadID", init.getThreadID(), dser.getThreadID());
297
298            SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(init
299                    .getThrown(), dser.getThrown());
300        }
301    };
302
303    /**
304     * @tests serialization/deserialization compatibility.
305     */
306    public void testSerializationSelf() throws Exception {
307        LogRecord r = new LogRecord(Level.ALL, "msg");
308        r.setLoggerName("LoggerName");
309        r.setMillis(123456789);
310        r.setResourceBundleName("ResourceBundleName");
311        r.setSequenceNumber(987654321);
312        r.setSourceClassName("SourceClassName");
313        r.setSourceMethodName("SourceMethodName");
314        r
315                .setParameters(new Object[] { "test string",
316                        new Exception("ex-msg") });
317        r.setThreadID(3232);
318        r.setThrown(new Exception("ExceptionMessage"));
319
320        SerializationTest.verifySelf(r, LOGRECORD_COMPARATOR);
321    }
322
323    /**
324     * @tests resolution of resource bundle for serialization/deserialization.
325     */
326    public void testSerializationResourceBundle() throws Exception {
327
328        // test case: valid resource bundle name
329        lr.setResourceBundleName("bundles/com/android/java/util/logging/res2");
330        lr.setResourceBundle(ResourceBundle.getBundle(
331                "bundles/com/android/java/util/logging/res", Locale.US));
332
333        LogRecord result = (LogRecord) SerializationTest.copySerializable(lr);
334        assertNotNull(result.getResourceBundle());
335
336        // test case: invalid resource bundle name, it is not resolved during
337        // deserialization LogRecord object so check for returned null value
338        lr.setResourceBundleName("bad bundle name");
339        lr.setResourceBundle(ResourceBundle.getBundle(
340                "bundles/com/android/java/util/logging/res", Locale.US));
341
342        result = (LogRecord) SerializationTest.copySerializable(lr);
343        assertNull(result.getResourceBundle());
344    }
345
346    /**
347     * @tests serialization/deserialization compatibility with RI.
348     */
349    public void testSerializationCompatibility() throws Exception {
350        LogRecord r = new LogRecord(Level.ALL, "msg");
351        r.setLoggerName("LoggerName");
352        r.setMillis(123456789);
353        r.setResourceBundleName("ResourceBundleName");
354        r.setSequenceNumber(987654321);
355        r.setSourceClassName("SourceClassName");
356        r.setSourceMethodName("SourceMethodName");
357        r
358                .setParameters(new Object[] { "test string",
359                        new Exception("ex-msg") });
360        r.setThreadID(3232);
361        r.setThrown(new Exception("ExceptionMessage"));
362
363        SerializationTest.verifyGolden(this, r, LOGRECORD_COMPARATOR);
364    }
365
366    public static class MockHandler extends Handler {
367        private String className;
368
369        private String methodName;
370
371        public void close() {
372        }
373
374        public void flush() {
375        }
376
377        public void publish(LogRecord record) {
378            className = record.getSourceClassName();
379            methodName = record.getSourceMethodName();
380        }
381
382        public String getSourceMethodName() {
383            return methodName;
384        }
385
386        public String getSourceClassName() {
387            return className;
388        }
389    }
390
391    // mock class, try to test when the sourceclass and sourcemethod of
392    // LogRecord is initiated
393    public static class RecordFactory {
394
395        public static LogRecord getDefaultRecord() {
396            return new LogRecord(Level.SEVERE, MSG);
397        }
398
399        public static void log(Logger logger, LogRecord lr) {
400            logger.log(lr);
401        }
402    }
403
404    public static class MockLogger extends Logger {
405
406        /**
407         * @param name
408         * @param resourceBundleName
409         */
410        public MockLogger(String name, String resourceBundleName) {
411            super(name, resourceBundleName);
412        }
413
414        public void log(Level l, String s) {
415            this.log(new LogRecord(l, s));
416        }
417
418        public void info(String s) {
419            super.info(s);
420        }
421
422        public void log(LogRecord record) {
423            if (isLoggable(record.getLevel())) {
424                // call the handlers of this logger
425                // TODO: What if an exception occurred in handler?
426                Handler[] ha = this.getHandlers();
427                for (int i = 0; i < ha.length; i++) {
428                    ha[i].publish(record);
429                }
430                // call the parent's handlers if set useParentHandlers
431                if (getUseParentHandlers()) {
432                    Logger anyParent = this.getParent();
433                    while (null != anyParent) {
434                        ha = anyParent.getHandlers();
435                        for (int i = 0; i < ha.length; i++) {
436                            ha[i].publish(record);
437                        }
438                        if (anyParent.getUseParentHandlers()) {
439                            anyParent = anyParent.getParent();
440                        } else {
441                            break;
442                        }
443                    }
444                }
445            }
446        }
447    }
448}
449