blob: a5e446e339756b61d88908b9ea2eaccc76ed9693 [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
#include <map>
#include <set>
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <stout/format.hpp>
#include <stout/gtest.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>
using std::map;
using std::string;
using std::vector;
TEST(StringsTest, Format)
{
Try<string> result = strings::format("%s %s", "hello", "world");
EXPECT_SOME_EQ("hello world", result);
result = strings::format("hello %d", 42);
EXPECT_SOME_EQ("hello 42", result);
result = strings::format("hello %s", "fourty-two");
EXPECT_SOME_EQ("hello fourty-two", result);
string hello = "hello";
result = strings::format("%s %s", hello, "fourty-two");
EXPECT_SOME_EQ("hello fourty-two", result);
}
TEST(StringsTest, Remove)
{
EXPECT_EQ("heo word", strings::remove("hello world", "l"));
EXPECT_EQ("hel world", strings::remove("hello world", "lo"));
EXPECT_EQ("home/", strings::remove("/home/", "/", strings::PREFIX));
EXPECT_EQ("/home", strings::remove("/home/", "/", strings::SUFFIX));
}
TEST(StringsTest, Replace)
{
EXPECT_EQ("hello*", strings::replace("hello/", "/", "*"));
EXPECT_EQ("*hello", strings::replace("/hello", "/", "*"));
EXPECT_EQ("*hello*world*", strings::replace("/hello/world/", "/", "*"));
EXPECT_EQ("*", strings::replace("/", "/", "*"));
EXPECT_EQ("hello world", strings::replace("hello world", "/", "*"));
EXPECT_EQ("***1***2***3***", strings::replace("/1/2/3/", "/", "***"));
EXPECT_EQ("123", strings::replace("/1/2/3/", "/", ""));
EXPECT_EQ("/1/2/3**", strings::replace("***1***2***3**", "***", "/"));
EXPECT_EQ("/1/2/3/", strings::replace("/1/2/3/", "", "*"));
}
TEST(StringsTest, Trim)
{
EXPECT_EQ("", strings::trim("", " "));
EXPECT_EQ("", strings::trim(" ", " "));
EXPECT_EQ("hello world", strings::trim("hello world", " "));
EXPECT_EQ("hello world", strings::trim(" hello world", " "));
EXPECT_EQ("hello world", strings::trim("hello world ", " "));
EXPECT_EQ("hello world", strings::trim(" hello world ", " "));
EXPECT_EQ("hello world", strings::trim(" \t hello world\t ", " \t"));
EXPECT_EQ("hello world", strings::trim(" \t hello world\t \n\r "));
// Also test trimming from just the prefix or suffix.
EXPECT_EQ("hello world\t \n\r ",
strings::trim(" \t hello world\t \n\r ", strings::PREFIX));
EXPECT_EQ(" \t hello world",
strings::trim(" \t hello world\t \n\r ", strings::SUFFIX));
EXPECT_EQ("\t hello world\t \n\r ",
strings::trim(" \t hello world\t \n\r ", strings::PREFIX, " "));
EXPECT_EQ(" \t hello world\t \n",
strings::trim(" \t hello world\t \n\r ", strings::SUFFIX, " \r"));
}
TEST(StringsTest, Tokenize)
{
vector<string> tokens = strings::tokenize("hello world, what's up?", " ");
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("hello", tokens[0]);
EXPECT_EQ("world,", tokens[1]);
EXPECT_EQ("what's", tokens[2]);
EXPECT_EQ("up?", tokens[3]);
}
TEST(StringsTest, TokenizeStringWithDelimsAtStart)
{
vector<string> tokens = strings::tokenize(" hello world, what's up?", " ");
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("hello", tokens[0]);
EXPECT_EQ("world,", tokens[1]);
EXPECT_EQ("what's", tokens[2]);
EXPECT_EQ("up?", tokens[3]);
}
TEST(StringsTest, TokenizeStringWithDelimsAtEnd)
{
vector<string> tokens =
strings::tokenize("hello world, what's up? ", " ");
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("hello", tokens[0]);
EXPECT_EQ("world,", tokens[1]);
EXPECT_EQ("what's", tokens[2]);
EXPECT_EQ("up?", tokens[3]);
}
TEST(StringsTest, TokenizeStringWithDelimsAtStartAndEnd)
{
vector<string> tokens =
strings::tokenize(" hello world, what's up? ", " ");
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("hello", tokens[0]);
EXPECT_EQ("world,", tokens[1]);
EXPECT_EQ("what's", tokens[2]);
EXPECT_EQ("up?", tokens[3]);
}
TEST(StringsTest, TokenizeWithMultipleDelims)
{
vector<string> tokens =
strings::tokenize("hello\tworld, \twhat's up?", " \t");
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("hello", tokens[0]);
EXPECT_EQ("world,", tokens[1]);
EXPECT_EQ("what's", tokens[2]);
EXPECT_EQ("up?", tokens[3]);
}
TEST(StringsTest, TokenizeEmptyString)
{
vector<string> tokens = strings::tokenize("", " ");
ASSERT_TRUE(tokens.empty());
}
TEST(StringsTest, TokenizeDelimOnlyString)
{
vector<string> tokens = strings::tokenize(" ", " ");
ASSERT_TRUE(tokens.empty());
}
TEST(StringsTest, TokenizeNullByteDelim)
{
string s;
s.push_back('\0');
s.push_back('\0');
s.push_back('\0');
s.push_back('h');
s.push_back('e');
s.push_back('l');
s.push_back('l');
s.push_back('o');
s.push_back('\0');
s.push_back('\0');
s.push_back('\0');
s.push_back('\0');
s.push_back('\0');
s.push_back('\0');
s.push_back('w');
s.push_back('o');
s.push_back('r');
s.push_back('l');
s.push_back('d');
s.push_back('\0');
s.push_back('\0');
s.push_back('\0');
vector<string> tokens = strings::tokenize(s, string(1, '\0'));
ASSERT_EQ(2u, tokens.size());
EXPECT_EQ("hello", tokens[0]);
EXPECT_EQ("world", tokens[1]);
}
TEST(StringsTest, TokenizeNZero)
{
vector<string> tokens = strings::tokenize("foo,bar,,,", ",", 0);
ASSERT_TRUE(tokens.empty());
}
TEST(StringsTest, TokenizeNOne)
{
vector<string> tokens = strings::tokenize("foo,bar,,,", ",", 1);
ASSERT_EQ(1u, tokens.size());
EXPECT_EQ("foo,bar,,,", tokens[0]);
}
TEST(StringsTest, TokenizeNDelimOnlyString)
{
vector<string> tokens = strings::tokenize(",,,", ",", 2);
ASSERT_TRUE(tokens.empty());
}
TEST(StringsTest, TokenizeN)
{
vector<string> tokens = strings::tokenize("foo,bar,,baz", ",", 2);
ASSERT_EQ(2u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar,,baz", tokens[1]);
}
TEST(StringsTest, TokenizeNStringWithDelimsAtStart)
{
vector<string> tokens = strings::tokenize(",,foo,bar,,baz", ",", 5);
ASSERT_EQ(3u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("baz", tokens[2]);
}
TEST(StringsTest, TokenizeNStringWithDelimsAtEnd)
{
vector<string> tokens = strings::tokenize("foo,bar,,baz,,", ",", 4);
ASSERT_EQ(3u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("baz", tokens[2]);
}
TEST(StringsTest, TokenizeNStringWithDelimsAtStartAndEnd)
{
vector<string> tokens = strings::tokenize(",,foo,bar,,", ",", 6);
ASSERT_EQ(2u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
}
TEST(StringsTest, TokenizeNWithMultipleDelims)
{
vector<string> tokens = strings::tokenize("foo.bar,.,.baz.", ",.", 6);
ASSERT_EQ(3u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("baz", tokens[2]);
}
TEST(StringsTest, SplitEmptyString)
{
vector<string> tokens = strings::split("", ",");
ASSERT_EQ(1u, tokens.size());
EXPECT_EQ("", tokens[0]);
}
TEST(StringsTest, SplitDelimOnlyString)
{
vector<string> tokens = strings::split(",,,", ",");
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("", tokens[0]);
EXPECT_EQ("", tokens[1]);
EXPECT_EQ("", tokens[2]);
EXPECT_EQ("", tokens[3]);
}
TEST(StringsTest, Split)
{
vector<string> tokens = strings::split("foo,bar,,baz", ",");
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("", tokens[2]);
EXPECT_EQ("baz", tokens[3]);
}
TEST(StringsTest, SplitStringWithDelimsAtStart)
{
vector<string> tokens = strings::split(",,foo,bar,,baz", ",");
ASSERT_EQ(6u, tokens.size());
EXPECT_EQ("", tokens[0]);
EXPECT_EQ("", tokens[1]);
EXPECT_EQ("foo", tokens[2]);
EXPECT_EQ("bar", tokens[3]);
EXPECT_EQ("", tokens[4]);
EXPECT_EQ("baz", tokens[5]);
}
TEST(StringsTest, SplitStringWithDelimsAtEnd)
{
vector<string> tokens = strings::split("foo,bar,,baz,,", ",");
ASSERT_EQ(6u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("", tokens[2]);
EXPECT_EQ("baz", tokens[3]);
EXPECT_EQ("", tokens[4]);
EXPECT_EQ("", tokens[5]);
}
TEST(StringsTest, SplitStringWithDelimsAtStartAndEnd)
{
vector<string> tokens = strings::split(",,foo,bar,,", ",");
ASSERT_EQ(6u, tokens.size());
EXPECT_EQ("", tokens[0]);
EXPECT_EQ("", tokens[1]);
EXPECT_EQ("foo", tokens[2]);
EXPECT_EQ("bar", tokens[3]);
EXPECT_EQ("", tokens[4]);
EXPECT_EQ("", tokens[5]);
}
TEST(StringsTest, SplitWithMultipleDelims)
{
vector<string> tokens = strings::split("foo.bar,.,.baz.", ",.");
ASSERT_EQ(7u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("", tokens[2]);
EXPECT_EQ("", tokens[3]);
EXPECT_EQ("", tokens[4]);
EXPECT_EQ("baz", tokens[5]);
EXPECT_EQ("", tokens[6]);
}
TEST(StringsTest, SplitNZero)
{
vector<string> tokens = strings::split("foo,bar,,,", ",", 0);
ASSERT_TRUE(tokens.empty());
}
TEST(StringsTest, SplitNOne)
{
vector<string> tokens = strings::split("foo,bar,,,", ",", 1);
ASSERT_EQ(1u, tokens.size());
EXPECT_EQ("foo,bar,,,", tokens[0]);
}
TEST(StringsTest, SplitNDelimOnlyString)
{
vector<string> tokens = strings::split(",,,", ",", 2);
ASSERT_EQ(2u, tokens.size());
EXPECT_EQ("", tokens[0]);
EXPECT_EQ(",,", tokens[1]);
}
TEST(StringsTest, SplitN)
{
vector<string> tokens = strings::split("foo,bar,,baz", ",", 2);
ASSERT_EQ(2u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar,,baz", tokens[1]);
}
TEST(StringsTest, SplitNStringWithDelimsAtStart)
{
vector<string> tokens = strings::split(",,foo,bar,,baz", ",", 5);
ASSERT_EQ(5u, tokens.size());
EXPECT_EQ("", tokens[0]);
EXPECT_EQ("", tokens[1]);
EXPECT_EQ("foo", tokens[2]);
EXPECT_EQ("bar", tokens[3]);
EXPECT_EQ(",baz", tokens[4]);
}
TEST(StringsTest, SplitNStringWithDelimsAtEnd)
{
vector<string> tokens = strings::split("foo,bar,,baz,,", ",", 4);
ASSERT_EQ(4u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("", tokens[2]);
EXPECT_EQ("baz,,", tokens[3]);
}
TEST(StringsTest, SplitNStringWithDelimsAtStartAndEnd)
{
vector<string> tokens = strings::split(",,foo,bar,,", ",", 6);
ASSERT_EQ(6u, tokens.size());
EXPECT_EQ("", tokens[0]);
EXPECT_EQ("", tokens[1]);
EXPECT_EQ("foo", tokens[2]);
EXPECT_EQ("bar", tokens[3]);
EXPECT_EQ("", tokens[4]);
EXPECT_EQ("", tokens[5]);
}
TEST(StringsTest, SplitNWithMultipleDelims)
{
vector<string> tokens = strings::split("foo.bar,.,.baz.", ",.", 6);
ASSERT_EQ(6u, tokens.size());
EXPECT_EQ("foo", tokens[0]);
EXPECT_EQ("bar", tokens[1]);
EXPECT_EQ("", tokens[2]);
EXPECT_EQ("", tokens[3]);
EXPECT_EQ("", tokens[4]);
EXPECT_EQ("baz.", tokens[5]);
}
TEST(StringsTest, Pairs)
{
{
map<string, vector<string>> pairs = strings::pairs("one=1,two=2", ",", "=");
map<string, vector<string>> expected = {
{"one", {"1"}},
{"two", {"2"}}
};
EXPECT_EQ(expected, pairs);
}
{
map<string, vector<string>> pairs = strings::pairs(
"foo=1;bar=2;baz;foo=3;bam=1=2", ";&", "=");
map<string, vector<string>> expected = {
{"foo", {"1", "3"}},
{"bar", {"2"}}
};
EXPECT_EQ(expected, pairs);
}
}
TEST(StringsTest, Join)
{
EXPECT_EQ("a/b", strings::join("/", "a", "b"));
EXPECT_EQ("a/b/c", strings::join("/", "a", "b", "c"));
EXPECT_EQ("a\nb\nc\nd", strings::join("\n", "a", "b", "c", "d"));
EXPECT_EQ("a//b///d", strings::join("/", "a", "", "b", "", "", "d"));
std::stringstream ss;
EXPECT_EQ("a, b, c", strings::join(ss, ", ", "a", "b", "c").str());
const string gnarly("gnarly");
EXPECT_EQ("a/gnarly/c", strings::join("/", "a", gnarly, "c"));
const bool is_true = true;
const std::set<int32_t> my_set {1, 2, 3};
EXPECT_EQ(
"a/gnarly/true/{ 1, 2, 3 }/c",
strings::join("/", "a", gnarly, is_true, my_set, "c"));
}
TEST(StringsTest, StartsWith)
{
EXPECT_TRUE(strings::startsWith("hello world", "hello"));
EXPECT_FALSE(strings::startsWith("hello world", "no"));
EXPECT_FALSE(strings::startsWith("hello world", "ello"));
EXPECT_TRUE(strings::startsWith("hello world", std::string("hello")));
EXPECT_FALSE(strings::startsWith("hello world", std::string("ello")));
}
TEST(StringsTest, EndsWith)
{
EXPECT_TRUE(strings::endsWith("hello world", "world"));
EXPECT_FALSE(strings::endsWith("hello world", "no"));
EXPECT_FALSE(strings::endsWith("hello world", "ello"));
EXPECT_TRUE(strings::endsWith("hello world", std::string("world")));
EXPECT_FALSE(strings::endsWith("hello world", std::string("worl")));
}
TEST(StringsTest, Contains)
{
EXPECT_TRUE(strings::contains("hello world", "world"));
EXPECT_FALSE(strings::contains("hello world", "no"));
}