blob: c327f20ea92b047bded4723fdcf3d4e9605d6af7 [file] [log] [blame]
// Copyright 2017-2020 The Verible Authors.
//
// 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 "common/strings/split.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "common/strings/range.h"
#include "common/util/range.h"
namespace verible {
namespace {
using ::testing::ElementsAre;
static void AcceptFunctionChar(std::function<absl::string_view(char)> func) {}
static void AcceptFunctionStringView(
std::function<absl::string_view(absl::string_view)> func) {}
// This tests that StringSpliterator can be passed to a std::function.
TEST(StringSpliteratorTest, CompileTimeAsFunction) {
StringSpliterator splitter("a,b,c");
AcceptFunctionChar(splitter);
AcceptFunctionStringView(splitter);
}
TEST(StringSpliteratorTest, EmptyOriginal) {
constexpr absl::string_view empty("");
StringSpliterator splitter(empty);
EXPECT_TRUE(splitter);
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), empty));
const auto token = splitter(",");
EXPECT_EQ(token, "");
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), empty));
EXPECT_TRUE(BoundsEqual(token, empty));
EXPECT_FALSE(splitter); // reached end
EXPECT_EQ(splitter(","), "");
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), empty));
}
TEST(StringSpliteratorTest, MyGodItsFullOfStars) {
constexpr absl::string_view stars("***");
const auto gen = MakeStringSpliterator(stars, '*'); // char delimiter
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(0, 0)));
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(1, 0)));
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(2, 0)));
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(3, 0)));
}
TEST(StringSpliteratorTest, StringDelimiter) {
constexpr absl::string_view stars("xxx");
const auto gen = MakeStringSpliterator(stars, "x"); // string delimiter
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(0, 0)));
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(1, 0)));
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(2, 0)));
EXPECT_TRUE(BoundsEqual(gen(), stars.substr(3, 0)));
}
TEST(StringSpliteratorTest, StarsAndStripes) {
constexpr absl::string_view space("==*===*=*====");
StringSpliterator splitter(space);
EXPECT_TRUE(splitter);
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), space));
absl::string_view token = splitter('*');
EXPECT_TRUE(splitter);
EXPECT_TRUE(BoundsEqual(token, space.substr(0, 2)))
<< " got \"" << token << '"';
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), space.substr(3)));
token = splitter('*');
EXPECT_TRUE(splitter);
EXPECT_TRUE(BoundsEqual(token, space.substr(3, 3)))
<< " got \"" << token << '"';
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), space.substr(7)));
token = splitter('*');
EXPECT_TRUE(splitter);
EXPECT_TRUE(BoundsEqual(token, space.substr(7, 1)))
<< " got \"" << token << '"';
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), space.substr(9)));
token = splitter('*');
EXPECT_FALSE(splitter); // this was the last token
EXPECT_TRUE(BoundsEqual(token, space.substr(9, 4)))
<< " got \"" << token << '"';
EXPECT_TRUE(BoundsEqual(splitter.Remainder(), space.substr(space.length())));
}
TEST(StringSpliteratorTest, InSpaceNoOneCanHearYouScream) {
constexpr absl::string_view space(" * * * ");
const auto gen = MakeStringSpliterator(space, '*'); // char delimiter
// expect to match the spaces between the stars
EXPECT_TRUE(BoundsEqual(gen(), space.substr(0, 2)));
EXPECT_TRUE(BoundsEqual(gen(), space.substr(3, 3)));
EXPECT_TRUE(BoundsEqual(gen(), space.substr(7, 1)));
EXPECT_TRUE(BoundsEqual(gen(), space.substr(9, 4)));
}
TEST(StringSpliteratorTest, CommaBabyCommaOverBaby) {
constexpr absl::string_view csv_row("abcd,,efg,hi");
const auto gen = MakeStringSpliterator(csv_row, ","); // string delimiter
// expect to match the spaces between the stars
EXPECT_TRUE(BoundsEqual(gen(), csv_row.substr(0, 4)));
EXPECT_TRUE(BoundsEqual(gen(), csv_row.substr(5, 0)));
EXPECT_TRUE(BoundsEqual(gen(), csv_row.substr(6, 3)));
EXPECT_TRUE(BoundsEqual(gen(), csv_row.substr(10, 2)));
}
using IntPair = std::pair<int, int>;
// For testing purposes, directly compare the substring indices,
// which is a stronger check than string contents comparison.
static std::vector<IntPair> SplitLinesToOffsets(absl::string_view text) {
std::vector<IntPair> offsets;
for (const auto& line : SplitLines(text)) {
offsets.push_back(SubstringOffsets(line, text));
}
return offsets;
}
TEST(SplitLinesTest, Empty) {
constexpr absl::string_view text("");
const auto lines = SplitLines(text);
EXPECT_TRUE(lines.empty());
}
TEST(SplitLinesTest, OneSpace) {
constexpr absl::string_view text(" ");
EXPECT_THAT(SplitLines(text), ElementsAre(" "));
EXPECT_THAT(SplitLinesToOffsets(text), ElementsAre(IntPair(0, 1)));
}
TEST(SplitLinesTest, OneBlankLine) {
constexpr absl::string_view text("\n");
EXPECT_THAT(SplitLines(text), ElementsAre(""));
EXPECT_THAT(SplitLinesToOffsets(text), ElementsAre(IntPair(0, 0)));
}
TEST(SplitLinesTest, BlankLines) {
constexpr absl::string_view text("\n\n\n");
EXPECT_THAT(SplitLines(text), ElementsAre("", "", ""));
EXPECT_THAT(SplitLinesToOffsets(text),
ElementsAre(IntPair(0, 0), IntPair(1, 1), IntPair(2, 2)));
}
TEST(SplitLinesTest, NonBlankLines) {
constexpr absl::string_view text("a\nbc\ndef\n");
EXPECT_THAT(SplitLines(text), ElementsAre("a", "bc", "def"));
EXPECT_THAT(SplitLinesToOffsets(text),
ElementsAre(IntPair(0, 1), IntPair(2, 4), IntPair(5, 8)));
}
TEST(SplitLinesTest, NonBlankLinesUnterminated) {
constexpr absl::string_view text("abc\nde\nf"); // no \n at the end
EXPECT_THAT(SplitLines(text), ElementsAre("abc", "de", "f"));
EXPECT_THAT(SplitLinesToOffsets(text),
ElementsAre(IntPair(0, 3), IntPair(4, 6), IntPair(7, 8)));
}
} // namespace
} // namespace verible