summaryrefslogtreecommitdiffstats
path: root/src/parser/string_pool_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/string_pool_test.cpp')
-rw-r--r--src/parser/string_pool_test.cpp134
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: */