1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23import java.io.ByteArrayInputStream;
24import java.io.ByteArrayOutputStream;
25import java.io.IOException;
26import java.io.ObjectInputStream;
27import java.io.ObjectOutputStream;
28import java.util.logging.Level;
29import java.util.logging.LogRecord;
30import java.util.logging.SimpleFormatter;
31
32/**
33 * @test
34 * @bug 8072645
35 * @summary tests that LogRecord has nanos...
36 * @run main LogRecordWithNanos
37 * @author danielfuchs
38 */
39public class LogRecordWithNanos {
40
41    static final int MILLIS_IN_SECOND = 1000;
42    static final int NANOS_IN_MILLI = 1000_000;
43    static final int NANOS_IN_SECOND = 1000_000_000;
44
45    static final boolean verbose = false;
46
47    static final class TestAssertException extends RuntimeException {
48        TestAssertException(String msg) { super(msg); }
49    }
50
51    private static void assertEquals(long expected, long received, String msg) {
52        if (expected != received) {
53            throw new TestAssertException("Unexpected result for " + msg
54                    + ".\n\texpected: " + expected
55                    +  "\n\tactual:   " + received);
56        } else if (verbose) {
57            System.out.println("Got expected " + msg + ": " + received);
58        }
59    }
60
61    /**
62     * Serializes a log record, then deserializes it and check that both
63     * records match.
64     * @param record the log record to serialize & deserialize.
65     * @throws IOException Unexpected.
66     * @throws ClassNotFoundException  Unexpected.
67     */
68    public static void test(LogRecord record)
69            throws IOException, ClassNotFoundException {
70
71        // Format the given logRecord using the SimpleFormatter
72        SimpleFormatter formatter = new SimpleFormatter();
73        String str = formatter.format(record);
74
75        // Serialize the given LogRecord
76        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
77        final ObjectOutputStream oos = new ObjectOutputStream(baos);
78        oos.writeObject(record);
79        oos.flush();
80        oos.close();
81
82        // First checks that the log record can be deserialized
83        final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
84        final ObjectInputStream ois = new ObjectInputStream(bais);
85        final LogRecord record2 = (LogRecord)ois.readObject();
86
87        assertEquals(record.getMillis(), record2.getMillis(), "getMillis()");
88        assertEquals(record.getInstant().getEpochSecond(),
89                record2.getInstant().getEpochSecond(),
90                "getInstant().getEpochSecond()");
91        assertEquals(record.getInstant().getNano(),
92                record2.getInstant().getNano(),
93                "getInstant().getNano()");
94        assertEquals(record.getInstant().toEpochMilli(),
95                record2.getInstant().toEpochMilli(),
96                "getInstant().toEpochMilli()");
97        assertEquals(record.getMillis(),
98                record.getInstant().toEpochMilli(),
99                "getMillis()/getInstant().toEpochMilli()");
100        assertEquals(record2.getMillis(),
101                record2.getInstant().toEpochMilli(),
102                "getMillis()/getInstant().toEpochMilli()");
103        assertEquals((record.getMillis()%MILLIS_IN_SECOND)*NANOS_IN_MILLI
104                + (record.getInstant().getNano() % NANOS_IN_MILLI),
105                record.getInstant().getNano(),
106                "record.getMillis()%1000)*1000_000"
107                + " + record.getInstant().getNano()%1000_000 / getInstant().getNano()");
108        assertEquals((record2.getMillis()%MILLIS_IN_SECOND)*NANOS_IN_MILLI
109                + (record2.getInstant().getNano() % NANOS_IN_MILLI),
110                record2.getInstant().getNano(),
111                "record2.getMillis()%1000)*1000_000"
112                + " + record2.getInstant().getNano()%1000_000 / getInstant().getNano()");
113
114        // Format the deserialized LogRecord using the SimpleFormatter, and
115        // check that the string representation obtained matches the string
116        // representation of the original LogRecord
117        String str2 = formatter.format(record2);
118        if (!str.equals(str2))
119            throw new RuntimeException("Unexpected values in deserialized object:"
120                + "\n\tExpected:  " + str
121                + "\n\tRetrieved: "+str);
122
123    }
124
125
126    public static void main(String[] args) throws Exception {
127        int count=0;
128        for (int i=0; i<1000; i++) {
129            LogRecord record = new LogRecord(Level.INFO, "Java Version: {0}");
130            record.setLoggerName("test");
131            record.setParameters(new Object[] {System.getProperty("java.version")});
132            if (record.getInstant().getNano() % 1000_000 != 0) {
133                count++;
134            }
135            test(record);
136        }
137        if (count == 0) {
138            throw new RuntimeException("Expected at least one record to have nanos");
139        }
140        System.out.println(count + "/1000 records had nano adjustment.");
141    }
142
143}
144