rev 11857 : [mq]: 8157948

   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 "logTestFixture.hpp"
  26 #include "logTestUtils.inline.hpp"
  27 #include "logging/logConfiguration.hpp"
  28 #include "logging/logLevel.hpp"
  29 #include "logging/logOutput.hpp"
  30 #include "logging/logTag.hpp"
  31 #include "logging/logTagSet.hpp"
  32 #include "memory/resourceArea.hpp"
  33 #include "unittest.hpp"
  34 #include "utilities/ostream.hpp"
  35 
  36 class LogConfigurationTest : public LogTestFixture {
  37  protected:
  38   static char _all_decorators[256];
  39 
  40  public:
  41   static void SetUpTestCase();
  42 };
  43 
  44 char LogConfigurationTest::_all_decorators[256];
  45 
  46 // Prepare _all_decorators to contain the full list of decorators (comma separated)
  47 void LogConfigurationTest::SetUpTestCase() {
  48   char *pos = _all_decorators;
  49   for (size_t i = 0; i < LogDecorators::Count; i++) {
  50     pos += jio_snprintf(pos, sizeof(_all_decorators) - (pos - _all_decorators), "%s%s",
  51                         (i == 0 ? "" : ","),
  52                         LogDecorators::name(static_cast<LogDecorators::Decorator>(i)));
  53   }
  54 }
  55 
  56 // Check if the given text is included by LogConfiguration::describe()
  57 static bool is_described(const char* text) {
  58   ResourceMark rm;
  59   stringStream ss;
  60   LogConfiguration::describe(&ss);
  61   return string_contains_substring(ss.as_string(), text);
  62 }
  63 
  64 TEST_F(LogConfigurationTest, describe) {
  65   ResourceMark rm;
  66   stringStream ss;
  67   LogConfiguration::describe(&ss);
  68   const char* description = ss.as_string();
  69 
  70   // Verify that stdout and stderr are listed by default
  71   EXPECT_PRED2(string_contains_substring, description, LogOutput::Stdout->name());
  72   EXPECT_PRED2(string_contains_substring, description, LogOutput::Stderr->name());
  73 
  74   // Verify that each tag, level and decorator is listed
  75   for (size_t i = 0; i < LogTag::Count; i++) {
  76     EXPECT_PRED2(string_contains_substring, description, LogTag::name(static_cast<LogTagType>(i)));
  77   }
  78   for (size_t i = 0; i < LogLevel::Count; i++) {
  79     EXPECT_PRED2(string_contains_substring, description, LogLevel::name(static_cast<LogLevelType>(i)));
  80   }
  81   for (size_t i = 0; i < LogDecorators::Count; i++) {
  82     EXPECT_PRED2(string_contains_substring, description, LogDecorators::name(static_cast<LogDecorators::Decorator>(i)));
  83   }
  84 
  85   // Verify that the default configuration is printed
  86   char expected_buf[256];
  87   int ret = jio_snprintf(expected_buf, sizeof(expected_buf), "=%s", LogLevel::name(LogLevel::Default));
  88   ASSERT_NE(-1, ret);
  89   EXPECT_PRED2(string_contains_substring, description, expected_buf);
  90   EXPECT_PRED2(string_contains_substring, description, "#1: stderr all=off");
  91 
  92   // Verify default decorators are listed
  93   LogDecorators default_decorators;
  94   expected_buf[0] = '\0';
  95   for (size_t i = 0; i < LogDecorators::Count; i++) {
  96     LogDecorators::Decorator d = static_cast<LogDecorators::Decorator>(i);
  97     if (default_decorators.is_decorator(d)) {
  98       ASSERT_LT(strlen(expected_buf), sizeof(expected_buf));
  99       ret = jio_snprintf(expected_buf + strlen(expected_buf),
 100                          sizeof(expected_buf) - strlen(expected_buf),
 101                          "%s%s",
 102                          strlen(expected_buf) > 0 ? "," : "",
 103                          LogDecorators::name(d));
 104       ASSERT_NE(-1, ret);
 105     }
 106   }
 107   EXPECT_PRED2(string_contains_substring, description, expected_buf);
 108 
 109   // Add a new output and verify that it gets described after it has been added
 110   const char* what = "all=trace";
 111   EXPECT_FALSE(is_described(TestLogFileName)) << "Test output already exists!";
 112   set_log_config(TestLogFileName, what);
 113   EXPECT_TRUE(is_described(TestLogFileName));
 114   EXPECT_TRUE(is_described("logging=trace"));
 115 }
 116 
 117 // Test updating an existing log output
 118 TEST_F(LogConfigurationTest, update_output) {
 119   // Update stdout twice, first using it's name, and the second time its index #
 120   const char* test_outputs[] = { "stdout", "#0" };
 121   for (size_t i = 0; i < ARRAY_SIZE(test_outputs); i++) {
 122     set_log_config(test_outputs[i], "all=info");
 123 
 124     // Verify configuration using LogConfiguration::describe
 125     EXPECT_TRUE(is_described("#0: stdout"));
 126     EXPECT_TRUE(is_described("logging=info"));
 127 
 128     // Verify by iterating over tagsets
 129     LogOutput* o = LogOutput::Stdout;
 130     for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
 131       EXPECT_TRUE(ts->has_output(o));
 132       EXPECT_TRUE(ts->is_level(LogLevel::Info));
 133       EXPECT_FALSE(ts->is_level(LogLevel::Debug));
 134     }
 135 
 136     // Now change the level and verify the change propagated
 137     set_log_config(test_outputs[i], "all=debug");
 138     for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
 139       EXPECT_TRUE(ts->has_output(o));
 140       EXPECT_TRUE(ts->is_level(LogLevel::Debug));
 141       EXPECT_FALSE(ts->is_level(LogLevel::Trace));
 142     }
 143   }
 144 }
 145 
 146 // Test adding a new output to the configuration
 147 TEST_F(LogConfigurationTest, add_new_output) {
 148   const char* what = "all=trace";
 149 
 150   ASSERT_FALSE(is_described(TestLogFileName));
 151   set_log_config(TestLogFileName, what);
 152 
 153   // Verify new output using LogConfiguration::describe
 154   EXPECT_TRUE(is_described(TestLogFileName));
 155   EXPECT_TRUE(is_described("logging=trace"));
 156 
 157   // Also verify by iterating over tagsets, checking levels on tagsets
 158   for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
 159     EXPECT_TRUE(ts->is_level(LogLevel::Trace));
 160   }
 161 }
 162 
 163 TEST_F(LogConfigurationTest, disable_logging) {
 164   // Add TestLogFileName as an output
 165   set_log_config(TestLogFileName, "logging=info");
 166 
 167   LogConfiguration::disable_logging();
 168 
 169   // Verify TestLogFileName was disabled
 170   EXPECT_FALSE(is_described(TestLogFileName));
 171 
 172   // Verify that no tagset has logging enabled
 173   for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
 174     EXPECT_FALSE(ts->has_output(LogOutput::Stdout));
 175     EXPECT_FALSE(ts->has_output(LogOutput::Stderr));
 176     EXPECT_FALSE(ts->is_level(LogLevel::Error));
 177   }
 178 }
 179 
 180 // Test disabling a particular output
 181 TEST_F(LogConfigurationTest, disable_output) {
 182   // Disable the default configuration for stdout
 183   set_log_config("stdout", "all=off");
 184 
 185   // Verify configuration using LogConfiguration::describe
 186   EXPECT_TRUE(is_described("#0: stdout all=off"));
 187 
 188   // Verify by iterating over tagsets
 189   LogOutput* o = LogOutput::Stdout;
 190   for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
 191     EXPECT_FALSE(ts->has_output(o));
 192     EXPECT_FALSE(ts->is_level(LogLevel::Error));
 193   }
 194 
 195   // Add a new file output
 196   const char* what = "all=debug";
 197   set_log_config(TestLogFileName, what);
 198   EXPECT_TRUE(is_described(TestLogFileName));
 199 
 200   // Now disable it, verifying it is removed completely
 201   set_log_config(TestLogFileName, "all=off");
 202   EXPECT_FALSE(is_described(TestLogFileName));
 203   for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
 204     EXPECT_FALSE(ts->is_level(LogLevel::Error));
 205   }
 206 }
 207 
 208 // Test reconfiguration of the selected decorators for an output
 209 TEST_F(LogConfigurationTest, reconfigure_decorators) {
 210   // Configure stderr with all decorators
 211   set_log_config("stderr", "all=off", _all_decorators);
 212   char buf[256];
 213   int ret = jio_snprintf(buf, sizeof(buf), "#1: stderr all=off %s", _all_decorators);
 214   ASSERT_NE(-1, ret);
 215   EXPECT_TRUE(is_described(buf)) << "'" << buf << "' not described after reconfiguration";
 216 
 217   // Now reconfigure logging on stderr with no decorators
 218   set_log_config("stderr", "all=off", "none");
 219   EXPECT_TRUE(is_described("#1: stderr all=off \n")) << "Expecting no decorators";
 220 }
 221 
 222 // Test that invalid options cause configuration errors
 223 TEST_F(LogConfigurationTest, invalid_configure_options) {
 224   LogConfiguration::disable_logging();
 225   const char* invalid_outputs[] = { "#2", "invalidtype=123", ":invalid/path}to*file?" };
 226   for (size_t i = 0; i < ARRAY_SIZE(invalid_outputs); i++) {
 227     EXPECT_FALSE(set_log_config(invalid_outputs[i], "", "", "", true))
 228       << "Accepted invalid output '" << invalid_outputs[i] << "'";
 229   }
 230   EXPECT_FALSE(LogConfiguration::parse_command_line_arguments("all=invalid_level"));
 231   EXPECT_FALSE(LogConfiguration::parse_command_line_arguments("what=invalid"));
 232   EXPECT_FALSE(LogConfiguration::parse_command_line_arguments("all::invalid_decorator"));
 233 }
 234 
 235 // Test empty configuration options
 236 TEST_F(LogConfigurationTest, parse_empty_command_line_arguments) {
 237   const char* empty_variations[] = { "", ":", "::", ":::", "::::" };
 238   for (size_t i = 0; i < ARRAY_SIZE(empty_variations); i++) {
 239     const char* cmdline = empty_variations[i];
 240     bool ret = LogConfiguration::parse_command_line_arguments(cmdline);
 241     EXPECT_TRUE(ret) << "Error parsing command line arguments '" << cmdline << "'";
 242     for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) {
 243       EXPECT_EQ(LogLevel::Unspecified, ts->level_for(LogOutput::Stdout));
 244     }
 245   }
 246 }
 247 
 248 // Test basic command line parsing & configuration
 249 TEST_F(LogConfigurationTest, parse_command_line_arguments) {
 250   // Prepare a command line for logging*=debug on stderr with all decorators
 251   int ret;
 252   char buf[256];
 253   ret = jio_snprintf(buf, sizeof(buf), "logging*=debug:stderr:%s", _all_decorators);
 254   ASSERT_NE(-1, ret);
 255 
 256   bool success = LogConfiguration::parse_command_line_arguments(buf);
 257   EXPECT_TRUE(success) << "Error parsing valid command line arguments '" << buf << "'";
 258   // Ensure the new configuration applied
 259   EXPECT_TRUE(is_described("logging=debug"));
 260   EXPECT_TRUE(is_described(_all_decorators));
 261 
 262   // Test the configuration of file outputs as well
 263   ret = jio_snprintf(buf, sizeof(buf), ":%s", TestLogFileName);
 264   ASSERT_NE(-1, ret);
 265   EXPECT_TRUE(LogConfiguration::parse_command_line_arguments(buf));
 266 }
 267 
 268 // Test split up log configuration arguments
 269 TEST_F(LogConfigurationTest, parse_log_arguments) {
 270   ResourceMark rm;
 271   stringStream ss;
 272   // Verify that it's possible to configure each individual tag
 273   for (size_t t = 1 /* Skip _NO_TAG */; t < LogTag::Count; t++) {
 274     const LogTagType tag = static_cast<LogTagType>(t);
 275     EXPECT_TRUE(LogConfiguration::parse_log_arguments("stdout", LogTag::name(tag), "", "", &ss));
 276   }
 277   // Same for each level
 278   for (size_t l = 0; l < LogLevel::Count; l++) {
 279     const LogLevelType level = static_cast<LogLevelType>(l);
 280     char expected_buf[256];
 281     int ret = jio_snprintf(expected_buf, sizeof(expected_buf), "all=%s", LogLevel::name(level));
 282     ASSERT_NE(-1, ret);
 283     EXPECT_TRUE(LogConfiguration::parse_log_arguments("stderr", expected_buf, "", "", &ss));
 284   }
 285   // And for each decorator
 286   for (size_t d = 0; d < LogDecorators::Count; d++) {
 287     const LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(d);
 288     EXPECT_TRUE(LogConfiguration::parse_log_arguments("#0", "", LogDecorators::name(decorator), "", &ss));
 289   }
 290   EXPECT_STREQ("", ss.as_string()) << "Error reported while parsing: " << ss.as_string();
 291 }



























--- EOF ---