Files
gem5/src/base/trace.test.cc
Yan Lee b923cbe840 base: add Activate to enable log of particular targets
When the activate list is not empty, only the target name in the list
will be enabled on logging. Even if the target name is in the activate
list, it will need to enable the flag with --debug-flags to enable the
log correctly.

Change-Id: Ic41cb97c8a2530fdc01e954d6cab76ae475d8722
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70617
Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
2023-05-16 09:02:38 +00:00

688 lines
22 KiB
C++

/*
* Copyright (c) 2021 Daniel R. Carvalho
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include <sstream>
#include <string>
#include "base/gtest/cur_tick_fake.hh"
#include "base/gtest/logging.hh"
#include "base/named.hh"
#include "base/trace.hh"
using namespace gem5;
// In test SetGetLogger this logger will be assigned to be the one returned
// by Tracer::getDebugLogger(). All tests before that test should assume
// that getDebugLogger() returns a cerr-based logger, and all tests after
// that test should assume that this logger is returned
std::stringstream ss;
trace::OstreamLogger main_logger(ss);
// Instantiate the mock class to have a valid curTick of 0
GTestTickHandler tickHandler;
namespace gem5
{
namespace debug
{
/** Debug flag used for the tests in this file. */
SimpleFlag TraceTestDebugFlag("TraceTestDebugFlag",
"Exclusive debug flag for the trace tests");
} // namespace debug
} // namespace gem5
/** @return The ostream as a std::string. */
std::string
getString(std::ostream &os)
{
auto buf = os.rdbuf();
std::ostringstream oss;
oss << buf;
return oss.str();
}
/** @return The logger's ostream as a std::string. */
std::string
getString(trace::Logger *logger)
{
return getString(logger->getOstream());
}
/** Test creating a simple log message. */
TEST(TraceTest, LogSimpleMessage)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.logMessage(Tick(100), "", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Test message");
}
/** Test creating a simple log message with a name. */
TEST(TraceTest, LogMessageName)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
}
/** Test that when the tick is set to MaxTick it is not printed. */
TEST(TraceTest, LogMessageMaxTick)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.logMessage(MaxTick, "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), "Foo: Test message");
}
/** Test that by default the flag is not printed. */
TEST(TraceTest, LogMessageFlagDisabled)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.logMessage(Tick(100), "Foo", "Bar", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
}
/**
* Test creating a simple log message without tick information and that
* enabling and disabling format flags work.
*/
TEST(TraceTest, LogMessageTickDisabledAndEnableDisable)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
trace::enable();
EXPECT_TRUE(debug::changeFlag("FmtTicksOff", true));
logger.logMessage(Tick(200), "Foo", "", "Test message");
#if TRACING_ON
ASSERT_EQ(getString(&logger), "Foo: Test message");
#else
ASSERT_EQ(getString(&logger), " 200: Foo: Test message");
#endif
debug::changeFlag("FmtTicksOff", false);
trace::disable();
logger.logMessage(Tick(300), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 300: Foo: Test message");
}
/**
* Test creating a full log message to verify expected order of appearance.
* This does not include the backtrace.
*/
TEST(TraceTest, LogMessageFlagEnabled)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
trace::enable();
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
logger.logMessage(Tick(100), "Foo", "Bar", "Test message");
#if TRACING_ON
ASSERT_EQ(getString(&logger), " 100: Bar: Foo: Test message");
#else
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
#endif
debug::changeFlag("FmtFlag", false);
trace::disable();
}
/** Test that log messages are displayed for activated objects (single). */
TEST(TraceTest, LogMessageActivateOne)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch activate_foo("Foo");
ObjectMatch activate_bar("Bar");
// Activate foo.
logger.setActivate(activate_foo);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), "");
// When setting a new activate, the old activates are not kept.
logger.setActivate(activate_bar);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), "");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Bar: Test message");
}
/** Test that log messages are displayed for activated objects (multiple). */
TEST(TraceTest, LogMessageActivateMultiple)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch activate_foo("Foo");
ObjectMatch activate_bar("Bar");
ObjectMatch activate_thy("Thy");
// Activate foo and bar
logger.setActivate(activate_foo);
logger.addActivate(activate_bar);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Bar: Test message");
logger.logMessage(Tick(100), "Thy", "", "Test message");
ASSERT_EQ(getString(&logger), "");
// Make sure that when setting a new activate, the old activates
// are not kept
logger.setActivate(activate_thy);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), "");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), "");
logger.logMessage(Tick(100), "Thy", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Thy: Test message");
}
/** Test that log messages are not displayed for ignored objects (single). */
TEST(TraceTest, LogMessageIgnoreOne)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch ignore_foo("Foo");
ObjectMatch ignore_bar("Bar");
// Ignore foo
logger.setIgnore(ignore_foo);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), "");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Bar: Test message");
// Make sure that when setting a new ignore the old ignores are not kept
logger.setIgnore(ignore_bar);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), "");
}
/** Test that log messages are not displayed for ignored objects (multiple). */
TEST(TraceTest, LogMessageIgnoreMultiple)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch ignore_foo("Foo");
ObjectMatch ignore_bar("Bar");
ObjectMatch ignore_thy("Thy");
// Ignore foo and bar
logger.setIgnore(ignore_foo);
logger.addIgnore(ignore_bar);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), "");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), "");
logger.logMessage(Tick(100), "Thy", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Thy: Test message");
// Make sure that when setting a new ignore, the old sub-ignores
// are not kept
logger.setIgnore(ignore_thy);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Bar: Test message");
logger.logMessage(Tick(100), "Thy", "", "Test message");
ASSERT_EQ(getString(&logger), "");
}
/** Test that log messages are displayed properly within ignore and activate */
TEST(TraceTest, LogMessageActivateAndIgnore)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch foo("Foo");
ObjectMatch bar("Bar");
// Activate foo and ignore bar
logger.setActivate(foo);
logger.setIgnore(bar);
logger.logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
logger.logMessage(Tick(100), "Bar", "", "Test message");
ASSERT_EQ(getString(&logger), "");
logger.logMessage(Tick(100), "Thy", "", "Test message");
// When the Activate list is not empty and thy is not in the list,
// log of Thy will not be displayed.
ASSERT_EQ(getString(&logger), "");
}
/** Test that dumping for an ignored name does not log anything. */
TEST(TraceTest, DumpIgnored)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch ignore_foo("Foo");
logger.setIgnore(ignore_foo);
std::string message = "Test message";
logger.dump(Tick(100), "Foo", message.c_str(), message.size(), "");
ASSERT_EQ(getString(&logger), "");
}
/**
* Test that a regular dump will change the message so that it contains both
* the hex and char representation of every byte. There is a space between
* every 8 bytes. For each 16-byte line of a message the order of appearance is
* <byte number> <2 spaces> <8 spaced bytes> <1 space> <8 spaced bytes>
* <3-spaces missing to fill 16 bytes> <1 space> <16 bytes as chars> <\n>
*/
TEST(TraceTest, DumpSimple)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
trace::enable();
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
std::string message = "Test message";
logger.dump(Tick(100), "Foo", message.c_str(), message.size(), "Bar");
#if TRACING_ON
ASSERT_EQ(getString(&logger),
// logMessage prefix
" 100: Bar: Foo: "
// Byte number + 2 spaces
"00000000 "
// 8 bytes + 1 space + 4 bytes + ((16 - 12) * 3) spaces
"54 65 73 74 20 6d 65 73 73 61 67 65 "
// 1 space + 12 chars + \n
" Test message\n");
#else
ASSERT_EQ(getString(&logger),
// logMessage prefix
" 100: Foo: "
// Byte number + 2 spaces
"00000000 "
// 8 bytes + 1 space + 4 bytes + ((16 - 12) * 3) spaces
"54 65 73 74 20 6d 65 73 73 61 67 65 "
// 1 space + 12 chars + \n
" Test message\n");
#endif
debug::changeFlag("FmtFlag", false);
trace::disable();
}
/**
* Test that a regular dump will change the message so that it contains both
* the hex and char representation of every byte, for a multi-line message.
*/
TEST(TraceTest, DumpMultiLine)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
std::string message =
"This is a very long line that will span over multiple lines";
logger.dump(Tick(100), "Foo", message.c_str(), message.size(), "");
ASSERT_EQ(getString(&logger),
" 100: Foo: 00000000 "
"54 68 69 73 20 69 73 20 61 20 76 65 72 79 20 6c This is a very l\n"
" 100: Foo: 00000010 "
"6f 6e 67 20 6c 69 6e 65 20 74 68 61 74 20 77 69 ong line that wi\n"
" 100: Foo: 00000020 "
"6c 6c 20 73 70 61 6e 20 6f 76 65 72 20 6d 75 6c ll span over mul\n"
" 100: Foo: 00000030 "
"74 69 70 6c 65 20 6c 69 6e 65 73 tiple lines\n");
}
/**
* Test that when no logger exists a logger is created redirecting to cerr.
* This is the only test that uses cerr. All other test will use main_logger.
*/
TEST(TraceTest, DISABLED_GetNullLogger)
{
trace::Logger *logger = trace::getDebugLogger();
ASSERT_FALSE(logger == nullptr);
gtestLogOutput.str("");
logger->logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(gtestLogOutput.str(), " 100: Foo: Test message");
}
/** Test that the logger is set properly. */
TEST(TraceTest, SetGetLogger)
{
// NOTE: From now on getDebugLogger will use main_logger to avoid
// having to check cerr. This assumes that tests are run in the order
// they appear from line 1 to the last line of this file.
trace::setDebugLogger(&main_logger);
// Set message with local variable, and retrieve the string with
// the debug-logger getter
main_logger.logMessage(Tick(100), "Foo", "", "Test message");
auto logger_from_getter = trace::getDebugLogger();
ASSERT_EQ(getString(logger_from_getter), " 100: Foo: Test message");
}
/** Test that output() gets the ostream of the current debug logger. */
TEST(TraceTest, Output)
{
trace::getDebugLogger()->logMessage(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(trace::output()), " 100: Foo: Test message");
}
/** Test dprintf_flag with ignored name. */
TEST(TraceTest, DprintfFlagIgnore)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch ignore_foo("Foo");
logger.setIgnore(ignore_foo);
logger.dprintf_flag(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), "");
}
/** Test dprintf_flag with zero args. */
TEST(TraceTest, DprintfFlagZeroArgs)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.dprintf_flag(Tick(100), "Foo", "", "Test message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
}
/** Test dprintf_flag with one arg. */
TEST(TraceTest, DprintfFlagOneArg)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.dprintf_flag(Tick(100), "Foo", "", "Test %s", "message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
}
/** Test dprintf_flag with multiple args. */
TEST(TraceTest, DprintfFlagMultipleArgs)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
logger.dprintf_flag(Tick(100), "Foo", "", "Test %s %c %d %x",
"message", 'A', 217, 0x30);
ASSERT_EQ(getString(&logger), " 100: Foo: Test message A 217 30");
}
/** Test dprintf_flag with flag. */
TEST(TraceTest, DprintfFlagEnabled)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
trace::enable();
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
logger.dprintf_flag(Tick(100), "Foo", "Bar", "Test %s", "message");
#if TRACING_ON
ASSERT_EQ(getString(&logger), " 100: Bar: Foo: Test message");
#else
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
#endif
debug::changeFlag("FmtFlag", false);
trace::disable();
}
/** Test dprintf with ignored name. */
TEST(TraceTest, DprintfIgnore)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
ObjectMatch ignore_foo("Foo");
logger.setIgnore(ignore_foo);
logger.dprintf(Tick(100), "Foo", "Test message");
ASSERT_EQ(getString(&logger), "");
}
/** Test that dprintf does not have a flag. */
TEST(TraceTest, DprintfEnabled)
{
std::stringstream ss;
trace::OstreamLogger logger(ss);
trace::enable();
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
logger.dprintf(Tick(100), "Foo", "Test %s", "message");
ASSERT_EQ(getString(&logger), " 100: Foo: Test message");
debug::changeFlag("FmtFlag", false);
trace::disable();
}
/** Test that dprintf is just a flagless wrapper for dprintf_flag. */
TEST(TraceTest, DprintfWrapper)
{
std::stringstream ss, ss_flag;
trace::OstreamLogger logger(ss);
trace::OstreamLogger logger_flag(ss_flag);
logger.dprintf(Tick(100), "Foo", "Test %s %c %d %x",
"message", 'A', 217, 0x30);
logger_flag.dprintf_flag(Tick(100), "Foo", "", "Test %s %c %d %x",
"message", 'A', 217, 0x30);
ASSERT_EQ(getString(&logger), getString(&logger_flag));
}
/** Test DDUMP with tracing on. */
TEST(TraceTest, MacroDDUMP)
{
StringWrap name("Foo");
std::string message = "Test message";
// Flag enabled
trace::enable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", true));
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
DDUMP(TraceTestDebugFlag, message.c_str(), message.size());
#if TRACING_ON
ASSERT_EQ(getString(trace::output()),
" 0: TraceTestDebugFlag: Foo: 00000000 "
"54 65 73 74 20 6d 65 73 73 61 67 65 Test message\n");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
// Flag disabled
trace::disable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", false));
DDUMP(TraceTestDebugFlag, message.c_str(), message.size());
ASSERT_EQ(getString(trace::output()), "");
}
/** Test DPRINTF with tracing on. */
TEST(TraceTest, MacroDPRINTF)
{
StringWrap name("Foo");
// Flag enabled
trace::enable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", true));
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
DPRINTF(TraceTestDebugFlag, "Test message");
#if TRACING_ON
ASSERT_EQ(getString(trace::output()),
" 0: TraceTestDebugFlag: Foo: Test message");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
// Flag disabled
trace::disable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", false));
DPRINTF(TraceTestDebugFlag, "Test message");
ASSERT_EQ(getString(trace::output()), "");
}
/** Test DPRINTFS with tracing on. */
TEST(TraceTest, MacroDPRINTFS)
{
Named named("Foo");
#if TRACING_ON
Named *named_ptr = &named;
#endif
// Flag enabled
trace::enable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", true));
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
#if TRACING_ON
DPRINTFS(TraceTestDebugFlag, named_ptr, "Test message");
ASSERT_EQ(getString(trace::output()),
" 0: TraceTestDebugFlag: Foo: Test message");
#endif
// Flag disabled
trace::disable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", false));
#if TRACING_ON
DPRINTFS(TraceTestDebugFlag, named_ptr, "Test message");
ASSERT_EQ(getString(trace::output()), "");
#endif
}
/** Test DPRINTFR with tracing on. */
TEST(TraceTest, MacroDPRINTFR)
{
// Flag enabled
trace::enable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", true));
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
DPRINTFR(TraceTestDebugFlag, "Test message");
#if TRACING_ON
ASSERT_EQ(getString(trace::output()), "TraceTestDebugFlag: Test message");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
// Flag disabled
trace::disable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", false));
DPRINTFR(TraceTestDebugFlag, "Test message");
ASSERT_EQ(getString(trace::output()), "");
}
/** Test DPRINTFN with tracing on. */
TEST(TraceTest, MacroDPRINTFN)
{
StringWrap name("Foo");
DPRINTFN("Test message");
#if TRACING_ON
ASSERT_EQ(getString(trace::output()), " 0: Foo: Test message");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
}
/** Test DPRINTFNR with tracing on. */
TEST(TraceTest, MacroDPRINTFNR)
{
DPRINTFNR("Test message");
#if TRACING_ON
ASSERT_EQ(getString(trace::output()), "Test message");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
}
/** Test DPRINTF_UNCONDITIONAL with tracing on. */
TEST(TraceTest, MacroDPRINTF_UNCONDITIONAL)
{
StringWrap name("Foo");
// Flag enabled
trace::enable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", true));
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
DPRINTF_UNCONDITIONAL(TraceTestDebugFlag, "Test message");
#if TRACING_ON
ASSERT_EQ(getString(trace::output()),
" 0: TraceTestDebugFlag: Foo: Test message");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
// Flag disabled
trace::disable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", false));
DPRINTF_UNCONDITIONAL(TraceTestDebugFlag, "Test message");
#if TRACING_ON
ASSERT_EQ(getString(trace::output()), " 0: Foo: Test message");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
}
/**
* Test that there is a global name() to fall through when a locally scoped
* name() is not defined.
*/
TEST(TraceTest, GlobalName)
{
// Flag enabled
trace::enable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", true));
EXPECT_TRUE(debug::changeFlag("FmtFlag", true));
DPRINTF(TraceTestDebugFlag, "Test message");
#if TRACING_ON
ASSERT_EQ(getString(trace::output()),
" 0: TraceTestDebugFlag: global: Test message");
#else
ASSERT_EQ(getString(trace::output()), "");
#endif
// Flag disabled
trace::disable();
EXPECT_TRUE(debug::changeFlag("TraceTestDebugFlag", false));
DPRINTF(TraceTestDebugFlag, "Test message");
ASSERT_EQ(getString(trace::output()), "");
}