diff options
Diffstat (limited to 'src/parser/string_pool_test.cpp')
-rw-r--r-- | src/parser/string_pool_test.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/parser/string_pool_test.cpp b/src/parser/string_pool_test.cpp new file mode 100644 index 0000000..7d3f864 --- /dev/null +++ b/src/parser/string_pool_test.cpp @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "test_global.hpp" +#include <orcus/string_pool.hpp> + +#include <type_traits> + +using namespace orcus; + +void test_basic() +{ + const char* static_text = "test"; + + string_pool pool; + assert(pool.size() == 0); + + std::pair<std::string_view, bool> ret = pool.intern("foo"); + assert(ret.first == "foo"); + assert(ret.second); // new instance + + ret = pool.intern("foo"); + assert(ret.first == "foo"); + assert(!ret.second); // existing instance. + + // Empty strings should not be interned. + ret = pool.intern(""); + assert(ret.first.empty()); + assert(!ret.second); + + ret = pool.intern("A"); + std::cout << "interned string: " << ret.first << std::endl; + assert(ret.second); + assert(pool.size() == 2); + + // Duplicate string. + ret = pool.intern("A"); + std::cout << "interned string: " << ret.first << std::endl; + assert(!ret.second); + + ret = pool.intern("B"); + std::cout << "interned string: " << ret.first << std::endl; + assert(pool.size() == 3); + + // Interning an already-intern string should return a string_view with + // identical memory address. + std::string_view str = ret.first; + std::string_view str2 = pool.intern(str).first; + assert(str == str2); + assert(pool.size() == 3); + assert(str.data() == str2.data()); // their memory address should be identical. + + std::string_view static_str(static_text); + ret = pool.intern(static_str); + str = ret.first; + std::cout << "interned string: " << str << std::endl; + assert(pool.size() == 4); + assert(str == static_str); + assert(str.data() != static_str.data()); + + // Make sure that the pool remains usable after calling clear(). + pool.clear(); + assert(pool.size() == 0); + ret = pool.intern(static_str); + assert(ret.second); // it should be a new string + assert(ret.first == static_str); +} + +void test_merge() +{ + string_pool pool1; + std::unique_ptr<string_pool> pool2(std::make_unique<string_pool>()); + + pool1.intern("A"); + pool1.intern("B"); + pool1.intern("C"); + std::string_view v1 = pool1.intern("same value").first; + + pool2->intern("D"); + pool2->intern("E"); + pool2->intern("F"); + std::string_view v2 = pool2->intern("same value").first; + + assert(pool1.size() == 4); + assert(pool2->size() == 4); + + pool1.merge(*pool2); + + assert(pool1.size() == 7); + assert(pool2->size() == 0); + + pool2.reset(); // Delete the pool2 instance altogether. + + // This should not create a new entry. + auto r = pool1.intern("F"); + assert(!r.second); + + // v2 still points to the original string in pool2, which should now be in + // the merged store in pool1 (thus valid). + assert(v1 == v2); + + std::vector<std::string_view> entries = pool1.get_interned_strings(); + assert(entries.size() == pool1.size()); +} + +void test_move() +{ + static_assert(!std::is_copy_constructible_v<orcus::string_pool>); + static_assert(std::is_move_constructible_v<orcus::string_pool>); + + string_pool pool1; + pool1.intern("A"); + pool1.intern("B"); + pool1.intern("C"); + pool1.intern("D"); + pool1.intern("E"); + + string_pool pool2 = std::move(pool1); + assert(pool2.size() == 5); +} + +int main() +{ + test_basic(); + test_merge(); + test_move(); + + return EXIT_SUCCESS; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |