blob: f3d9e0717c830362d3623bbada313c44d87fec38 [file] [log] [blame]
/*
* Copyright (c) 2020 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 "base/debug.hh"
#include "base/gtest/logging.hh"
using namespace gem5;
/** Test assignment of names and descriptions. */
TEST(DebugFlagTest, NameDesc)
{
debug::SimpleFlag flag_a("FlagNameDescTestKidA", "Kid A");
EXPECT_EQ("FlagNameDescTestKidA", flag_a.name());
EXPECT_EQ("Kid A", flag_a.desc());
debug::SimpleFlag flag_b("FlagNameDescTestKidB", "Kid B");
EXPECT_EQ("FlagNameDescTestKidB", flag_b.name());
EXPECT_EQ("Kid B", flag_b.desc());
debug::CompoundFlag compound_flag("FlagNameDescTest", "Compound Flag",
{&flag_a, &flag_b});
EXPECT_EQ("FlagNameDescTest", compound_flag.name());
EXPECT_EQ("Compound Flag", compound_flag.desc());
}
/** Test that names are unique. */
TEST(DebugFlagDeathTest, UniqueNames)
{
debug::SimpleFlag flag("FlagUniqueNamesTest", "A");
gtestLogOutput.str("");
EXPECT_ANY_THROW(debug::SimpleFlag("FlagUniqueNamesTest", "B"));
const std::string expected = "panic: panic condition !result.second "
"occurred: Flag FlagUniqueNamesTest already defined!\n";
std::string actual = gtestLogOutput.str();
EXPECT_EQ(expected, actual);
}
/** Test format attribute. */
TEST(DebugFlagTest, IsFormat)
{
debug::SimpleFlag flag_a("FlagIsFormatTestA", "", true);
EXPECT_TRUE(flag_a.isFormat());
debug::SimpleFlag flag_b("FlagIsFormatTestB", "", false);
EXPECT_FALSE(flag_b.isFormat());
debug::SimpleFlag flag_c("FlagIsFormatTestC", "");
EXPECT_FALSE(flag_c.isFormat());
}
/** Test enabling and disabling simple flags, as well as the global enabler. */
TEST(DebugSimpleFlagTest, Enabled)
{
debug::Flag::globalDisable();
debug::SimpleFlag flag("SimpleFlagEnabledTest", "");
// By default flags are initialized disabled
ASSERT_FALSE(flag.tracing());
// Flags must be globally enabled before individual flags are enabled
flag.enable();
ASSERT_FALSE(flag.tracing());
debug::Flag::globalEnable();
ASSERT_TRUE(!TRACING_ON || flag.tracing());
// Verify that the global enabler works
debug::Flag::globalDisable();
ASSERT_FALSE(flag.tracing());
debug::Flag::globalEnable();
ASSERT_TRUE(!TRACING_ON || flag.tracing());
// Test disabling the flag with global enabled
flag.disable();
ASSERT_FALSE(flag.tracing());
}
/**
* Tests that manipulate the enablement status of the compound flag to change
* the corresponding status of the kids.
*/
TEST(DebugCompoundFlagTest, Enabled)
{
debug::Flag::globalDisable();
debug::SimpleFlag flag_a("CompoundFlagEnabledTestKidA", "");
debug::SimpleFlag flag_b("CompoundFlagEnabledTestKidB", "");
debug::CompoundFlag flag("CompoundFlagEnabledTest", "",
{&flag_a, &flag_b});
// By default flags are initialized disabled
ASSERT_FALSE(flag.tracing());
// Flags must be globally enabled before individual flags are enabled
flag.enable();
ASSERT_FALSE(flag_a.tracing());
ASSERT_FALSE(flag_b.tracing());
ASSERT_FALSE(flag.tracing());
debug::Flag::globalEnable();
for (auto &kid : flag.kids()) {
ASSERT_TRUE(!TRACING_ON || kid->tracing());
}
ASSERT_TRUE(!TRACING_ON || flag_a.tracing());
ASSERT_TRUE(!TRACING_ON || flag_b.tracing());
// Test disabling the flag with global enabled
flag.disable();
for (auto &kid : flag.kids()) {
ASSERT_FALSE(kid->tracing());
}
ASSERT_FALSE(flag_a.tracing());
ASSERT_FALSE(flag_b.tracing());
ASSERT_FALSE(flag.tracing());
}
/** Test that the conversion operator matches the enablement status. */
TEST(DebugFlagTest, ConversionOperator)
{
debug::Flag::globalEnable();
debug::SimpleFlag flag("FlagConversionOperatorTest", "");
ASSERT_EQ(flag, flag.tracing());
flag.enable();
ASSERT_EQ(flag, flag.tracing());
flag.disable();
}
/**
* Tests that manipulate the kids to change the enablement status of the
* compound flag.
*/
TEST(DebugCompoundFlagTest, EnabledKids)
{
debug::Flag::globalEnable();
debug::SimpleFlag flag_a("CompoundFlagEnabledKidsTestKidA", "");
debug::SimpleFlag flag_b("CompoundFlagEnabledKidsTestKidB", "");
debug::CompoundFlag flag("CompoundFlagEnabledKidsTest", "",
{&flag_a, &flag_b});
// Test enabling only flag A
ASSERT_FALSE(flag_a.tracing());
ASSERT_FALSE(flag_b.tracing());
ASSERT_FALSE(flag.tracing());
flag_a.enable();
ASSERT_TRUE(!TRACING_ON || flag_a.tracing());
ASSERT_FALSE(flag_b.tracing());
ASSERT_FALSE(flag.tracing());
// Test that enabling both flags enables the compound flag
ASSERT_TRUE(!TRACING_ON || flag_a.tracing());
ASSERT_FALSE(flag_b.tracing());
ASSERT_FALSE(flag.tracing());
flag_b.enable();
ASSERT_TRUE(!TRACING_ON || flag_a.tracing());
ASSERT_TRUE(!TRACING_ON || flag_b.tracing());
// Test that disabling one of the flags disables the compound flag
flag_a.disable();
ASSERT_FALSE(flag_a.tracing());
ASSERT_TRUE(!TRACING_ON || flag_b.tracing());
ASSERT_FALSE(flag.tracing());
}
/** Search for existent and non-existent flags. */
TEST(DebugFlagTest, FindFlag)
{
debug::Flag::globalEnable();
debug::SimpleFlag flag_a("FlagFindFlagTestA", "");
debug::SimpleFlag flag_b("FlagFindFlagTestB", "");
// Enable the found flags and verify that the original flags are
// enabled too
debug::Flag *flag;
EXPECT_TRUE(flag = debug::findFlag("FlagFindFlagTestA"));
ASSERT_FALSE(flag_a.tracing());
flag->enable();
ASSERT_TRUE(!TRACING_ON || flag_a.tracing());
EXPECT_TRUE(flag = debug::findFlag("FlagFindFlagTestB"));
ASSERT_FALSE(flag_b.tracing());
flag->enable();
ASSERT_TRUE(!TRACING_ON || flag_b.tracing());
// Search for a non-existent flag
EXPECT_FALSE(debug::findFlag("FlagFindFlagTestC"));
}
/** Test changing flag enabled. */
TEST(DebugFlagTest, ChangeFlag)
{
debug::Flag::globalEnable();
debug::SimpleFlag flag_a("FlagChangeFlagTestA", "");
debug::SimpleFlag flag_b("FlagChangeFlagTestB", "");
// Enable the found flags and verify that the original flags are
// enabled too
ASSERT_FALSE(flag_a.tracing());
EXPECT_TRUE(debug::changeFlag("FlagChangeFlagTestA", true));
ASSERT_TRUE(!TRACING_ON || flag_a.tracing());
EXPECT_TRUE(debug::changeFlag("FlagChangeFlagTestA", false));
ASSERT_FALSE(flag_a.tracing());
// Disable and enable a flag
ASSERT_FALSE(flag_b.tracing());
EXPECT_TRUE(debug::changeFlag("FlagChangeFlagTestB", false));
ASSERT_FALSE(flag_b.tracing());
EXPECT_TRUE(debug::changeFlag("FlagChangeFlagTestB", true));
ASSERT_TRUE(!TRACING_ON || flag_b.tracing());
// Change a non-existent flag
ASSERT_FALSE(debug::changeFlag("FlagChangeFlagTestC", true));
}
/** Test changing flag enabled with aux functions. */
TEST(DebugFlagTest, SetClearDebugFlag)
{
debug::Flag::globalEnable();
debug::SimpleFlag flag_a("FlagSetClearDebugFlagTestA", "");
debug::SimpleFlag flag_b("FlagSetClearDebugFlagTestB", "");
// Enable and disable a flag
ASSERT_FALSE(flag_a.tracing());
setDebugFlag("FlagSetClearDebugFlagTestA");
ASSERT_TRUE(!TRACING_ON || flag_a.tracing());
clearDebugFlag("FlagSetClearDebugFlagTestA");
ASSERT_FALSE(flag_a.tracing());
// Disable and enable a flag
ASSERT_FALSE(flag_b.tracing());
clearDebugFlag("FlagSetClearDebugFlagTestB");
ASSERT_FALSE(flag_b.tracing());
setDebugFlag("FlagSetClearDebugFlagTestB");
ASSERT_TRUE(!TRACING_ON || flag_b.tracing());
// Change a non-existent flag
setDebugFlag("FlagSetClearDebugFlagTestC");
clearDebugFlag("FlagSetClearDebugFlagTestC");
}
/** Test dumping no enabled debug flags. */
TEST(DebugFlagTest, NoDumpDebugFlags)
{
debug::Flag::globalEnable();
debug::SimpleFlag flag("FlagDumpDebugFlagTest", "");
// Verify that the names of the enabled flags are printed
gtestLogOutput.str("");
dumpDebugFlags();
std::string output = gtestLogOutput.str();
EXPECT_EQ(output, "");
ASSERT_FALSE(flag.tracing());
}
/** Test dumping enabled debug flags with a larger set of flags. */
TEST(DebugFlagTest, DumpDebugFlags)
{
debug::Flag::globalEnable();
debug::SimpleFlag flag_a("FlagDumpDebugFlagTestA", "");
debug::SimpleFlag flag_b("FlagDumpDebugFlagTestB", "");
debug::SimpleFlag flag_c("FlagDumpDebugFlagTestC", "");
debug::SimpleFlag flag_d("FlagDumpDebugFlagTestD", "");
debug::SimpleFlag flag_e("FlagDumpDebugFlagTestE", "");
debug::CompoundFlag compound_flag_a("CompoundFlagDumpDebugFlagTestA", "",
{&flag_d});
debug::CompoundFlag compound_flag_b("CompoundFlagDumpDebugFlagTestB", "",
{&flag_e});
// Enable a few flags
ASSERT_FALSE(flag_a.tracing());
ASSERT_FALSE(flag_b.tracing());
ASSERT_FALSE(flag_c.tracing());
ASSERT_FALSE(flag_d.tracing());
ASSERT_FALSE(flag_e.tracing());
flag_a.enable();
flag_c.enable();
compound_flag_b.enable();
// Verify that the names of the enabled flags are printed if TRACING_ON.
if (TRACING_ON) {
std::ostringstream os;
dumpDebugFlags(os);
std::string output = os.str();
EXPECT_EQ(output, "FlagDumpDebugFlagTestA\nFlagDumpDebugFlagTestC\n" \
"FlagDumpDebugFlagTestE\n");
}
}