< prev index next >

src/share/vm/logging/log.cpp

Print this page
rev 10178 : imported patch 8145934
rev 10179 : [mq]: 8145934.alternative

*** 28,40 **** --- 28,68 ---- #ifndef PRODUCT #include "logging/log.hpp" #include "logging/logConfiguration.hpp" + #include "logging/logMessage.hpp" + #include "logging/logMessageBuffer.hpp" #include "logging/logOutput.hpp" #include "memory/resourceArea.hpp" + static bool file_contains_substrings_in_order(const char* filename, const char* substrs[]) { + FILE* fp = fopen(filename, "r"); + assert(fp, "File read error"); + char buffer[1024]; + for (int i = 0; substrs[i] != NULL; i++) { + assert(sizeof(buffer) > strlen(substrs[i]), "insufficient buffer"); + bool found = false; + while (fgets(buffer, sizeof(buffer), fp) != NULL) { + if (strstr(buffer, substrs[i]) != NULL) { + found = true; + break; + } + } + if (!found) { + return false; + } + } + fclose(fp); + return true; + } + + static bool file_contains_substring(const char* filename, const char* substr) { + const char* strs[] = {substr, NULL}; + return file_contains_substrings_in_order(filename, strs); + } + void Test_log_length() { remove("loglengthoutput.txt"); // Write long message to output file ResourceMark rm;
*** 81,97 **** "37:1234567890-"); LogConfiguration::parse_log_arguments("loglengthoutput.txt", "all=off", NULL, NULL, log.error_stream()); // Look for end of message in output file ! FILE* fp = fopen("loglengthoutput.txt", "r"); ! assert(fp, "File read error"); ! char output[600]; ! if (fgets(output, 600, fp) != NULL) { ! assert(strstr(output, "37:1234567890-"), "logging print size error"); ! } ! fclose(fp); remove("loglengthoutput.txt"); } #define assert_str_eq(s1, s2) \ assert(strcmp(s1, s2) == 0, "Expected '%s' to equal '%s'", s1, s2) --- 109,119 ---- "37:1234567890-"); LogConfiguration::parse_log_arguments("loglengthoutput.txt", "all=off", NULL, NULL, log.error_stream()); // Look for end of message in output file ! assert(file_contains_substring("loglengthoutput.txt", "37:1234567890-"), "logging print size error"); remove("loglengthoutput.txt"); } #define assert_str_eq(s1, s2) \ assert(strcmp(s1, s2) == 0, "Expected '%s' to equal '%s'", s1, s2)
*** 134,139 **** --- 156,371 ---- // Restore saved configuration LogConfiguration::parse_log_arguments("stdout", saved_config, NULL, NULL, log.error_stream()); os::free(saved_config); } + + class LogMessageTest { + private: + static LogHandle(logging) _log; + static const char* _level_filename[]; + + static void test_level_inclusion(); + static void test_long_message(); + static void test_message_with_many_lines(); + static void test_line_order(); + static void test_prefixing(); + static void test_scoped_messages(); + + public: + static void test(); + }; + + const char* LogMessageTest::_level_filename[] = { + NULL, // LogLevel::Off + #define LOG_LEVEL(name, printname) "multiline-" #printname ".log", + LOG_LEVEL_LIST + #undef LOG_LEVEL + }; + + void Test_multiline_logging() { + LogMessageTest::test(); + } + + void LogMessageTest::test() { + ResourceMark rm; + + for (int i = 0; i < LogLevel::Count; i++) { + char buf[32]; + // Attempt to remove possibly pre-existing log files + remove(_level_filename[i]); + + jio_snprintf(buf, sizeof(buf), "logging=%s", LogLevel::name(static_cast<LogLevelType>(i))); + bool success = LogConfiguration::parse_log_arguments(_level_filename[i], buf, + NULL, NULL, _log.error_stream()); + assert(success, "unable to configure logging to file '%s'", _level_filename[i]); + } + + test_level_inclusion(); + test_line_order(); + test_long_message(); + test_message_with_many_lines(); + test_prefixing(); + test_scoped_messages(); + + // Stop logging to the files and remove them. + for (int i = 0; i < LogLevel::Count; i++) { + LogConfiguration::parse_log_arguments(_level_filename[i], "all=off", NULL, NULL, _log.error_stream()); + remove(_level_filename[i]); + } + } + + // Verify that messages with multiple levels are written + // to outputs configured for all the corresponding levels + void LogMessageTest::test_level_inclusion() { + const size_t message_count = 10; + LogMessageBuffer msg[message_count]; + + struct { + int message_number; + LogLevelType level; + } lines[] = { + { 0, LogLevel::Error }, + { 1, LogLevel::Info }, + { 2, LogLevel::Info }, { 2, LogLevel::Debug }, + { 3, LogLevel::Info }, { 3, LogLevel::Warning }, + { 4, LogLevel::Debug }, { 4, LogLevel::Warning }, + { 5, LogLevel::Trace }, { 5, LogLevel::Debug }, + { 6, LogLevel::Warning }, { 6, LogLevel::Error }, + { 7, LogLevel::Trace }, { 7, LogLevel::Info }, { 7, LogLevel::Debug }, + { 8, LogLevel::Trace }, { 8, LogLevel::Debug }, { 8, LogLevel::Info }, + { 8, LogLevel::Warning }, { 8, LogLevel::Error}, + { 9, LogLevel::Trace } + }; + + // Fill in messages with the above lines + for (size_t i = 0; i < ARRAY_SIZE(lines); i++) { + switch (lines[i].level) { + #define LOG_LEVEL(name, printname) \ + case LogLevel::name: \ + msg[lines[i].message_number].printname("msg[%d]: " #printname, lines[i].message_number); \ + break; + LOG_LEVEL_LIST + #undef LOG_LEVEL + } + } + + for (size_t i = 0; i < message_count; i++) { + _log.write(msg[i]); + } + + // Verify that lines are written to the expected log files + for (size_t i = 0; i < ARRAY_SIZE(lines); i++) { + char expected[256]; + jio_snprintf(expected, sizeof(expected), "msg[%d]: %s", + lines[i].message_number, LogLevel::name(lines[i].level)); + for (int level = lines[i].level; level > 0; level--) { + assert(file_contains_substring(_level_filename[level], expected), + "line #" SIZE_FORMAT " missing from log file '%s'", i, _level_filename[level]); + } + for (int level = lines[i].level + 1; level < LogLevel::Count; level++) { + assert(!file_contains_substring(_level_filename[level], expected), + "line #" SIZE_FORMAT " erroneously included in log file '%s'", i, _level_filename[level]); + } + } + } + + // Verify that messages are logged in the order they are added to the log message + void LogMessageTest::test_line_order() { + LogMessageBuffer msg; + msg.info("info line").error("error line").trace("trace line") + .error("another error").warning("warning line").debug("debug line"); + _log.write(msg); + + const char* expected[] = { "info line", "error line", "trace line", + "another error", "warning line", "debug line", NULL }; + assert(file_contains_substrings_in_order(_level_filename[LogLevel::Trace], expected), + "output missing or in incorrect order"); + } + + void LogMessageTest::test_long_message() { + // Write 10K bytes worth of log data + LogMessageBuffer msg; + const size_t size = 10 * K; + const char* start_marker = "#start#"; + const char* end_marker = "#the end#"; + char* data = NEW_C_HEAP_ARRAY(char, size, mtLogging); + + // fill buffer with start_marker...some data...end_marker + sprintf(data, "%s", start_marker); + for (size_t i = strlen(start_marker); i < size; i++) { + data[i] = '0' + (i % 10); + } + sprintf(data + size - strlen(end_marker) - 1, "%s", end_marker); + + msg.trace("%s", data); // Adds a newline, making the message exactly 10K in length. + _log.write(msg); + + const char* expected[] = { start_marker, "0123456789", end_marker, NULL }; + assert(file_contains_substrings_in_order(_level_filename[LogLevel::Trace], expected), + "unable to print long line"); + FREE_C_HEAP_ARRAY(char, data); + } + + void LogMessageTest::test_message_with_many_lines() { + const size_t lines = 100; + const size_t line_length = 16; + + LogMessageBuffer msg; + for (size_t i = 0; i < lines; i++) { + msg.info("Line #" SIZE_FORMAT, i); + } + _log.write(msg); + + char expected_lines_data[lines][line_length]; + const char* expected_lines[lines + 1]; + for (size_t i = 0; i < lines; i++) { + jio_snprintf(&expected_lines_data[i][0], line_length, "Line #" SIZE_FORMAT, i); + expected_lines[i] = expected_lines_data[i]; + } + expected_lines[lines] = NULL; + + assert(file_contains_substrings_in_order(_level_filename[LogLevel::Trace], expected_lines), + "couldn't find all lines in multiline message"); + } + + static size_t dummy_prefixer(char* buf, size_t len) { + static int i = 0; + const char* prefix = "some prefix: "; + const size_t prefix_len = strlen(prefix); + if (len < prefix_len) { + return prefix_len; + } + jio_snprintf(buf, len, "%s", prefix); + return prefix_len; + } + + void LogMessageTest::test_prefixing() { + LogMessageBuffer msg; + msg.set_prefix(dummy_prefixer); + for (int i = 0; i < 3; i++) { + msg.info("test %d", i); + } + msg.set_prefix(NULL); + msg.info("test 3"); + _log.write(msg); + + const char* expected[] = { + "] some prefix: test 0", + "] some prefix: test 1", + "] some prefix: test 2", + "] test 3", + NULL + }; + assert(file_contains_substrings_in_order(_level_filename[LogLevel::Trace], expected), "error in prefixed output"); + } + + void LogMessageTest::test_scoped_messages() { + { + LogMessage(logging) msg; + msg.info("scoped info"); + } + assert(file_contains_substring(_level_filename[LogLevel::Info], "scoped info"), + "missing output from scoped log message"); + } + #endif // PRODUCT
< prev index next >