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