Change-Id: I73020efd522489ee152af890ab5e03449bc0a900 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/25415 Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
460 lines
12 KiB
C++
460 lines
12 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"
|
|
|
|
/*
|
|
* 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(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, 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);
|
|
}
|
|
|
|
/*
|
|
* 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));
|
|
}
|