test_logOutputList.cpp revision 12158:0fe2815ffa74
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/logLevel.hpp" 26#include "logging/logOutput.hpp" 27#include "logging/logOutputList.hpp" 28#include "runtime/os.hpp" 29#include "unittest.hpp" 30 31// Count the outputs in the given list, starting from the specified level 32static size_t output_count(LogOutputList* list, LogLevelType from = LogLevel::Error) { 33 size_t count = 0; 34 for (LogOutputList::Iterator it = list->iterator(from); it != list->end(); it++) { 35 count++; 36 } 37 return count; 38} 39 40// Get the level for an output in the given list 41static LogLevelType find_output_level(LogOutputList* list, LogOutput* o) { 42 for (size_t levelnum = 1; levelnum < LogLevel::Count; levelnum++) { 43 LogLevelType level = static_cast<LogLevelType>(levelnum); 44 for (LogOutputList::Iterator it = list->iterator(level); it != list->end(); it++) { 45 if (*it == o) { 46 return level; 47 } 48 } 49 } 50 return LogLevel::Off; 51} 52 53// Create a dummy output pointer with the specified id. 54// This dummy pointer should not be used for anything 55// but pointer comparisons with other dummies. 56static LogOutput* dummy_output(size_t id) { 57 return reinterpret_cast<LogOutput*>(id + 1); 58} 59 60// Randomly update and verify some outputs some number of times 61TEST(LogOutputList, set_output_level_update) { 62 const size_t TestOutputCount = 10; 63 const size_t TestIterations = 10000; 64 LogOutputList list; 65 size_t outputs_on_level[LogLevel::Count]; 66 LogLevelType expected_level_for_output[TestOutputCount]; 67 68 os::init_random(0x4711); 69 for (size_t i = 0; i < LogLevel::Count; i++) { 70 outputs_on_level[i] = 0; 71 } 72 outputs_on_level[LogLevel::Off] = TestOutputCount; 73 for (size_t i = 0; i < TestOutputCount; i++) { 74 expected_level_for_output[i] = LogLevel::Off; 75 } 76 77 for (size_t iteration = 0; iteration < TestIterations; iteration++) { 78 size_t output_idx = os::random() % TestOutputCount; 79 size_t levelnum = os::random() % LogLevel::Count; 80 LogLevelType level = static_cast<LogLevelType>(levelnum); 81 82 // Update the expectations 83 outputs_on_level[expected_level_for_output[output_idx]]--; 84 outputs_on_level[levelnum]++; 85 expected_level_for_output[output_idx] = level; 86 87 // Update the actual list 88 list.set_output_level(dummy_output(output_idx), level); 89 90 // Verify expected levels 91 for (size_t i = 0; i < TestOutputCount; i++) { 92 ASSERT_EQ(expected_level_for_output[i], find_output_level(&list, dummy_output(i))); 93 } 94 // Verify output counts 95 size_t expected_count = 0; 96 for (size_t i = 1; i < LogLevel::Count; i++) { 97 expected_count += outputs_on_level[i]; 98 ASSERT_EQ(expected_count, output_count(&list, static_cast<LogLevelType>(i))); 99 } 100 ASSERT_EQ(TestOutputCount, expected_count + outputs_on_level[LogLevel::Off]); 101 } 102} 103 104// Test removing outputs from a LogOutputList 105TEST(LogOutputList, set_output_level_remove) { 106 LogOutputList list; 107 108 // Add three dummy outputs per loglevel 109 for (size_t i = 1; i < LogLevel::Count; i++) { 110 list.set_output_level(dummy_output(i), static_cast<LogLevelType>(i)); 111 list.set_output_level(dummy_output(i*10), static_cast<LogLevelType>(i)); 112 list.set_output_level(dummy_output(i*100), static_cast<LogLevelType>(i)); 113 } 114 115 // Verify that they have been added successfully 116 // (Count - 1 since we don't count LogLevel::Off) 117 EXPECT_EQ(3u * (LogLevel::Count - 1), output_count(&list)); 118 // Now remove the second output from each loglevel 119 for (size_t i = 1; i < LogLevel::Count; i++) { 120 list.set_output_level(dummy_output(i*10), LogLevel::Off); 121 } 122 // Make sure they have been successfully removed 123 EXPECT_EQ(2u * (LogLevel::Count - 1), output_count(&list)); 124 125 // Now remove the remaining outputs 126 for (size_t i = 1; i < LogLevel::Count; i++) { 127 list.set_output_level(dummy_output(i), LogLevel::Off); 128 list.set_output_level(dummy_output(i*100), LogLevel::Off); 129 } 130 EXPECT_EQ(0u, output_count(&list)); 131} 132 133// Test adding to a LogOutputList 134TEST(LogOutputList, set_output_level_add) { 135 LogOutputList list; 136 137 // First add 5 outputs to Info level 138 for (size_t i = 10; i < 15; i++) { 139 list.set_output_level(dummy_output(i), LogLevel::Info); 140 } 141 142 // Verify that they have been added successfully 143 size_t count = 0; 144 for (LogOutputList::Iterator it = list.iterator(); it != list.end(); it++) { 145 ASSERT_EQ(dummy_output(10 + count++), *it); 146 } 147 ASSERT_EQ(5u, count); 148 149 // Now add more outputs, but on all different levels 150 for (size_t i = 5; i < 10; i++) { 151 list.set_output_level(dummy_output(i), LogLevel::Warning); 152 } 153 for (size_t i = 0; i < 5; i++) { 154 list.set_output_level(dummy_output(i), LogLevel::Error); 155 } 156 for (size_t i = 15; i < 20; i++) { 157 list.set_output_level(dummy_output(i), LogLevel::Debug); 158 } 159 for (size_t i = 20; i < 25; i++) { 160 list.set_output_level(dummy_output(i), LogLevel::Trace); 161 } 162 163 // Verify that that all outputs have been added, and that the order is Error, Warning, Info, Debug, Trace 164 count = 0; 165 for (LogOutputList::Iterator it = list.iterator(); it != list.end(); it++) { 166 ASSERT_EQ(dummy_output(count++), *it); 167 } 168 ASSERT_EQ(25u, count); 169} 170 171// Test is_level() on lists with a single output on different levels 172TEST(LogOutputList, is_level_single_output) { 173 for (size_t i = LogLevel::First; i < LogLevel::Count; i++) { 174 LogLevelType level = static_cast<LogLevelType>(i); 175 LogOutputList list; 176 list.set_output_level(LogOutput::Stdout, level); 177 for (size_t j = LogLevel::First; j < LogLevel::Count; j++) { 178 LogLevelType other = static_cast<LogLevelType>(j); 179 // Verify that levels finer than the current level for stdout are reported as disabled, 180 // and levels equal to or included in the current level are reported as enabled 181 if (other >= level) { 182 EXPECT_TRUE(list.is_level(other)) 183 << LogLevel::name(other) << " >= " << LogLevel::name(level) << " but is_level() returns false"; 184 } else { 185 EXPECT_FALSE(list.is_level(other)) 186 << LogLevel::name(other) << " < " << LogLevel::name(level) << " but is_level() returns true"; 187 } 188 } 189 } 190} 191 192// Test is_level() with an empty list 193TEST(LogOutputList, is_level_empty) { 194 LogOutputList emptylist; 195 for (size_t i = LogLevel::First; i < LogLevel::Count; i++) { 196 LogLevelType other = static_cast<LogLevelType>(i); 197 EXPECT_FALSE(emptylist.is_level(other)) << "is_level() returns true even though the list is empty"; 198 } 199} 200 201// Test is_level() on lists with two outputs on different levels 202TEST(LogOutputList, is_level_multiple_outputs) { 203 for (size_t i = LogLevel::First; i < LogLevel::Count - 1; i++) { 204 LogOutput* dummy1 = LogOutput::Stdout; 205 LogOutput* dummy2 = LogOutput::Stderr; 206 LogLevelType first = static_cast<LogLevelType>(i); 207 LogLevelType second = static_cast<LogLevelType>(i + 1); 208 LogOutputList list; 209 list.set_output_level(dummy1, first); 210 list.set_output_level(dummy2, second); 211 for (size_t j = LogLevel::First; j < LogLevel::Count; j++) { 212 LogLevelType other = static_cast<LogLevelType>(j); 213 // The first output's level will be the finest, expect it's level to be reported by the list 214 if (other >= first) { 215 EXPECT_TRUE(list.is_level(other)) 216 << LogLevel::name(other) << " >= " << LogLevel::name(first) << " but is_level() returns false"; 217 } else { 218 EXPECT_FALSE(list.is_level(other)) 219 << LogLevel::name(other) << " < " << LogLevel::name(first) << " but is_level() returns true"; 220 } 221 } 222 } 223} 224 225TEST(LogOutputList, level_for) { 226 LogOutputList list; 227 228 // Ask the empty list about stdout, stderr 229 EXPECT_EQ(LogLevel::Off, list.level_for(LogOutput::Stdout)); 230 EXPECT_EQ(LogLevel::Off, list.level_for(LogOutput::Stderr)); 231 232 // Ask for level in a list with two outputs on different levels 233 list.set_output_level(LogOutput::Stdout, LogLevel::Info); 234 list.set_output_level(LogOutput::Stderr, LogLevel::Trace); 235 EXPECT_EQ(LogLevel::Info, list.level_for(LogOutput::Stdout)); 236 EXPECT_EQ(LogLevel::Trace, list.level_for(LogOutput::Stderr)); 237 238 // Remove and ask again 239 list.set_output_level(LogOutput::Stdout, LogLevel::Off); 240 EXPECT_EQ(LogLevel::Off, list.level_for(LogOutput::Stdout)); 241 EXPECT_EQ(LogLevel::Trace, list.level_for(LogOutput::Stderr)); 242 243 // Ask about an unknown output 244 LogOutput* dummy = dummy_output(4711); 245 EXPECT_EQ(LogLevel::Off, list.level_for(dummy)); 246 247 for (size_t i = LogLevel::First; i <= LogLevel::Last; i++) { 248 LogLevelType level = static_cast<LogLevelType>(i); 249 list.set_output_level(dummy, level); 250 EXPECT_EQ(level, list.level_for(dummy)); 251 } 252 253 // Make sure the stderr level is still the same 254 EXPECT_EQ(LogLevel::Trace, list.level_for(LogOutput::Stderr)); 255} 256