event_engine/iomgr_event_engine/timer_heap_test.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include <gmock/gmock.h>
25 #include <gtest/gtest.h>
26 
30 
31 using testing::Contains;
32 using testing::Not;
33 
34 namespace grpc_event_engine {
35 namespace iomgr_engine {
36 
37 namespace {
38 int64_t RandomDeadline(void) { return rand(); }
39 
40 std::vector<Timer> CreateTestElements(size_t num_elements) {
41  std::vector<Timer> elems(num_elements);
42  for (size_t i = 0; i < num_elements; i++) {
43  elems[i].deadline = RandomDeadline();
44  }
45  return elems;
46 }
47 
48 void CheckValid(TimerHeap* pq) {
49  const std::vector<Timer*>& timers = pq->TestOnlyGetTimers();
50  for (size_t i = 0; i < timers.size(); ++i) {
51  size_t left_child = 1u + 2u * i;
52  size_t right_child = left_child + 1u;
53  if (left_child < timers.size()) {
54  EXPECT_LE(timers[i]->deadline, timers[left_child]->deadline);
55  }
56  if (right_child < timers.size()) {
57  EXPECT_LE(timers[i]->deadline, timers[right_child]->deadline);
58  }
59  }
60 }
61 
62 TEST(TimerHeapTest, Basics) {
63  TimerHeap pq;
64  const size_t num_test_elements = 200;
65  const size_t num_test_operations = 10000;
66  size_t i;
67  std::vector<Timer> test_elements = CreateTestElements(num_test_elements);
69 
70  EXPECT_TRUE(pq.is_empty());
71  CheckValid(&pq);
72  for (i = 0; i < num_test_elements; ++i) {
73  EXPECT_THAT(pq.TestOnlyGetTimers(), Not(Contains(&test_elements[i])));
74  pq.Add(&test_elements[i]);
75  CheckValid(&pq);
76  EXPECT_THAT(pq.TestOnlyGetTimers(), Contains(&test_elements[i]));
77  inpq.set(i);
78  }
79  for (i = 0; i < num_test_elements; ++i) {
80  /* Test that check still succeeds even for element that wasn't just
81  inserted. */
82  EXPECT_THAT(pq.TestOnlyGetTimers(), Contains(&test_elements[i]));
83  }
84 
85  EXPECT_EQ(pq.TestOnlyGetTimers().size(), num_test_elements);
86  CheckValid(&pq);
87 
88  for (i = 0; i < num_test_operations; ++i) {
89  size_t elem_num = static_cast<size_t>(rand()) % num_test_elements;
90  Timer* el = &test_elements[elem_num];
91  if (!inpq.is_set(elem_num)) { /* not in pq */
92  EXPECT_THAT(pq.TestOnlyGetTimers(), Not(Contains(el)));
93  el->deadline = RandomDeadline();
94  pq.Add(el);
95  EXPECT_THAT(pq.TestOnlyGetTimers(), Contains(el));
96  inpq.set(elem_num);
97  CheckValid(&pq);
98  } else {
99  EXPECT_THAT(pq.TestOnlyGetTimers(), Contains(el));
100  pq.Remove(el);
101  EXPECT_THAT(pq.TestOnlyGetTimers(), Not(Contains(el)));
102  inpq.clear(elem_num);
103  CheckValid(&pq);
104  }
105  }
106 }
107 
108 struct ElemStruct {
109  Timer elem;
110  bool inserted = false;
111 };
112 
113 ElemStruct* SearchElems(std::vector<ElemStruct>& elems, bool inserted) {
114  std::vector<size_t> search_order;
115  for (size_t i = 0; i < elems.size(); i++) {
116  search_order.push_back(i);
117  }
118  for (size_t i = 0; i < elems.size() * 2; i++) {
119  size_t a = static_cast<size_t>(rand()) % elems.size();
120  size_t b = static_cast<size_t>(rand()) % elems.size();
121  std::swap(search_order[a], search_order[b]);
122  }
123  ElemStruct* out = nullptr;
124  for (size_t i = 0; out == nullptr && i < elems.size(); i++) {
125  if (elems[search_order[i]].inserted == inserted) {
126  out = &elems[search_order[i]];
127  }
128  }
129  return out;
130 }
131 
132 // TODO(ctiller): this should be an actual fuzzer
133 TEST(TimerHeapTest, RandomMutations) {
134  TimerHeap pq;
135 
136  static const size_t elems_size = 1000;
137  std::vector<ElemStruct> elems(elems_size);
138  size_t num_inserted = 0;
139 
140  for (size_t round = 0; round < 10000; round++) {
141  int r = rand() % 1000;
142  if (r <= 550) {
143  /* 55% of the time we try to add something */
144  ElemStruct* el = SearchElems(elems, false);
145  if (el != nullptr) {
146  el->elem.deadline = RandomDeadline();
147  pq.Add(&el->elem);
148  el->inserted = true;
149  num_inserted++;
150  CheckValid(&pq);
151  }
152  } else if (r <= 650) {
153  /* 10% of the time we try to remove something */
154  ElemStruct* el = SearchElems(elems, true);
155  if (el != nullptr) {
156  pq.Remove(&el->elem);
157  el->inserted = false;
158  num_inserted--;
159  CheckValid(&pq);
160  }
161  } else {
162  /* the remaining times we pop */
163  if (num_inserted > 0) {
164  Timer* top = pq.Top();
165  pq.Pop();
166  for (size_t i = 0; i < elems_size; i++) {
167  if (top == &elems[i].elem) {
168  GPR_ASSERT(elems[i].inserted);
169  elems[i].inserted = false;
170  }
171  }
172  num_inserted--;
173  CheckValid(&pq);
174  }
175  }
176 
177  if (num_inserted) {
178  int64_t* min_deadline = nullptr;
179  for (size_t i = 0; i < elems_size; i++) {
180  if (elems[i].inserted) {
181  if (min_deadline == nullptr) {
182  min_deadline = &elems[i].elem.deadline;
183  } else {
184  if (elems[i].elem.deadline < *min_deadline) {
185  min_deadline = &elems[i].elem.deadline;
186  }
187  }
188  }
189  }
190  GPR_ASSERT(pq.Top()->deadline == *min_deadline);
191  }
192  }
193 }
194 
195 } // namespace
196 } // namespace iomgr_engine
197 } // namespace grpc_event_engine
198 
199 int main(int argc, char** argv) {
200  ::testing::InitGoogleTest(&argc, argv);
201  return RUN_ALL_TESTS();
202 }
grpc_event_engine::iomgr_engine::Timer::deadline
int64_t deadline
Definition: event_engine/iomgr_engine/timer.h:45
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
testing::Not
internal::NotMatcher< InnerMatcher > Not(InnerMatcher m)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8926
grpc_core::BitSet::set
GRPC_BITSET_CONSTEXPR_MUTATOR void set(int i)
Definition: bitset.h:93
EXPECT_THAT
#define EXPECT_THAT(value, matcher)
string.h
useful.h
elem
Timer elem
Definition: event_engine/iomgr_event_engine/timer_heap_test.cc:109
inserted
bool inserted
Definition: event_engine/iomgr_event_engine/timer_heap_test.cc:110
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
num_elements
static size_t num_elements(const uint8_t *in, size_t in_len)
Definition: evp_asn1.c:283
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
EXPECT_LE
#define EXPECT_LE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2030
grpc_core::BitSet::clear
GRPC_BITSET_CONSTEXPR_MUTATOR void clear(int i)
Definition: bitset.h:107
grpc_core::BitSet::is_set
constexpr bool is_set(int i) const
Definition: bitset.h:112
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
round
static int round(int n)
Definition: bloaty/third_party/re2/util/benchmark.cc:91
std::swap
void swap(Json::Value &a, Json::Value &b)
Specialize std::swap() for Json::Value.
Definition: third_party/bloaty/third_party/protobuf/conformance/third_party/jsoncpp/json.h:1226
grpc_event_engine::iomgr_engine::TEST
TEST(TimeAveragedStatsTest, NoRegressNoPersistTest1)
Definition: event_engine/iomgr_event_engine/time_averaged_stats_test.cc:28
RUN_ALL_TESTS
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2471
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
absl::container_internal::internal_layout::Contains
absl::disjunction< std::is_same< T, Ts >... > Contains
Definition: abseil-cpp/absl/container/internal/layout.h:253
testing::InitGoogleTest
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: bloaty/third_party/googletest/googletest/src/gtest.cc:6106
grpc_core::BitSet
Definition: bitset.h:85
main
int main(int argc, char **argv)
Definition: event_engine/iomgr_event_engine/timer_heap_test.cc:199
fix_build_deps.r
r
Definition: fix_build_deps.py:491
grpc_event_engine
Definition: endpoint_config.h:24
timer_heap.h
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
testing::Contains
internal::ContainsMatcher< M > Contains(M matcher)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:9101
top
static upb_pb_encoder_segment * top(upb_pb_encoder *e)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:7624
bitset.h
timer.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:38