Files
gem5/src/base/str.test.cc
Daniel R. Carvalho 974a47dfb9 misc: Adopt the gem5 namespace
Apply the gem5 namespace to the codebase.

Some anonymous namespaces could theoretically be removed,
but since this change's main goal was to keep conflicts
at a minimum, it was decided not to modify much the
general shape of the files.

A few missing comments of the form "// namespace X" that
occurred before the newly added "} // namespace gem5"
have been added for consistency.

std out should not be included in the gem5 namespace, so
they weren't.

ProtoMessage has not been included in the gem5 namespace,
since I'm not familiar with how proto works.

Regarding the SystemC files, although they belong to gem5,
they actually perform integration between gem5 and SystemC;
therefore, it deserved its own separate namespace.

Files that are automatically generated have been included
in the gem5 namespace.

The .isa files currently are limited to a single namespace.
This limitation should be later removed to make it easier
to accomodate a better API.

Regarding the files in util, gem5:: was prepended where
suitable. Notice that this patch was tested as much as
possible given that most of these were already not
previously compiling.

Change-Id: Ia53d404ec79c46edaa98f654e23bc3b0e179fe2d
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/46323
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Reviewed-by: Matthew Poremba <matthew.poremba@amd.com>
Tested-by: kokoro <noreply+kokoro@google.com>
2021-07-01 19:08:24 +00:00

548 lines
14 KiB
C++

/*
* Copyright (c) 2019 The Regents of the University of California
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* 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 <cstdint>
#include "base/str.hh"
using namespace gem5;
/*
* str.cc has "eat_lead_white", "eat_end_white", and "eat_white" fucntions to
* remove leading and trailing whitespace. The following tests verify this
* behavior.
*/
TEST(StrTest, EatLeadWhite)
{
std::string val = " hello there ";
eat_lead_white(val);
EXPECT_EQ("hello there ", val);
}
TEST(StrTest, EatLeadWhiteNoLeadingWhitespace)
{
std::string val = "hello there ";
eat_lead_white(val);
EXPECT_EQ("hello there ", val);
}
TEST(StrTest, EatEndWhite)
{
std::string val = " hello there ";
eat_end_white(val);
EXPECT_EQ(" hello there", val);
}
TEST(StrTest, EatEndWhiteNoTrailingWhitespace)
{
std::string val = " hello there";
eat_end_white(val);
EXPECT_EQ(" hello there", val);
}
TEST(StrTest, EatWhite)
{
std::string val = " hello there ";
eat_white(val);
EXPECT_EQ("hello there", val);
}
TEST(StrTest, EatWhiteNoWhitespace)
{
std::string val = "hello there";
eat_lead_white(val);
EXPECT_EQ("hello there", val);
}
/*
* This tests checks that str.cc's "to_lower" function converts a string to
* lowercase.
*/
TEST(StrTest, ToLower)
{
std::string val = "gOoDbYe FOO@barr!";
EXPECT_EQ("goodbye foo@barr!", to_lower(val));
}
/*
* str.cc's "split_first" and "split_last" fucntions split a string on a
* character into two parts. "split_first" splits on the first instance of
* this character and "split_last" splits on the last instance of this
* character. The character itself is not included in either of the output
* right-hand side and left-hand side strings. If the character cannot be
* found in the string then the left-hand side string is equal to the input
* string and the right-hand side string is empty.
*/
TEST(StrTest, SplitFirst)
{
std::string val = "abcdefg abcdefg";
std::string lhs;
std::string rhs;
split_first(val , lhs, rhs, 'f');
EXPECT_EQ("abcdefg abcdefg", val);
EXPECT_EQ("abcde", lhs);
EXPECT_EQ("g abcdefg", rhs);
}
TEST(StrTest, SplitFirstNoChar)
{
std::string val = "abcdefg abcdefg";
std::string lhs;
std::string rhs;
split_first(val , lhs, rhs, 'h');
EXPECT_EQ("abcdefg abcdefg", val);
EXPECT_EQ("abcdefg abcdefg", lhs);
EXPECT_EQ("", rhs);
}
TEST(StrTest, SplitFirstOnFirstChar)
{
std::string val = "abcdefg abcdefg";
std::string lhs;
std::string rhs;
split_first(val , lhs, rhs, 'a');
EXPECT_EQ("abcdefg abcdefg", val);
EXPECT_EQ("", lhs);
EXPECT_EQ("bcdefg abcdefg", rhs);
}
TEST(StrTest, SplitLast)
{
std::string val = "abcdefg abcdefg";
std::string lhs;
std::string rhs;
split_last(val , lhs, rhs, 'f');
EXPECT_EQ("abcdefg abcdefg", val);
EXPECT_EQ("abcdefg abcde", lhs);
EXPECT_EQ("g", rhs);
}
TEST(StrTest, SplitLastNoChar)
{
std::string val = "abcdefg abcdefg";
std::string lhs;
std::string rhs;
split_last(val , lhs, rhs, 'h');
EXPECT_EQ("abcdefg abcdefg", val);
EXPECT_EQ("abcdefg abcdefg", lhs);
EXPECT_EQ("", rhs);
}
TEST(StrTest, SplitLastOnLastChar)
{
std::string val = "abcdefg abcdefg";
std::string lhs;
std::string rhs;
split_last(val , lhs, rhs, 'g');
EXPECT_EQ("abcdefg abcdefg", val);
EXPECT_EQ("abcdefg abcdef", lhs);
EXPECT_EQ("", rhs);
}
/*
* str.cc's "tokenize" function splits a string into its constituent tokens.
* It splits based on an input character.
*/
TEST(StrTest, TokenizeOnSpace)
{
/*
* val has a double space between each token with trailing and leading
* whitespace.
*/
std::string val = " Hello, this is a sentence. ";
std::vector<std::string> tokens;
/*
* By default 'ign' is true. This means empty tokens are not included in
* the output list.
*/
tokenize(tokens, val, ' ');
EXPECT_EQ(" Hello, this is a sentence. ", val);
EXPECT_EQ(5, tokens.size());
EXPECT_EQ("Hello,", tokens[0]);
EXPECT_EQ("this", tokens[1]);
EXPECT_EQ("is", tokens[2]);
EXPECT_EQ("a", tokens[3]);
EXPECT_EQ("sentence.", tokens[4]);
}
TEST(StrTest, TokenizeOnSpaceIgnFalse)
{
/*
* val has a double space between each token with trailing and leading
* whitespace.
*/
std::string val = " Hello, this is a sentence. ";
std::vector<std::string> tokens;
tokenize(tokens, val, ' ', false);
EXPECT_EQ(" Hello, this is a sentence. ", val);
EXPECT_EQ(11, tokens.size());
EXPECT_EQ("", tokens[0]);
EXPECT_EQ("Hello,", tokens[1]);
EXPECT_EQ("", tokens[2]);
EXPECT_EQ("this", tokens[3]);
EXPECT_EQ("", tokens[4]);
EXPECT_EQ("is", tokens[5]);
EXPECT_EQ("", tokens[6]);
EXPECT_EQ("a", tokens[7]);
EXPECT_EQ("", tokens[8]);
EXPECT_EQ("sentence.", tokens[9]);
EXPECT_EQ("", tokens[10]);
}
TEST(StrTest, TokenizedTokenDoesNotExist)
{
std::string val = "abcdefg";
std::vector<std::string> tokens;
tokenize(tokens, val, 'h');
EXPECT_EQ("abcdefg", val);
EXPECT_EQ(1, tokens.size());
EXPECT_EQ("abcdefg", tokens[0]);
}
/*
* str.cc's "to_number" function converts a string to a number. The function
* will return false if this is not possible either because the string
* represents a number out-of-range, or because the string cannot be parsed.
*/
TEST(StrTest, ToNumber8BitInt)
{
int8_t output;
std::string input = "-128";
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(-128, output);
}
TEST(StrTest, ToNumber8BitIntStringOutOfRange)
{
int8_t output;
std::string input = "-129";
EXPECT_FALSE(to_number(input, output));
}
TEST(StrTest, ToNumber8BitIntInvalidString)
{
int8_t output;
std::string input = "onetwoeight";
EXPECT_FALSE(to_number(input, output));
}
TEST(StrTest, ToNumberUnsigned8BitInt)
{
uint8_t output;
std::string input = "255";
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(255, output);
}
TEST(StrTest, ToNumberUnsigned8BitIntNegative)
{
uint8_t output;
std::string input = "-1";
EXPECT_FALSE(to_number(input, output));
}
/** Test that a double that can be converted to int is always rounded down. */
TEST(StrTest, ToNumberUnsigned8BitIntRoundDown)
{
uint8_t output;
std::string input_1 = "2.99";
EXPECT_TRUE(to_number(input_1, output));
EXPECT_EQ(2, output);
std::string input_2 = "3.99";
EXPECT_TRUE(to_number(input_2, output));
EXPECT_EQ(3, output);
}
/**
* Test that a double can still be converted to int as long as it is below
* the numerical limit + 1.
*/
TEST(StrTest, ToNumber8BitUnsignedLimit)
{
uint8_t output;
std::string input = "255.99";
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(255, output);
}
/**
* Test that a double cannot be converted to int when it passes the numerical
* limit.
*/
TEST(StrTest, ToNumber8BitUnsignedOutOfRange)
{
uint8_t output;
std::string input = "256.99";
EXPECT_FALSE(to_number(input, output));
}
/** Test that a scientific number cannot be converted to int. */
TEST(StrTest, ToNumberUnsignedScientific)
{
uint32_t output;
std::string input = "8.234e+08";
EXPECT_FALSE(to_number(input, output));
}
/** Test that a negative scientific number cannot be converted to int. */
TEST(StrTest, ToNumberIntScientificNegative)
{
int32_t output;
std::string input = "-8.234e+08";
EXPECT_FALSE(to_number(input, output));
}
TEST(StrTest, ToNumber64BitInt)
{
int64_t output;
int64_t input_number = 0xFFFFFFFFFFFFFFFF;
std::string input = std::to_string(input_number);
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(input_number, output);
}
TEST(StrTest, ToNumber64BitIntInvalidString)
{
int64_t output;
std::string input = " ";
EXPECT_FALSE(to_number(input, output));
}
TEST(StrTest, ToNumberEnum)
{
enum Number
{
TWO=2,
};
Number output;
std::string input = "2";
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(TWO, output);
}
/** Test that trying to convert a number to an enum that is not valid fails. */
TEST(StrTest, DISABLED_ToNumberEnumInvalid)
{
enum Number
{
TWO=2,
};
Number output;
std::string input = "3";
EXPECT_FALSE(to_number(input, output));
}
TEST(StrTest, ToNumberFloat)
{
float output;
std::string input = "0.1";
float expected_output = 0.1;
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(expected_output, output);
}
TEST(StrTest, ToNumberFloatIntegerString)
{
float output;
std::string input = "10";
float expected_output = 10.0;
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(expected_output, output);
}
TEST(StrTest, ToNumberFloatNegative)
{
float output;
std::string input = "-0.1";
float expected_output = -0.1;
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(expected_output, output);
}
TEST(StrTest, ToNumberDouble)
{
double output;
std::string input = "0.0001";
double expected_output = 0.0001;
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(expected_output, output);
}
TEST(StrTest, ToNumberDoubleIntegerString)
{
double output;
std::string input = "12345";
double expected_output = 12345.0;
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(expected_output, output);
}
TEST(StrTest, ToNumberDoubleNegative)
{
double output;
std::string input = "-1.2345";
double expected_output = -1.2345;
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(expected_output, output);
}
/** Test that a scientific number is converted properly to double. */
TEST(StrTest, ToNumberScientific)
{
double output;
std::string input = "8.234e+08";
double expected_output = 823400000;
EXPECT_TRUE(to_number(input, output));
EXPECT_EQ(expected_output, output);
}
/*
* The "to_bool" function takes a string, "true" or "false"
* (case-insenstive), and sets the second argument to the bool equivilent.
* The function will return false if it cannot parse the string.
*/
TEST(StrTest, ToBoolTrue)
{
bool output = false;
EXPECT_TRUE(to_bool("TrUe", output));
EXPECT_TRUE(output);
}
TEST(StrTest, ToBoolFalse){
bool output = true;
EXPECT_TRUE(to_bool("fAlSe", output));
EXPECT_FALSE(output);
}
TEST(StrTest, ToBoolInvalidInput)
{
bool output;
EXPECT_FALSE(to_bool("falsify", output));
}
/*
* The "quote" function take a string and returns that string quoted (i.e.,
* between double-quotes) if the string contains a space.
*/
TEST(StrTest, QuoteStringNoSpace)
{
EXPECT_EQ("hello", quote("hello"));
}
TEST(StrTest, QuoteStringWithSpace)
{
EXPECT_EQ("\"hello world\"", quote("hello world"));
}
TEST(StrTest, QuoteQuotedString)
{
/*
* At present, a quoted string can be quoted again.
*/
EXPECT_EQ("\"\"hello world\"\"", quote("\"hello world\""));
}
TEST(StrTest, QuoteStringWithTab)
{
/*
* The "quote" function only works with standard space, not any
* whitepsace.
*/
EXPECT_EQ("hello\tworld", quote("hello\tworld"));
}
/*
* str.hh has three implementations of "startswith"; a function that takes
* string and a prefix and returns true if the string starts with the prefix.
* One implementation takes two strings, another takes two char*, and the
* third takes a string and a char* as a prefix.
*/
TEST(StrTest, StartswithDoubleStringDoesStartWith)
{
std::string s = "Hello, how are you?";
std::string prefix = "Hello";
EXPECT_TRUE(startswith(s, prefix));
}
TEST(StrTest, StartswithDoubleStringDoesNotStartWith)
{
std::string s = "Hello, how are you?";
std::string prefix = "ello";
EXPECT_FALSE(startswith(s, prefix));
}
TEST(StrTest, StartswithDoubleCharArrayDoesStartWith)
{
const char* s = "abcdefg";
const char* prefix = "ab";
EXPECT_TRUE(startswith(s, prefix));
}
TEST(StrTest, StartswithDoubleCharArrayDoesNotStartWith)
{
const char* s = " abcdefg";
const char* prefix = "a";
EXPECT_FALSE(startswith(s, prefix));
}
TEST(StrTest, StartswithStringCharArrayDoesStartWith)
{
std::string s = "foobarr";
const char* prefix = "f";
EXPECT_TRUE(startswith(s, prefix));
}
TEST(StrTest, StartswithStringCharArrayDoesNotStartWith)
{
std::string s = "foobarr";
const char* prefix = "barr";
EXPECT_FALSE(startswith(s, prefix));
}