| /* |
| * 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-spi.h> |
| #include <gtest/gtest.h> |
| |
| #include "base/stats/info.hh" |
| |
| using namespace gem5; |
| |
| class TestInfo : public statistics::Info |
| { |
| public: |
| using statistics::Info::Info; |
| |
| int value = 0; |
| |
| bool check() const override { return true; } |
| void prepare() override {} |
| void reset() override { value = 0; } |
| bool zero() const override { return false; } |
| void visit(statistics::Output &visitor) override {} |
| }; |
| |
| /** Test that a name is properly assigned under the new style. */ |
| TEST(StatsInfoTest, NameNewStyle) |
| { |
| TestInfo info; |
| info.setName("InfoNameNewStyle", false); |
| ASSERT_EQ(info.name, "InfoNameNewStyle"); |
| } |
| |
| /** Test that the first character accepts alpha and underscore. */ |
| TEST(StatsInfoTest, NameFirstCharacter) |
| { |
| TestInfo info; |
| info.setName("X", false); |
| ASSERT_EQ(info.name, "X"); |
| |
| TestInfo info2; |
| info2.setName("a", false); |
| ASSERT_EQ(info2.name, "a"); |
| |
| TestInfo info3; |
| info3.setName("_", false); |
| ASSERT_EQ(info3.name, "_"); |
| |
| TestInfo info4; |
| info4.setName("X.Y", false); |
| ASSERT_EQ(info4.name, "X.Y"); |
| |
| TestInfo info5; |
| info5.setName("a.b._.d.e", false); |
| ASSERT_EQ(info5.name, "a.b._.d.e"); |
| } |
| |
| /** Test that the non-first characters accept alpha-numeric and underscore. */ |
| TEST(StatsInfoTest, NameOtherCharacters) |
| { |
| TestInfo info; |
| info.setName("abCde", false); |
| ASSERT_EQ(info.name, "abCde"); |
| |
| TestInfo info2; |
| info2.setName("ab_de", false); |
| ASSERT_EQ(info2.name, "ab_de"); |
| |
| TestInfo info3; |
| info3.setName("ab9de", false); |
| ASSERT_EQ(info3.name, "ab9de"); |
| |
| TestInfo info4; |
| info4.setName("a_bCD12_ef", false); |
| ASSERT_EQ(info4.name, "a_bCD12_ef"); |
| |
| TestInfo info5; |
| info5.setName("a_._bC.D12_ef", false); |
| ASSERT_EQ(info5.name, "a_._bC.D12_ef"); |
| } |
| |
| /** |
| * Test that a name is properly assigned under the old style. The name map |
| * must be checked to make sure it can resolved. |
| */ |
| TEST(StatsInfoTest, NameOldStyle) |
| { |
| TestInfo info; |
| info.setName("InfoNameOldStyle", true); |
| ASSERT_EQ(info.name, "InfoNameOldStyle"); |
| |
| const auto &it = statistics::nameMap().find(info.name); |
| ASSERT_NE(it, statistics::nameMap().cend()); |
| ASSERT_EQ(info.id, it->second->id); |
| } |
| |
| /** |
| * @todo Test the behavior when set name is called twice on the same old-style |
| * info. Should it be allowed? If so, the old name should be removed from the |
| * name map. |
| */ |
| TEST(StatsInfoTest, DISABLED_NameOldStyleTwice) |
| { |
| TestInfo info; |
| std::string old_name = "InfoNameOldStyleTwice"; |
| info.setName(old_name, true); |
| info.setName("InfoNameOldStyleTwice2", true); |
| ASSERT_EQ(info.name, "InfoNameOldStyleTwice2"); |
| |
| const auto &it = statistics::nameMap().find(old_name); |
| ASSERT_EQ(it, statistics::nameMap().cend()); |
| } |
| |
| /** |
| * Test that a name can be duplicated when using the new styles. Duplicating |
| * is not a problem that must be solved by Info in this case. The stats name |
| * resolver does that. |
| */ |
| TEST(StatsInfoTest, NameNewStyleDuplicate) |
| { |
| TestInfo info; |
| std::string name = "InfoNameNewStyleDuplicate"; |
| info.setName(name, false); |
| EXPECT_EQ(info.name, name); |
| |
| TestInfo info2; |
| info2.setName(name, false); |
| ASSERT_EQ(info2.name, name); |
| } |
| |
| /** |
| * Test that a name can be duplicated when mixing styles. Duplicating |
| * is not a problem that must be solved by Info in this case. The stats |
| * name resolver does that. |
| */ |
| TEST(StatsInfoTest, NameMixStyleDuplicate) |
| { |
| TestInfo info; |
| std::string name = "InfoNameMixStyleDuplicate"; |
| info.setName(name, false); |
| EXPECT_EQ(info.name, name); |
| |
| TestInfo info2; |
| info2.setName(name, true); |
| ASSERT_EQ(info2.name, name); |
| } |
| |
| /** Test changing the separator. */ |
| TEST(StatsInfoTest, Separator) |
| { |
| TestInfo info; |
| |
| // Get current separator |
| auto separator = info.separatorString; |
| |
| // Do the test with EXPECT_ so that we can restore the separator later |
| info.setSeparator(",-=-,"); |
| EXPECT_EQ(statistics::Info::separatorString, ",-=-,"); |
| |
| // Restore separator |
| info.setSeparator(separator); |
| } |
| |
| /** Test changing the less operation, which is applied on the name. */ |
| TEST(StatsInfoTest, Less) |
| { |
| TestInfo info; |
| info.setName("Less1"); |
| TestInfo info2; |
| info2.setName("Less2"); |
| |
| ASSERT_TRUE(statistics::Info::less(&info, &info2)); |
| ASSERT_FALSE(statistics::Info::less(&info2, &info)); |
| } |
| |
| /** Test that checking Info after setting the init flag succeeds. */ |
| TEST(StatsInfoTest, BaseCheckInit) |
| { |
| TestInfo info; |
| info.flags.set(statistics::init); |
| ASSERT_TRUE(info.baseCheck()); |
| } |
| |
| /** Test that checking Info for display after setting the name succeeds. */ |
| TEST(StatsInfoTest, BaseCheckDisplay) |
| { |
| TestInfo info; |
| info.setName("BaseCheckDisplay"); |
| info.flags.set(statistics::init | statistics::display); |
| ASSERT_TRUE(info.baseCheck()); |
| } |
| |
| /** |
| * Test changing the less operation, which is applied on the name (sub-groups). |
| */ |
| TEST(StatsInfoTest, LessSub) |
| { |
| TestInfo info; |
| info.setName("Less.Sub2.a"); |
| TestInfo info2; |
| info2.setName("Less.Sub1.b"); |
| |
| ASSERT_TRUE(statistics::Info::less(&info2, &info)); |
| ASSERT_FALSE(statistics::Info::less(&info, &info2)); |
| } |
| |
| /** Test that a name cannot be empty. */ |
| TEST(StatsInfoDeathTest, NameEmpty) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("", false)); |
| } |
| |
| /** Test that a sub-group's name cannot be empty. */ |
| TEST(StatsInfoDeathTest, NameSubEmpty) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName(".a", false)); |
| } |
| |
| /** Test that a sub-group's name cannot be empty. */ |
| TEST(StatsInfoDeathTest, NameSubEmpty2) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("A.", false)); |
| } |
| |
| /** Test that a sub-group's name cannot be empty. */ |
| TEST(StatsInfoDeathTest, NameSubEmpty3) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("a.b..c", false)); |
| } |
| |
| /** Test that the first character does not accept numbers. */ |
| TEST(StatsInfoDeathTest, NameFirstCharacterNumber) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("1", false)); |
| } |
| |
| /** Test that the first character does not accept numbers (sub-group). */ |
| TEST(StatsInfoDeathTest, NameFirstCharacterNumberSub) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("A.1", false)); |
| } |
| |
| /** Test that the first character does not accept special characters. */ |
| TEST(StatsInfoDeathTest, NameFirstCharacterSpecial) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("!", false)); |
| } |
| |
| /** |
| * Test that the first character does not accept special characters |
| * (sub-group). |
| */ |
| TEST(StatsInfoDeathTest, NameFirstCharacterSpecialSub) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("A.!", false)); |
| } |
| |
| /** Test that the non-first characters do not accept special characters. */ |
| TEST(StatsInfoDeathTest, NameOtherCharacterSpecial) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.setName("ab!de", false)); |
| } |
| |
| /** Test that a name cannot be duplicated under the old style. */ |
| TEST(StatsInfoDeathTest, NameOldStyleDuplicate) |
| { |
| TestInfo info; |
| std::string name = "InfoNameOldStyleDuplicate"; |
| info.setName(name, true); |
| EXPECT_EQ(info.name, name); |
| |
| TestInfo info2; |
| ASSERT_ANY_THROW(info2.setName(name, true)); |
| } |
| |
| /** Test that checking Info without setting the init flag fails. */ |
| TEST(StatsInfoDeathTest, BaseCheckNoInit) |
| { |
| TestInfo info; |
| ASSERT_ANY_THROW(info.baseCheck()); |
| } |
| |
| /** Test that checking Info for display without setting the name fails. */ |
| TEST(StatsInfoDeathTest, BaseCheckDisplayNoName) |
| { |
| TestInfo info; |
| info.flags.set(statistics::init | statistics::display); |
| ASSERT_ANY_THROW(info.baseCheck()); |
| } |