Path: blob/master/test/hotspot/gtest/logging/test_logDecorations.cpp
41144 views
/*1* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "logging/logDecorations.hpp"25#include "logging/logTagSet.hpp"26#include "runtime/os.hpp"27#include "unittest.hpp"28#include "utilities/globalDefinitions.hpp"2930static const LogTagSet& tagset = LogTagSetMapping<LOG_TAGS(logging, safepoint)>::tagset();31static const LogDecorators default_decorators;3233TEST_VM(LogDecorations, level) {34char buf[LogDecorations::max_decoration_size + 1];35for (uint l = LogLevel::First; l <= LogLevel::Last; l++) {36LogLevelType level = static_cast<LogLevelType>(l);37// Create a decorations object for the current level38LogDecorations decorations(level, tagset, default_decorators);39// Verify that the level decoration matches the specified level40EXPECT_STREQ(LogLevel::name(level), decorations.decoration(LogDecorators::level_decorator, buf, sizeof(buf)));4142// Test changing level after object creation time43LogLevelType other_level;44if (l != LogLevel::Last) {45other_level = static_cast<LogLevelType>(l + 1);46} else {47other_level = static_cast<LogLevelType>(LogLevel::First);48}49decorations.set_level(other_level);50EXPECT_STREQ(LogLevel::name(other_level), decorations.decoration(LogDecorators::level_decorator, buf, sizeof(buf)))51<< "Decoration reports incorrect value after changing the level";52}53}5455TEST_VM(LogDecorations, uptime) {56char buf[LogDecorations::max_decoration_size + 1];57// Verify the format of the decoration58int a, b;59char decimal_point;60LogDecorations decorations(LogLevel::Info, tagset, default_decorators);61const char* uptime = decorations.decoration(LogDecorators::uptime_decorator, buf, sizeof(buf));62int read = sscanf(uptime, "%d%c%ds", &a, &decimal_point, &b);63EXPECT_EQ(3, read) << "Invalid uptime decoration: " << uptime;64EXPECT_TRUE(decimal_point == '.' || decimal_point == ',') << "Invalid uptime decoration: " << uptime;6566// Verify that uptime increases67double prev = 0;68for (int i = 0; i < 3; i++) {69os::naked_short_sleep(10);70LogDecorations d(LogLevel::Info, tagset, default_decorators);71double cur = strtod(d.decoration(LogDecorators::uptime_decorator, buf, sizeof(buf)), NULL);72ASSERT_LT(prev, cur);73prev = cur;74}75}7677TEST_VM(LogDecorations, tags) {78char buf[LogDecorations::max_decoration_size + 1];79char expected_tags[1 * K];80tagset.label(expected_tags, sizeof(expected_tags));81// Verify that the expected tags are included in the tags decoration82LogDecorations decorations(LogLevel::Info, tagset, default_decorators);83EXPECT_STREQ(expected_tags, decorations.decoration(LogDecorators::tags_decorator, buf, sizeof(buf)));84}8586// Test each variation of the different timestamp decorations (ms, ns, uptime ms, uptime ns)87TEST_VM(LogDecorations, timestamps) {88char buf[LogDecorations::max_decoration_size + 1];89struct {90const LogDecorators::Decorator decorator;91const char* suffix;92const char* desc;93} test_decorator[] = {94{ LogDecorators::timemillis_decorator, "ms", "timemillis" },95{ LogDecorators::uptimemillis_decorator, "ms", "uptimemillis" },96{ LogDecorators::timenanos_decorator, "ns", "timenanos" },97{ LogDecorators::uptimenanos_decorator, "ns", "uptimenanos" }98};99100for (uint i = 0; i < ARRAY_SIZE(test_decorator); i++) {101tty->print_cr("Processing Decorator %s", test_decorator[i].desc);102LogDecorators::Decorator decorator = test_decorator[i].decorator;103LogDecorators decorator_selection;104ASSERT_TRUE(decorator_selection.parse(LogDecorators::name(decorator)));105106// Create decorations with the decorator we want to test included107LogDecorations decorations(LogLevel::Info, tagset, decorator_selection);108const char* decoration = decorations.decoration(decorator, buf, sizeof(buf));109110// Verify format of timestamp111const char* suffix;112for (suffix = decoration; isdigit(*suffix); suffix++) {113// Skip over digits114}115EXPECT_STREQ(test_decorator[i].suffix, suffix);116117// Verify timestamp values118julong prev = 0;119for (int i = 0; i < 3; i++) {120// The sleep needs to be longer than the timer resolution to ensure121// we see updates to 'timemillis'. Windows has the lowest resolution122// at 15-16ms, so we use 20.123os::naked_short_sleep(20);124LogDecorations d(LogLevel::Info, tagset, decorator_selection);125julong val = strtoull(d.decoration(decorator, buf, sizeof(buf)), NULL, 10);126tty->print_cr("Read value: " UINT64_FORMAT, val);127ASSERT_LT(prev, val);128prev = val;129}130}131}132133// Test the time decoration134TEST(LogDecorations, iso8601_time) {135char buf[LogDecorations::max_decoration_size + 1];136LogDecorators decorator_selection;137ASSERT_TRUE(decorator_selection.parse("time"));138LogDecorations decorations(LogLevel::Info, tagset, decorator_selection);139140const char *timestr = decorations.decoration(LogDecorators::time_decorator, buf, sizeof(buf));141time_t expected_ts = time(NULL);142143// Verify format144int y, M, d, h, m, s, ms;145int read = sscanf(timestr, "%d-%d-%dT%d:%d:%d.%d", &y, &M, &d, &h, &m, &s, &ms);146ASSERT_EQ(7, read) << "Invalid format: " << timestr;147148// Verify reported time & date149struct tm reported_time = {0};150reported_time.tm_year = y - 1900;151reported_time.tm_mon = M - 1;152reported_time.tm_mday = d;153reported_time.tm_hour = h;154reported_time.tm_min = m;155reported_time.tm_sec = s;156reported_time.tm_isdst = -1; // let mktime deduce DST settings157time_t reported_ts = mktime(&reported_time);158expected_ts = mktime(localtime(&expected_ts));159time_t diff = reported_ts - expected_ts;160if (diff < 0) {161diff = -diff;162}163// Allow up to 10 seconds in difference164ASSERT_LE(diff, 10) << "Reported time: " << reported_ts << " (" << timestr << ")"165<< ", expected time: " << expected_ts;166}167168// Test the utctime decoration169TEST(LogDecorations, iso8601_utctime) {170char buf[LogDecorations::max_decoration_size + 1];171LogDecorators decorator_selection;172ASSERT_TRUE(decorator_selection.parse("utctime"));173LogDecorations decorations(LogLevel::Info, tagset, decorator_selection);174175const char *timestr = decorations.decoration(LogDecorators::utctime_decorator, buf, sizeof(buf));176time_t expected_ts = time(NULL);177178// Verify format179char trailing_character;180int y, M, d, h, m, s, ms, offset;181182int read = sscanf(timestr, "%d-%d-%dT%d:%d:%d.%d%c%d", &y, &M, &d, &h, &m, &s, &ms, &trailing_character, &offset);183184ASSERT_EQ(9, read) << "Invalid format: " << timestr;185186// Ensure time is UTC (no offset)187ASSERT_EQ('+', trailing_character) << "Invalid trailing character for UTC: "188<< trailing_character;189ASSERT_EQ(0, offset) << "Invalid offset: " << timestr;190191struct tm reported_time = {0};192reported_time.tm_year = y - 1900;193reported_time.tm_mon = M - 1;194reported_time.tm_mday = d;195reported_time.tm_hour = h;196reported_time.tm_min = m;197reported_time.tm_sec = s;198reported_time.tm_isdst = 0; // No DST for UTC timestamps199time_t reported_ts = mktime(&reported_time);200expected_ts = mktime(gmtime(&expected_ts));201time_t diff = reported_ts - expected_ts;202if (diff < 0) {203diff = -diff;204}205// Allow up to 10 seconds in difference206ASSERT_LE(diff, 10) << "Reported time: " << reported_ts << " (" << timestr << ")"207<< ", expected time: " << expected_ts;208}209210// Test the pid and tid decorations211TEST(LogDecorations, identifiers) {212char buf[LogDecorations::max_decoration_size + 1];213LogDecorators decorator_selection;214ASSERT_TRUE(decorator_selection.parse("pid,tid"));215LogDecorations decorations(LogLevel::Info, tagset, decorator_selection);216217struct {218intx expected;219LogDecorators::Decorator decorator;220} ids[] = {221{ os::current_process_id(), LogDecorators::pid_decorator },222{ os::current_thread_id(), LogDecorators::tid_decorator },223};224225for (uint i = 0; i < ARRAY_SIZE(ids); i++) {226const char* reported = decorations.decoration(ids[i].decorator, buf, sizeof(buf));227228// Verify format229const char* str;230for (str = reported; isdigit(*str); str++) {231// Skip over digits232}233EXPECT_EQ('\0', *str) << "Should only contain digits";234235// Verify value236EXPECT_EQ(ids[i].expected, strtol(reported, NULL, 10));237}238}239240241