1 /* 2 * Copyright (c) 2016, 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 */ 23 24 #include "precompiled.hpp" 25 #include "logging/logDecorations.hpp" 26 #include "logging/logTagSet.hpp" 27 #include "runtime/os.hpp" 28 #include "unittest.hpp" 29 #include "utilities/globalDefinitions.hpp" 30 31 static const LogTagSet& tagset = LogTagSetMapping<LOG_TAGS(logging, safepoint)>::tagset(); 32 static const LogDecorators default_decorators; 33 34 TEST_VM(LogDecorations, level) { 35 for (uint l = LogLevel::First; l <= LogLevel::Last; l++) { 36 LogLevelType level = static_cast<LogLevelType>(l); 37 // Create a decorations object for the current level 38 LogDecorations decorations(level, tagset, default_decorators); 39 // Verify that the level decoration matches the specified level 40 EXPECT_STREQ(LogLevel::name(level), decorations.decoration(LogDecorators::level_decorator)); 41 42 // Test changing level after object creation time 43 LogLevelType other_level; 44 if (l != LogLevel::Last) { 45 other_level = static_cast<LogLevelType>(l + 1); 46 } else { 47 other_level = static_cast<LogLevelType>(LogLevel::First); 48 } 49 decorations.set_level(other_level); 50 EXPECT_STREQ(LogLevel::name(other_level), decorations.decoration(LogDecorators::level_decorator)) 51 << "Decoration reports incorrect value after changing the level"; 52 } 53 } 54 55 TEST_VM(LogDecorations, uptime) { 56 // Verify the format of the decoration 57 int a, b; 58 char decimal_point; 59 LogDecorations decorations(LogLevel::Info, tagset, default_decorators); 60 const char* uptime = decorations.decoration(LogDecorators::uptime_decorator); 61 int read = sscanf(uptime, "%d%c%ds", &a, &decimal_point, &b); 62 EXPECT_EQ(3, read) << "Invalid uptime decoration: " << uptime; 63 EXPECT_TRUE(decimal_point == '.' || decimal_point == ',') << "Invalid uptime decoration: " << uptime; 64 65 // Verify that uptime increases 66 double prev = 0; 67 for (int i = 0; i < 3; i++) { 68 os::naked_short_sleep(10); 69 LogDecorations d(LogLevel::Info, tagset, default_decorators); 70 double cur = strtod(d.decoration(LogDecorators::uptime_decorator), NULL); 71 ASSERT_LT(prev, cur); 72 prev = cur; 73 } 74 } 75 76 TEST_VM(LogDecorations, tags) { 77 char expected_tags[1 * K]; 78 tagset.label(expected_tags, sizeof(expected_tags)); 79 // Verify that the expected tags are included in the tags decoration 80 LogDecorations decorations(LogLevel::Info, tagset, default_decorators); 81 EXPECT_STREQ(expected_tags, decorations.decoration(LogDecorators::tags_decorator)); 82 } 83 84 // Test each variation of the different timestamp decorations (ms, ns, uptime ms, uptime ns) 85 TEST_VM(LogDecorations, timestamps) { 86 struct { 87 const LogDecorators::Decorator decorator; 88 const char* suffix; 89 } test_decorator[] = { 90 { LogDecorators::timemillis_decorator, "ms" }, 91 { LogDecorators::uptimemillis_decorator, "ms" }, 92 { LogDecorators::timenanos_decorator, "ns" }, 93 { LogDecorators::uptimenanos_decorator, "ns" } 94 }; 95 96 for (uint i = 0; i < ARRAY_SIZE(test_decorator); i++) { 97 LogDecorators::Decorator decorator = test_decorator[i].decorator; 98 LogDecorators decorator_selection; 99 ASSERT_TRUE(decorator_selection.parse(LogDecorators::name(decorator))); 100 101 // Create decorations with the decorator we want to test included 102 LogDecorations decorations(LogLevel::Info, tagset, decorator_selection); 103 const char* decoration = decorations.decoration(decorator); 104 105 // Verify format of timestamp 106 const char* suffix; 107 for (suffix = decoration; isdigit(*suffix); suffix++) { 108 // Skip over digits 109 } 110 EXPECT_STREQ(test_decorator[i].suffix, suffix); 111 112 // Verify timestamp values 113 julong prev = 0; 114 for (int i = 0; i < 3; i++) { 115 os::naked_short_sleep(5); 116 LogDecorations d(LogLevel::Info, tagset, decorator_selection); 117 julong val = strtoull(d.decoration(decorator), NULL, 10); 118 ASSERT_LT(prev, val); 119 prev = val; 120 } 121 } 122 } 123 124 // Test the time decoration 125 TEST(LogDecorations, iso8601_time) { 126 LogDecorators decorator_selection; 127 ASSERT_TRUE(decorator_selection.parse("time")); 128 LogDecorations decorations(LogLevel::Info, tagset, decorator_selection); 129 130 const char *timestr = decorations.decoration(LogDecorators::time_decorator); 131 time_t expected_ts = time(NULL); 132 133 // Verify format 134 int y, M, d, h, m; 135 double s; 136 int read = sscanf(timestr, "%d-%d-%dT%d:%d:%lf", &y, &M, &d, &h, &m, &s); 137 ASSERT_EQ(6, read) << "Invalid format: " << timestr; 138 139 // Verify reported time & date 140 struct tm reported_time = {0}; 141 reported_time.tm_year = y - 1900; 142 reported_time.tm_mon = M - 1; 143 reported_time.tm_mday = d; 144 reported_time.tm_hour = h; 145 reported_time.tm_min = m; 146 reported_time.tm_sec = s; 147 reported_time.tm_isdst = -1; // let mktime deduce DST settings 148 time_t reported_ts = mktime(&reported_time); 149 expected_ts = mktime(localtime(&expected_ts)); 150 time_t diff = reported_ts - expected_ts; 151 if (diff < 0) { 152 diff = -diff; 153 } 154 // Allow up to 10 seconds in difference 155 ASSERT_LE(diff, 10) << "Reported time: " << reported_ts << " (" << timestr << ")" 156 << ", expected time: " << expected_ts; 157 } 158 159 // Test the utctime decoration 160 TEST(LogDecorations, iso8601_utctime) { 161 LogDecorators decorator_selection; 162 ASSERT_TRUE(decorator_selection.parse("utctime")); 163 LogDecorations decorations(LogLevel::Info, tagset, decorator_selection); 164 165 const char *timestr = decorations.decoration(LogDecorators::utctime_decorator); 166 time_t expected_ts = time(NULL); 167 168 // Verify format 169 char trailing_character; 170 int y, M, d, h, m, offset; 171 double s; 172 int read = sscanf(timestr, "%d-%d-%dT%d:%d:%lf%c%d", &y, &M, &d, &h, &m, &s, &trailing_character, &offset); 173 ASSERT_GT(read, 7) << "Invalid format: " << timestr; 174 175 // Ensure time is UTC (no offset) 176 if (trailing_character == '+') { 177 ASSERT_EQ(0, offset) << "Invalid offset: " << timestr; 178 } else { 179 ASSERT_EQ('Z', trailing_character) << "Invalid offset: " << timestr; 180 } 181 182 struct tm reported_time = {0}; 183 reported_time.tm_year = y - 1900; 184 reported_time.tm_mon = M - 1; 185 reported_time.tm_mday = d; 186 reported_time.tm_hour = h; 187 reported_time.tm_min = m; 188 reported_time.tm_sec = s; 189 reported_time.tm_isdst = 0; // No DST for UTC timestamps 190 time_t reported_ts = mktime(&reported_time); 191 expected_ts = mktime(gmtime(&expected_ts)); 192 time_t diff = reported_ts - expected_ts; 193 if (diff < 0) { 194 diff = -diff; 195 } 196 // Allow up to 10 seconds in difference 197 ASSERT_LE(diff, 10) << "Reported time: " << reported_ts << " (" << timestr << ")" 198 << ", expected time: " << expected_ts; 199 } 200 201 // Test the pid and tid decorations 202 TEST(LogDecorations, identifiers) { 203 LogDecorators decorator_selection; 204 ASSERT_TRUE(decorator_selection.parse("pid,tid")); 205 LogDecorations decorations(LogLevel::Info, tagset, decorator_selection); 206 207 struct { 208 intx expected; 209 LogDecorators::Decorator decorator; 210 } ids[] = { 211 { os::current_process_id(), LogDecorators::pid_decorator }, 212 { os::current_thread_id(), LogDecorators::tid_decorator }, 213 }; 214 215 for (uint i = 0; i < ARRAY_SIZE(ids); i++) { 216 const char* reported = decorations.decoration(ids[i].decorator); 217 218 // Verify format 219 const char* str; 220 for (str = reported; isdigit(*str); str++) { 221 // Skip over digits 222 } 223 EXPECT_EQ('\0', *str) << "Should only contain digits"; 224 225 // Verify value 226 EXPECT_EQ(ids[i].expected, strtol(reported, NULL, 10)); 227 } 228 }