[Groonga-commit] groonga/groonga [master] add a test that randomly inserts/searches/removes/updates keys.

Back to archive index

null+****@clear***** null+****@clear*****
2011年 11月 11日 (金) 14:26:20 JST


Susumu Yata	2011-11-11 05:26:20 +0000 (Fri, 11 Nov 2011)

  New Revision: d3bd0590e2f286e5532a718fd8ad3d55ddfce43c

  Log:
    add a test that randomly inserts/searches/removes/updates keys.

  Modified files:
    test/unit/core/dat/test-trie.cpp

  Modified: test/unit/core/dat/test-trie.cpp (+111 -4)
===================================================================
--- test/unit/core/dat/test-trie.cpp    2011-11-11 05:24:48 +0000 (f395ec5)
+++ test/unit/core/dat/test-trie.cpp    2011-11-11 05:26:20 +0000 (7eca207)
@@ -27,22 +27,31 @@
 #include <cstdlib>
 #include <cstring>
 #include <ctime>
+#include <map>
 #include <set>
+#include <stack>
 #include <string>
 #include <vector>
 
+#include "test-string.hpp"
+
 namespace
 {
+  void create_key(std::string *key, std::size_t min_length, std::size_t max_length)
+  {
+    key->resize(min_length + (std::rand() % (max_length - min_length + 1)));
+    for (std::size_t i = 0; i < key->size(); ++i) {
+      (*key)[i] = '0' + (std::rand() % 10);
+    }
+  }
+
   void create_keys(std::vector<std::string> *keys, std::size_t num_keys,
                    std::size_t min_length, std::size_t max_length)
   {
     std::string key;
     std::set<std::string> keyset;
     while (keyset.size() < num_keys) {
-      key.resize(min_length + (std::rand() % (max_length - min_length + 1)));
-      for (std::size_t j = 0; j < key.size(); ++j) {
-        key[j] = '0' + (std::rand() % 10);
-      }
+      create_key(&key, min_length, max_length);
       keyset.insert(key);
     }
     std::vector<std::string>(keyset.begin(), keyset.end()).swap(*keys);
@@ -309,4 +318,102 @@ namespace test_dat_trie
     cppcut_assert_equal(grn::dat::UInt32(0), dest_trie.num_zombies());
     cut_assert(dest_trie.num_blocks() < src_trie.num_nodes());
   }
+
+  void test_random_queries(void)
+  {
+    typedef std::stack<grn::dat::UInt32> Stack;
+    typedef std::map<std::string, grn::dat::UInt32> Keyset;
+
+    grn::dat::Trie trie;
+    trie.create();
+
+    Keyset keyset;
+    Stack stack;
+    std::string str;
+    for (std::size_t i = 0; i < (1 << 16); ++i) {
+      create_key(&str, 3, 6);
+      switch (static_cast<int>(4.0 * std::rand() / RAND_MAX)) {
+        case 0: {
+          const Keyset::const_iterator it = keyset.find(str);
+          const bool to_be_found = (it != keyset.end());
+          grn::dat::UInt32 key_pos;
+          const bool is_found = trie.search(str.c_str(), str.length(), &key_pos);
+          cppcut_assert_equal(to_be_found, is_found);
+          if (is_found) {
+            const grn::dat::Key &key = trie.get_key(key_pos);
+            cppcut_assert_equal(it->second, key.id());
+            cppcut_assert_equal(static_cast<grn::dat::UInt32>(str.length()),
+                                key.length());
+            cppcut_assert_equal(grn::dat::String(str.c_str(), str.length()),
+                                key.str());
+          }
+          break;
+        }
+        case 1: {
+          const Keyset::iterator it = keyset.find(str);
+          const bool to_be_removed = (it != keyset.end());
+          const bool is_removed = trie.remove(str.c_str(), str.length());
+          cppcut_assert_equal(to_be_removed, is_removed);
+          if (is_removed) {
+            stack.push(it->second);
+            keyset.erase(it);
+          }
+          break;
+        }
+        case 2: {
+          const grn::dat::UInt32 key_id =
+              stack.empty() ? (keyset.size() + 1) : stack.top();
+          const std::pair<Keyset::iterator, bool> it_bool_pair =
+              keyset.insert(std::make_pair(str, key_id));
+          const Keyset::const_iterator it = it_bool_pair.first;
+          const bool to_be_inserted = it_bool_pair.second;
+          if (!stack.empty() && to_be_inserted) {
+            stack.pop();
+          }
+          grn::dat::UInt32 key_pos;
+          bool is_inserted = !to_be_inserted;
+          try {
+            is_inserted = trie.insert(str.c_str(), str.length(), &key_pos);
+          } catch (const grn::dat::SizeError &ex) {
+            trie.create(trie, NULL, trie.file_size() * 2);
+            is_inserted = trie.insert(str.c_str(), str.length(), &key_pos);
+          }
+          cppcut_assert_equal(to_be_inserted, is_inserted);
+          const grn::dat::Key &key = trie.get_key(key_pos);
+          cppcut_assert_equal(grn::dat::String(str.c_str(), str.length()),
+                              key.str());
+          break;
+        }
+        default: {
+          const grn::dat::UInt32 key_id = (trie.max_key_id()) ?
+              ((std::rand() % trie.max_key_id()) + 1) : 0;
+          const grn::dat::Key &src_key = trie.ith_key(key_id);
+          const Keyset::iterator src_it = !src_key.is_valid() ? keyset.end() :
+              keyset.find(std::string(
+                  static_cast<const char *>(src_key.ptr()), src_key.length()));
+          cppcut_assert_equal(src_key.is_valid(), src_it != keyset.end());
+          const bool to_be_updated = src_key.is_valid() &&
+              (keyset.find(str) == keyset.end());
+          grn::dat::UInt32 key_pos;
+          bool is_updated = !to_be_updated;
+          try {
+            is_updated = trie.update(key_id, str.c_str(), str.length(), &key_pos);
+          } catch (const grn::dat::SizeError &ex) {
+            trie.create(trie, NULL, trie.file_size() * 2);
+            is_updated = trie.update(key_id, str.c_str(), str.length(), &key_pos);
+          }
+          cppcut_assert_equal(to_be_updated, is_updated);
+          if (is_updated) {
+            const grn::dat::Key &key = trie.get_key(key_pos);
+            cppcut_assert_equal(key.id(), key_id);
+            cppcut_assert_equal(grn::dat::String(str.c_str(), str.length()),
+                                key.str());
+            keyset.erase(src_it);
+            keyset.insert(std::make_pair(str, key_id));
+          }
+          break;
+        }
+      }
+    }
+  }
 }




Groonga-commit メーリングリストの案内
Back to archive index