|
| 1 | +/* Copyright (c) 2024, Oracle and/or its affiliates. |
| 2 | +
|
| 3 | + This program is free software; you can redistribute it and/or modify |
| 4 | + it under the terms of the GNU General Public License, version 2.0, |
| 5 | + as published by the Free Software Foundation. |
| 6 | +
|
| 7 | + This program is designed to work with certain software (including |
| 8 | + but not limited to OpenSSL) that is licensed under separate terms, |
| 9 | + as designated in a particular file or component or in included license |
| 10 | + documentation. The authors of MySQL hereby grant you an additional |
| 11 | + permission to link the program and your derivative works with the |
| 12 | + separately licensed software that they have either included with |
| 13 | + the program or referenced in the documentation. |
| 14 | +
|
| 15 | + This program is distributed in the hope that it will be useful, |
| 16 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | + GNU General Public License, version 2.0, for more details. |
| 19 | +
|
| 20 | + You should have received a copy of the GNU General Public License |
| 21 | + along with this program; if not, write to the Free Software |
| 22 | + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 23 | + |
| 24 | +#include <gtest/gtest.h> |
| 25 | + |
| 26 | +#include "storage/innobase/include/detail/fts/fts.h" |
| 27 | +#include "storage/innobase/include/fts0fts.h" |
| 28 | +#include "storage/innobase/include/fts0types.h" |
| 29 | +#include "storage/innobase/include/os0event.h" |
| 30 | +#include "storage/innobase/include/sync0debug.h" |
| 31 | +#include "storage/innobase/include/univ.i" |
| 32 | +#include "storage/innobase/include/ut0rbt.h" |
| 33 | + |
| 34 | +namespace innodb_fts0fts_unittest { |
| 35 | + |
| 36 | +/* Doc id array for testing with values exceeding 32-bit integer limit */ |
| 37 | +const doc_id_t doc_ids[] = { |
| 38 | + 17574, 89783, 94755, 97537, 101358, 101361, |
| 39 | + 102587, 103571, 104018, 106821, 108647, 109352, |
| 40 | + 109379, 110325, 122868, 210682130, 231275441, 234172769, |
| 41 | + 366236849, 526467159, 1675241735, 1675243405, 1947751899, 1949940363, |
| 42 | + 2033691953, 2148227299, 2256289791, 2294223591, 2367501260, 2792700091, |
| 43 | + 2792701220, 2817121627, 2820680352, 2821165664, 3253312130, 3404918378, |
| 44 | + 3532599429, 3538712078, 3539373037, 3546479309, 3566641838, 3580209634, |
| 45 | + 3580871267, 3693930556, 3693932734, 3693932983, 3781949558, 3839877411, |
| 46 | + 3930968983, 4146309172, 4524715523, 4524715525, 4534911119, 4597818456}; |
| 47 | + |
| 48 | +const doc_id_t search_doc_id = 1675241735; |
| 49 | + |
| 50 | +namespace { |
| 51 | +struct dummy { |
| 52 | + doc_id_t doc_id; |
| 53 | +}; |
| 54 | +} // namespace |
| 55 | + |
| 56 | +TEST(fts0fts, fts_doc_id_field_cmp) { |
| 57 | + // doc_ids are in ascending order |
| 58 | + auto doc_ids_size = sizeof(doc_ids) / sizeof(doc_ids[0]); |
| 59 | + for (size_t i = 1; i < doc_ids_size; ++i) { |
| 60 | + dummy obj1{doc_ids[i - 1]}; |
| 61 | + dummy obj2{doc_ids[i]}; |
| 62 | + EXPECT_LT(fts_doc_id_field_cmp<dummy>(&obj1, &obj2), 0); |
| 63 | + obj1.doc_id = doc_ids[i]; |
| 64 | + obj2.doc_id = doc_ids[i - 1]; |
| 65 | + EXPECT_GT(fts_doc_id_field_cmp<dummy>(&obj1, &obj2), 0); |
| 66 | + obj2.doc_id = doc_ids[i]; |
| 67 | + EXPECT_EQ(fts_doc_id_field_cmp<dummy>(&obj1, &obj2), 0); |
| 68 | + } |
| 69 | + |
| 70 | + /*Test in the context of RBT, where fts_doc_id_field_cmp is intended |
| 71 | + to be used */ |
| 72 | + |
| 73 | + ib_rbt_t *doc_id_rbt = rbt_create(sizeof(dummy), fts_doc_id_field_cmp<dummy>); |
| 74 | + |
| 75 | + /* Insert doc ids into rbtree. */ |
| 76 | + for (auto doc_id : doc_ids) { |
| 77 | + ib_rbt_bound_t parent; |
| 78 | + dummy obj; |
| 79 | + obj.doc_id = doc_id; |
| 80 | + |
| 81 | + if (rbt_search(doc_id_rbt, &parent, &obj.doc_id) != 0) { |
| 82 | + rbt_add_node(doc_id_rbt, &parent, &obj); |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + /* Check if doc id exists in rbtree */ |
| 87 | + ib_rbt_bound_t parent; |
| 88 | + EXPECT_EQ(rbt_search(doc_id_rbt, &parent, &search_doc_id), 0); |
| 89 | + |
| 90 | + rbt_free(doc_id_rbt); |
| 91 | +} |
| 92 | + |
| 93 | +// RAII wrapper for initialization needed to create and use RW locks |
| 94 | +struct os_support_t { |
| 95 | + os_support_t() { |
| 96 | + os_event_global_init(); |
| 97 | + sync_check_init(1); |
| 98 | + } |
| 99 | + ~os_support_t() { |
| 100 | + sync_check_close(); |
| 101 | + os_event_global_destroy(); |
| 102 | + } |
| 103 | +}; |
| 104 | + |
| 105 | +TEST(fts0fts, fts_reset_get_doc) { |
| 106 | + os_support_t dummy; |
| 107 | + dict_table_t *table = |
| 108 | + static_cast<dict_table_t *>(calloc(1, sizeof(dict_table_t))); |
| 109 | + |
| 110 | + struct fts_cache_wrapper_t { |
| 111 | + fts_cache_t *const cache{}; |
| 112 | + fts_cache_wrapper_t(dict_table_t *table) : cache{fts_cache_create(table)} {} |
| 113 | + ~fts_cache_wrapper_t() { detail::fts_cache_destroy(cache); } |
| 114 | + } cache_wrapper(table); |
| 115 | + fts_cache_t *const cache = cache_wrapper.cache; |
| 116 | + |
| 117 | + rw_lock_x_lock(&cache->init_lock, UT_LOCATION_HERE); |
| 118 | + cache->get_docs = detail::fts_get_docs_create(cache); |
| 119 | + // Provide some content in get_docs for fts_reset_get_doc to overwrite |
| 120 | + fts_get_doc_t *get_doc = |
| 121 | + static_cast<fts_get_doc_t *>(ib_vector_push(cache->get_docs, nullptr)); |
| 122 | + memset(get_doc, 0x0, sizeof(*get_doc)); |
| 123 | + |
| 124 | + { |
| 125 | + fts_index_cache_t ic1{}; |
| 126 | + fts_index_cache_t ic2{}; |
| 127 | + ib_vector_push(cache->indexes, &ic1); |
| 128 | + ib_vector_push(cache->indexes, &ic2); |
| 129 | + } |
| 130 | + |
| 131 | + detail::fts_reset_get_doc(cache); |
| 132 | + |
| 133 | + rw_lock_x_unlock(&cache->init_lock); |
| 134 | + |
| 135 | + auto index_cache1 = |
| 136 | + static_cast<fts_index_cache_t *>(ib_vector_get(cache->indexes, 0)); |
| 137 | + auto index_cache2 = |
| 138 | + static_cast<fts_index_cache_t *>(ib_vector_get(cache->indexes, 1)); |
| 139 | + |
| 140 | + EXPECT_EQ(ib_vector_size(cache->get_docs), 2); |
| 141 | + |
| 142 | + get_doc = static_cast<fts_get_doc_t *>(ib_vector_get(cache->get_docs, 0)); |
| 143 | + EXPECT_EQ(get_doc->index_cache, index_cache1); |
| 144 | + EXPECT_EQ(get_doc->get_document_graph, nullptr); |
| 145 | + EXPECT_EQ(get_doc->cache, cache); |
| 146 | + |
| 147 | + get_doc = static_cast<fts_get_doc_t *>(ib_vector_get(cache->get_docs, 1)); |
| 148 | + EXPECT_EQ(get_doc->index_cache, index_cache2); |
| 149 | + EXPECT_EQ(get_doc->get_document_graph, nullptr); |
| 150 | + EXPECT_EQ(get_doc->cache, cache); |
| 151 | + |
| 152 | + free(table); |
| 153 | +} |
| 154 | +} // namespace innodb_fts0fts_unittest |
0 commit comments