1+ /*
2+ * Licensed to the Apache Software Foundation (ASF) under one
3+ * or more contributor license agreements. See the NOTICE file
4+ * distributed with this work for additional information
5+ * regarding copyright ownership. The ASF licenses this file
6+ * to you under the Apache License, Version 2.0 (the
7+ * "License"); you may not use this file except in compliance
8+ * with the License. You may obtain a copy of the License at
9+ *
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ *
12+ * Unless required by applicable law or agreed to in writing,
13+ * software distributed under the License is distributed on an
14+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+ * KIND, either express or implied. See the License for the
16+ * specific language governing permissions and limitations
17+ * under the License.
18+ *
19+ */
20+
21+ #include < gtest/gtest.h>
22+
23+ #include < memory>
24+
25+ #include " test_base.h"
26+ #include " types/redis_topk.h"
27+
28+ static constexpr uint32_t k = 5 ;
29+ static constexpr uint32_t width = 7 ;
30+ static constexpr uint32_t depth = 8 ;
31+ static constexpr double decay = 0.9 ;
32+
33+ class RedisTopKTest : public TestBase {
34+ protected:
35+ explicit RedisTopKTest () : TestBase() {
36+ top_k_ = std::make_unique<redis::TopK>(storage_.get (), " topk_ns" );
37+ }
38+ ~RedisTopKTest () override = default ;
39+
40+ void SetUp () override {
41+ key_ = " test_topk->key" ;
42+ top_k_->Reserve (*ctx_, key_, k, width, depth, decay);
43+ }
44+
45+ void TearDown () override {}
46+
47+ std::unique_ptr<redis::TopK> top_k_;
48+ };
49+
50+ TEST_F (RedisTopKTest, TestTopKInfo) {
51+ // test exist key
52+ redis::TopKInfo info1;
53+ top_k_->Info (*ctx_, key_, &info1);
54+ ASSERT_EQ (info1.k , k);
55+ ASSERT_EQ (info1.width , width);
56+ ASSERT_EQ (info1.depth , depth);
57+ ASSERT_EQ (info1.decay , decay);
58+
59+ // test not exist key
60+ redis::TopKInfo info2;
61+ auto s = top_k_->Info (*ctx_, " not_exist_key" , &info2);
62+ ASSERT_FALSE (s.ok ());
63+ }
64+
65+ TEST_F (RedisTopKTest, TestTopKAddAndQuery) {
66+ // test not exist key
67+ std::string no_exist_key = " no_exist_key" ;
68+ auto s = top_k_->Add (*ctx_, no_exist_key, " 1" );
69+ ASSERT_FALSE (s.ok ());
70+
71+ bool exist;
72+ s = top_k_->Query (*ctx_, no_exist_key, " 1" , &exist);
73+ ASSERT_FALSE (s.ok ());
74+
75+ std::vector<std::string> list;
76+ s = top_k_->List (*ctx_, no_exist_key, list);
77+ ASSERT_FALSE (s.ok ());
78+
79+ // test exist key
80+ std::vector<std::string> values1 = {" 1" , " 2" , " 3" , " 4" , " 5" };
81+ std::vector<std::string> values2 = {" 6" , " 7" , " 8" , " 9" , " 10" };
82+ std::unordered_set<std::string> values_set1 (values1.begin (), values1.end ());
83+ std::unordered_set<std::string> values_set2 (values2.begin (), values2.end ());
84+
85+ // found not exist values1
86+ for (size_t i = 0 ; i < values1.size (); ++i) {
87+ bool found = true ;
88+ top_k_->Query (*ctx_, key_, values1[i], &found);
89+ ASSERT_FALSE (found);
90+ }
91+ // add values1, and query values1.
92+ for (size_t i = 0 ; i < values1.size (); ++i) {
93+ top_k_->Add (*ctx_, key_, values1[i]);
94+ bool found = false ;
95+ top_k_->Query (*ctx_, key_, values1[i], &found);
96+ ASSERT_TRUE (found);
97+ }
98+ for (size_t i = 0 ; i < values1.size (); ++i) {
99+ bool found = false ;
100+ top_k_->Query (*ctx_, key_, values1[i], &found);
101+ ASSERT_TRUE (found);
102+ }
103+
104+ // found topk list.
105+ std::vector<std::string> top_k_list;
106+ top_k_->List (*ctx_, key_, top_k_list);
107+ ASSERT_EQ (top_k_list.size (), values1.size ());
108+ for (size_t i = 0 ; i < k; ++i) {
109+ ASSERT_TRUE (values_set1.find (top_k_list[i]) != values_set1.end ());
110+ }
111+
112+ // heap is full, need remove values1.
113+ for (size_t i = 0 ; i < values2.size (); ++i) {
114+ bool found = false ;
115+ // due to decay, topk is possiable to remove values1.
116+ while (!found) {
117+ top_k_->Add (*ctx_, key_, values2[i]);
118+ top_k_->Query (*ctx_, key_, values2[i], &found);
119+ }
120+ top_k_->Add (*ctx_, key_, values2[i]);
121+ }
122+
123+ // values1 is removed.
124+ for (size_t i = 0 ; i < values1.size (); ++i) {
125+ bool found = true ;
126+ top_k_->Query (*ctx_, key_, values1[i], &found);
127+ ASSERT_FALSE (found);
128+ }
129+
130+ // found topk list.
131+ top_k_list.clear ();
132+ top_k_->List (*ctx_, key_, top_k_list);
133+ for (size_t i = 0 ; i < top_k_list.size (); ++i) {
134+ ASSERT_TRUE (values_set2.find (top_k_list[i]) != values_set2.end ());
135+ }
136+ }
0 commit comments