blob: d3d5f344c214891e1de6eb598db59a465f917df3 [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/string_memory_map.h"
#include <memory>
#include <string>
#include "absl/memory/memory.h"
#include "common/strings/range.h"
#include "common/util/range.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace verible {
namespace {
static void ForAllSubstringRanges(
absl::string_view sv, const std::function<void(absl::string_view)>& func) {
for (auto start_iter = sv.begin(); start_iter != sv.end(); ++start_iter) {
for (auto end_iter = start_iter; end_iter != sv.end(); ++end_iter) {
if (start_iter == end_iter) continue; // skip empty ranges
func(make_string_view_range(start_iter, end_iter));
}
}
}
TEST(StringViewSuperRangeMapTest, Empty) {
StringViewSuperRangeMap svmap;
EXPECT_TRUE(svmap.empty());
}
TEST(StringViewSuperRangeMapTest, OneString) {
StringViewSuperRangeMap svmap;
constexpr absl::string_view text("text");
const auto new_iter = svmap.must_emplace(text);
EXPECT_NE(new_iter, svmap.end());
EXPECT_FALSE(svmap.empty());
EXPECT_TRUE(BoundsEqual(
make_string_view_range(new_iter->first, new_iter->second), text));
EXPECT_TRUE(BoundsEqual(svmap.must_find(text), text));
ForAllSubstringRanges(text, [&svmap, text](absl::string_view subrange) {
EXPECT_TRUE(BoundsEqual(svmap.must_find(subrange), text));
});
}
TEST(StringViewSuperRangeMapTest, Overlap) {
StringViewSuperRangeMap svmap;
constexpr absl::string_view text("text");
svmap.must_emplace(text);
EXPECT_DEATH(svmap.must_emplace(text), "Failed to emplace");
}
TEST(StringViewSuperRangeMapTest, OverlapSubstring) {
StringViewSuperRangeMap svmap;
constexpr absl::string_view text("text");
svmap.must_emplace(text);
EXPECT_DEATH(svmap.must_emplace(text.substr(1)), "Failed to emplace");
}
TEST(StringViewSuperRangeMapTest, SuperRangeNotInSet) {
StringViewSuperRangeMap svmap;
constexpr absl::string_view text("text");
svmap.must_emplace(text);
EXPECT_DEATH(svmap.must_find(absl::string_view("never-there")), "");
}
TEST(StringViewSuperRangeMapTest, TwoStrings) {
StringViewSuperRangeMap svmap;
constexpr absl::string_view text1("hello"), text2("world");
{
const auto new_iter = svmap.must_emplace(text1);
EXPECT_NE(new_iter, svmap.end());
EXPECT_FALSE(svmap.empty());
EXPECT_TRUE(BoundsEqual(
make_string_view_range(new_iter->first, new_iter->second), text1));
EXPECT_TRUE(BoundsEqual(svmap.must_find(text1), text1));
}
{
const auto new_iter = svmap.must_emplace(text2);
EXPECT_NE(new_iter, svmap.end());
EXPECT_FALSE(svmap.empty());
EXPECT_TRUE(BoundsEqual(
make_string_view_range(new_iter->first, new_iter->second), text2));
EXPECT_TRUE(BoundsEqual(svmap.must_find(text2), text2));
}
ForAllSubstringRanges(text1, [&svmap, text1](absl::string_view subrange) {
EXPECT_TRUE(BoundsEqual(svmap.must_find(subrange), text1));
});
ForAllSubstringRanges(text2, [&svmap, text2](absl::string_view subrange) {
EXPECT_TRUE(BoundsEqual(svmap.must_find(subrange), text2));
});
}
// Function to get the owned address range of the underlying string.
static absl::string_view StringViewKey(
const std::unique_ptr<const std::string>& owned) {
return absl::string_view(*ABSL_DIE_IF_NULL(owned));
}
typedef StringMemoryMap<std::unique_ptr<const std::string>, StringViewKey>
StringSet;
TEST(StringMemoryMapTest, EmptyOwnsNothing) {
const StringSet sset;
EXPECT_EQ(sset.find("not-owned-anywhere"), nullptr);
}
static absl::string_view InsertStringCopy(StringSet* sset, const char* text) {
const auto new_iter =
sset->insert(std::make_unique<std::string>(text)); // copy
return make_string_view_range(new_iter->first.first, new_iter->first.second);
}
TEST(StringMemoryMapTest, OneElement) {
StringSet sset;
const absl::string_view sv(InsertStringCopy(&sset, "OWNED"));
// Check all valid substring ranges
ForAllSubstringRanges(sv, [&sset, sv](absl::string_view subrange) {
const auto* f = sset.find(subrange);
ASSERT_NE(f, nullptr) << "subrange returned nullptr: " << subrange;
const absl::string_view fv(**f);
EXPECT_TRUE(BoundsEqual(fv, sv)) << "got: " << fv << " vs. " << sv;
EXPECT_EQ(fv, "OWNED");
});
}
TEST(StringMemoryMapTest, MultipleElements) {
StringSet sset;
// There's no telling where these allocated strings will reside in memory.
const absl::string_view sv1(InsertStringCopy(&sset, "AAA"));
const absl::string_view sv2(InsertStringCopy(&sset, "BBBB"));
const absl::string_view sv3(InsertStringCopy(&sset, "CCCCC"));
// Check all valid substring ranges
ForAllSubstringRanges(sv1, [&sset, sv1](absl::string_view subrange) {
const auto* f = sset.find(subrange);
ASSERT_NE(f, nullptr) << "subrange returned nullptr: " << subrange;
const absl::string_view fv(*ABSL_DIE_IF_NULL(*f));
EXPECT_TRUE(BoundsEqual(fv, sv1)) << "got: " << fv << " vs. " << sv1;
EXPECT_EQ(fv, "AAA");
});
ForAllSubstringRanges(sv2, [&sset, sv2](absl::string_view subrange) {
const auto* f = sset.find(subrange);
ASSERT_NE(f, nullptr) << "subrange returned nullptr: " << subrange;
const absl::string_view fv(*ABSL_DIE_IF_NULL(*f));
EXPECT_TRUE(BoundsEqual(fv, sv2)) << "got: " << fv << " vs. " << sv2;
EXPECT_EQ(fv, "BBBB");
});
ForAllSubstringRanges(sv3, [&sset, sv3](absl::string_view subrange) {
const auto* f = sset.find(subrange);
ASSERT_NE(f, nullptr) << "subrange returned nullptr: " << subrange;
const absl::string_view fv(*ABSL_DIE_IF_NULL(*f));
EXPECT_TRUE(BoundsEqual(fv, sv3)) << "got: " << fv << " vs. " << sv3;
EXPECT_EQ(fv, "CCCCC");
});
}
} // namespace
} // namespace verible