Path: blob/master/test/hotspot/gtest/logging/test_logOutputList.cpp
41144 views
/*1* Copyright (c) 2016, 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/logFileStreamOutput.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"3031// Count the outputs in the given list, starting from the specified level32static size_t output_count(LogOutputList* list, LogLevelType from = LogLevel::Error) {33size_t count = 0;34for (LogOutputList::Iterator it = list->iterator(from); it != list->end(); it++) {35count++;36}37return count;38}3940// Get the level for an output in the given list41static LogLevelType find_output_level(LogOutputList* list, LogOutput* o) {42for (size_t levelnum = 1; levelnum < LogLevel::Count; levelnum++) {43LogLevelType level = static_cast<LogLevelType>(levelnum);44for (LogOutputList::Iterator it = list->iterator(level); it != list->end(); it++) {45if (*it == o) {46return level;47}48}49}50return LogLevel::Off;51}5253// Create a dummy output pointer with the specified id.54// This dummy pointer should not be used for anything55// but pointer comparisons with other dummies.56static LogOutput* dummy_output(size_t id) {57return reinterpret_cast<LogOutput*>(id + 1);58}5960// Randomly update and verify some outputs some number of times61TEST(LogOutputList, set_output_level_update) {62const size_t TestOutputCount = 10;63const size_t TestIterations = 10000;64LogOutputList list;65size_t outputs_on_level[LogLevel::Count];66LogLevelType expected_level_for_output[TestOutputCount];6768os::init_random(0x4711);69for (size_t i = 0; i < LogLevel::Count; i++) {70outputs_on_level[i] = 0;71}72outputs_on_level[LogLevel::Off] = TestOutputCount;73for (size_t i = 0; i < TestOutputCount; i++) {74expected_level_for_output[i] = LogLevel::Off;75}7677for (size_t iteration = 0; iteration < TestIterations; iteration++) {78size_t output_idx = os::random() % TestOutputCount;79size_t levelnum = os::random() % LogLevel::Count;80LogLevelType level = static_cast<LogLevelType>(levelnum);8182// Update the expectations83outputs_on_level[expected_level_for_output[output_idx]]--;84outputs_on_level[levelnum]++;85expected_level_for_output[output_idx] = level;8687// Update the actual list88list.set_output_level(dummy_output(output_idx), level);8990// Verify expected levels91for (size_t i = 0; i < TestOutputCount; i++) {92ASSERT_EQ(expected_level_for_output[i], find_output_level(&list, dummy_output(i)));93}94// Verify output counts95size_t expected_count = 0;96for (size_t i = 1; i < LogLevel::Count; i++) {97expected_count += outputs_on_level[i];98ASSERT_EQ(expected_count, output_count(&list, static_cast<LogLevelType>(i)));99}100ASSERT_EQ(TestOutputCount, expected_count + outputs_on_level[LogLevel::Off]);101}102}103104// Test removing outputs from a LogOutputList105TEST(LogOutputList, set_output_level_remove) {106LogOutputList list;107108// Add three dummy outputs per loglevel109for (size_t i = 1; i < LogLevel::Count; i++) {110list.set_output_level(dummy_output(i), static_cast<LogLevelType>(i));111list.set_output_level(dummy_output(i*10), static_cast<LogLevelType>(i));112list.set_output_level(dummy_output(i*100), static_cast<LogLevelType>(i));113}114115// Verify that they have been added successfully116// (Count - 1 since we don't count LogLevel::Off)117EXPECT_EQ(3u * (LogLevel::Count - 1), output_count(&list));118// Now remove the second output from each loglevel119for (size_t i = 1; i < LogLevel::Count; i++) {120list.set_output_level(dummy_output(i*10), LogLevel::Off);121}122// Make sure they have been successfully removed123EXPECT_EQ(2u * (LogLevel::Count - 1), output_count(&list));124125// Now remove the remaining outputs126for (size_t i = 1; i < LogLevel::Count; i++) {127list.set_output_level(dummy_output(i), LogLevel::Off);128list.set_output_level(dummy_output(i*100), LogLevel::Off);129}130EXPECT_EQ(0u, output_count(&list));131}132133// Test adding to a LogOutputList134TEST(LogOutputList, set_output_level_add) {135LogOutputList list;136137// First add 5 outputs to Info level138for (size_t i = 10; i < 15; i++) {139list.set_output_level(dummy_output(i), LogLevel::Info);140}141142// Verify that they have been added successfully143size_t count = 0;144for (LogOutputList::Iterator it = list.iterator(); it != list.end(); it++) {145ASSERT_EQ(dummy_output(10 + count++), *it);146}147ASSERT_EQ(5u, count);148149// Now add more outputs, but on all different levels150for (size_t i = 5; i < 10; i++) {151list.set_output_level(dummy_output(i), LogLevel::Warning);152}153for (size_t i = 0; i < 5; i++) {154list.set_output_level(dummy_output(i), LogLevel::Error);155}156for (size_t i = 15; i < 20; i++) {157list.set_output_level(dummy_output(i), LogLevel::Debug);158}159for (size_t i = 20; i < 25; i++) {160list.set_output_level(dummy_output(i), LogLevel::Trace);161}162163// Verify that that all outputs have been added, and that the order is Error, Warning, Info, Debug, Trace164count = 0;165for (LogOutputList::Iterator it = list.iterator(); it != list.end(); it++) {166ASSERT_EQ(dummy_output(count++), *it);167}168ASSERT_EQ(25u, count);169}170171// Test is_level() on lists with a single output on different levels172TEST(LogOutputList, is_level_single_output) {173for (size_t i = LogLevel::First; i < LogLevel::Count; i++) {174LogLevelType level = static_cast<LogLevelType>(i);175LogOutputList list;176list.set_output_level(&StdoutLog, level);177for (size_t j = LogLevel::First; j < LogLevel::Count; j++) {178LogLevelType 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 enabled181if (other >= level) {182EXPECT_TRUE(list.is_level(other))183<< LogLevel::name(other) << " >= " << LogLevel::name(level) << " but is_level() returns false";184} else {185EXPECT_FALSE(list.is_level(other))186<< LogLevel::name(other) << " < " << LogLevel::name(level) << " but is_level() returns true";187}188}189}190}191192// Test is_level() with an empty list193TEST(LogOutputList, is_level_empty) {194LogOutputList emptylist;195for (size_t i = LogLevel::First; i < LogLevel::Count; i++) {196LogLevelType other = static_cast<LogLevelType>(i);197EXPECT_FALSE(emptylist.is_level(other)) << "is_level() returns true even though the list is empty";198}199}200201// Test is_level() on lists with two outputs on different levels202TEST(LogOutputList, is_level_multiple_outputs) {203for (size_t i = LogLevel::First; i < LogLevel::Count - 1; i++) {204LogOutput* dummy1 = &StdoutLog;205LogOutput* dummy2 = &StderrLog;206LogLevelType first = static_cast<LogLevelType>(i);207LogLevelType second = static_cast<LogLevelType>(i + 1);208LogOutputList list;209list.set_output_level(dummy1, first);210list.set_output_level(dummy2, second);211for (size_t j = LogLevel::First; j < LogLevel::Count; j++) {212LogLevelType other = static_cast<LogLevelType>(j);213// The first output's level will be the finest, expect it's level to be reported by the list214if (other >= first) {215EXPECT_TRUE(list.is_level(other))216<< LogLevel::name(other) << " >= " << LogLevel::name(first) << " but is_level() returns false";217} else {218EXPECT_FALSE(list.is_level(other))219<< LogLevel::name(other) << " < " << LogLevel::name(first) << " but is_level() returns true";220}221}222}223}224225TEST(LogOutputList, level_for) {226LogOutputList list;227228// Ask the empty list about stdout, stderr229EXPECT_EQ(LogLevel::Off, list.level_for(&StdoutLog));230EXPECT_EQ(LogLevel::Off, list.level_for(&StderrLog));231232// Ask for level in a list with two outputs on different levels233list.set_output_level(&StdoutLog, LogLevel::Info);234list.set_output_level(&StderrLog, LogLevel::Trace);235EXPECT_EQ(LogLevel::Info, list.level_for(&StdoutLog));236EXPECT_EQ(LogLevel::Trace, list.level_for(&StderrLog));237238// Remove and ask again239list.set_output_level(&StdoutLog, LogLevel::Off);240EXPECT_EQ(LogLevel::Off, list.level_for(&StdoutLog));241EXPECT_EQ(LogLevel::Trace, list.level_for(&StderrLog));242243// Ask about an unknown output244LogOutput* dummy = dummy_output(4711);245EXPECT_EQ(LogLevel::Off, list.level_for(dummy));246247for (size_t i = LogLevel::First; i <= LogLevel::Last; i++) {248LogLevelType level = static_cast<LogLevelType>(i);249list.set_output_level(dummy, level);250EXPECT_EQ(level, list.level_for(dummy));251}252253// Make sure the stderr level is still the same254EXPECT_EQ(LogLevel::Trace, list.level_for(&StderrLog));255}256257258