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/logFileStreamOutput.hpp" 26#include "logging/logLevel.hpp" 27#include "logging/logOutput.hpp" 28#include "logging/logTag.hpp" 29#include "logging/logTagSet.hpp" 30#include "unittest.hpp" 31 32// Test the default level for each tagset 33TEST(LogTagSet, defaults) { 34 for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { 35 char buf[256]; 36 ts->label(buf, sizeof(buf)); 37 SCOPED_TRACE(buf); 38 EXPECT_TRUE(ts->is_level(LogLevel::Error)); 39 EXPECT_TRUE(ts->is_level(LogLevel::Warning)); 40 EXPECT_FALSE(ts->is_level(LogLevel::Info)); 41 EXPECT_TRUE(ts->has_output(&StdoutLog)); 42 EXPECT_FALSE(ts->has_output(&StderrLog)); 43 } 44} 45 46TEST(LogTagSet, has_output) { 47 LogTagSet& ts = LogTagSetMapping<LOG_TAGS(logging)>::tagset(); 48 ts.set_output_level(&StderrLog, LogLevel::Trace); 49 EXPECT_TRUE(ts.has_output(&StderrLog)); 50 EXPECT_FALSE(ts.has_output(NULL)); 51 ts.set_output_level(&StderrLog, LogLevel::Off); 52 EXPECT_FALSE(ts.has_output(&StderrLog)); 53} 54 55TEST(LogTagSet, ntags) { 56 const LogTagSet& ts = LogTagSetMapping<LOG_TAGS(logging)>::tagset(); 57 EXPECT_EQ(1u, ts.ntags()); 58 const LogTagSet& ts2 = LogTagSetMapping<LOG_TAGS(logging, gc, class, safepoint, heap)>::tagset(); 59 EXPECT_EQ(5u, ts2.ntags()); 60} 61 62TEST(LogTagSet, is_level) { 63 LogTagSet& ts = LogTagSetMapping<LOG_TAGS(logging)>::tagset(); 64 // Set info level on stdout and verify that is_level() reports correctly 65 ts.set_output_level(&StdoutLog, LogLevel::Info); 66 EXPECT_TRUE(ts.is_level(LogLevel::Error)); 67 EXPECT_TRUE(ts.is_level(LogLevel::Warning)); 68 EXPECT_TRUE(ts.is_level(LogLevel::Info)); 69 EXPECT_FALSE(ts.is_level(LogLevel::Debug)); 70 EXPECT_FALSE(ts.is_level(LogLevel::Trace)); 71 ts.set_output_level(&StdoutLog, LogLevel::Default); 72 EXPECT_TRUE(ts.is_level(LogLevel::Default)); 73} 74 75TEST(LogTagSet, level_for) { 76 LogOutput* output = &StdoutLog; 77 LogTagSet& ts = LogTagSetMapping<LOG_TAGS(logging)>::tagset(); 78 for (uint i = 0; i < LogLevel::Count; i++) { 79 LogLevelType level = static_cast<LogLevelType>(i); 80 // Set the level and verify that level_for() reports it back 81 ts.set_output_level(output, level); 82 EXPECT_EQ(level, ts.level_for(output)); 83 } 84 ts.set_output_level(output, LogLevel::Default); 85} 86 87TEST(LogTagSet, contains) { 88 // Verify that contains works as intended for a few predetermined tagsets 89 const LogTagSet& ts = LogTagSetMapping<LOG_TAGS(logging)>::tagset(); 90 EXPECT_TRUE(ts.contains(PREFIX_LOG_TAG(logging))); 91 EXPECT_FALSE(ts.contains(PREFIX_LOG_TAG(gc))); 92 EXPECT_FALSE(ts.contains(PREFIX_LOG_TAG(class))); 93 94 const LogTagSet& ts2 = LogTagSetMapping<LOG_TAGS(logging, gc)>::tagset(); 95 EXPECT_TRUE(ts2.contains(PREFIX_LOG_TAG(logging))); 96 EXPECT_TRUE(ts2.contains(PREFIX_LOG_TAG(gc))); 97 EXPECT_FALSE(ts2.contains(PREFIX_LOG_TAG(class))); 98 99 const LogTagSet& ts3 = LogTagSetMapping<LOG_TAGS(logging, gc, class)>::tagset(); 100 EXPECT_TRUE(ts3.contains(PREFIX_LOG_TAG(logging))); 101 EXPECT_TRUE(ts3.contains(PREFIX_LOG_TAG(gc))); 102 EXPECT_TRUE(ts3.contains(PREFIX_LOG_TAG(class))); 103 EXPECT_FALSE(ts3.contains(PREFIX_LOG_TAG(safepoint))); 104 105 const LogTagSet& ts4 = LogTagSetMapping<LOG_TAGS(logging, gc, class, safepoint, heap)>::tagset(); 106 EXPECT_TRUE(ts4.contains(PREFIX_LOG_TAG(logging))); 107 EXPECT_TRUE(ts4.contains(PREFIX_LOG_TAG(gc))); 108 EXPECT_TRUE(ts4.contains(PREFIX_LOG_TAG(class))); 109 EXPECT_TRUE(ts4.contains(PREFIX_LOG_TAG(safepoint))); 110 EXPECT_TRUE(ts4.contains(PREFIX_LOG_TAG(heap))); 111} 112 113TEST(LogTagSet, label) { 114 char buf[256]; 115 const LogTagSet& ts = LogTagSetMapping<LOG_TAGS(logging, safepoint)>::tagset(); 116 ASSERT_NE(-1, ts.label(buf, sizeof(buf))); 117 EXPECT_STREQ("logging,safepoint", buf); 118 // Verify using a custom separator 119 ASSERT_NE(-1, ts.label(buf, sizeof(buf), "++")); 120 EXPECT_STREQ("logging++safepoint", buf); 121 122 // Verify with three tags 123 const LogTagSet& ts1 = LogTagSetMapping<LOG_TAGS(logging, safepoint, jni)>::tagset(); 124 ASSERT_NE(-1, ts1.label(buf, sizeof(buf))); 125 EXPECT_STREQ("logging,safepoint,jni", buf); 126 127 // Verify with a single tag 128 const LogTagSet& ts2 = LogTagSetMapping<LOG_TAGS(logging)>::tagset(); 129 ASSERT_NE(-1, ts2.label(buf, sizeof(buf))); 130 EXPECT_STREQ("logging", buf); 131} 132 133TEST(LogTagSet, duplicates) { 134 for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { 135 char ts_name[512]; 136 ts->label(ts_name, sizeof(ts_name), ","); 137 138 // verify that NO_TAG is never followed by a real tag 139 for (size_t i = 0; i < LogTag::MaxTags; i++) { 140 if (ts->tag(i) == LogTag::__NO_TAG) { 141 for (i++; i < LogTag::MaxTags; i++) { 142 EXPECT_EQ(LogTag::__NO_TAG, ts->tag(i)) 143 << "NO_TAG was followed by a real tag (" << LogTag::name(ts->tag(i)) << ") in tagset " << ts_name; 144 } 145 } 146 } 147 148 // verify that there are no duplicate tagsets (same tags in different order) 149 for (LogTagSet* other = ts->next(); other != NULL; other = other->next()) { 150 if (ts->ntags() != other->ntags()) { 151 continue; 152 } 153 bool equal = true; 154 for (size_t i = 0; i < ts->ntags(); i++) { 155 LogTagType tag = ts->tag(i); 156 if (!other->contains(tag)) { 157 equal = false; 158 break; 159 } 160 } 161 // Since tagsets are implemented using template arguments, using both of 162 // the (logically equivalent) tagsets (t1, t2) and (t2, t1) somewhere will 163 // instantiate two different LogTagSetMappings. This causes multiple 164 // tagset instances to be created for the same logical set. We want to 165 // avoid this to save time, memory and prevent any confusion around it. 166 if (equal) { 167 char other_name[512]; 168 other->label(other_name, sizeof(other_name), ","); 169 FAIL() << "duplicate LogTagSets found: '" << ts_name << "' vs '" << other_name << "' " 170 << "(tags must always be specified in the same order for each tagset)"; 171 } 172 } 173 } 174} 175