1 //
2 //
3 // Copyright 2016 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
19 #include "src/core/lib/transport/bdp_estimator.h"
20
21 #include <grpc/grpc.h>
22 #include <stdlib.h>
23
24 #include <algorithm>
25 #include <atomic>
26
27 #include "gtest/gtest.h"
28 #include "src/core/lib/iomgr/exec_ctx.h"
29 #include "src/core/lib/iomgr/timer_manager.h"
30 #include "test/core/test_util/test_config.h"
31
32 extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
33
34 namespace grpc_core {
35 namespace testing {
36 namespace {
37 std::atomic<int> g_clock{123};
38
fake_gpr_now(gpr_clock_type clock_type)39 gpr_timespec fake_gpr_now(gpr_clock_type clock_type) {
40 gpr_timespec ts;
41 ts.tv_sec = g_clock.load();
42 ts.tv_nsec = 0;
43 ts.clock_type = clock_type;
44 return ts;
45 }
46
inc_time(void)47 void inc_time(void) { g_clock.fetch_add(30); }
48 } // namespace
49
TEST(BdpEstimatorTest,NoOp)50 TEST(BdpEstimatorTest, NoOp) { BdpEstimator est("test"); }
51
TEST(BdpEstimatorTest,EstimateBdpNoSamples)52 TEST(BdpEstimatorTest, EstimateBdpNoSamples) {
53 BdpEstimator est("test");
54 est.EstimateBdp();
55 }
56
57 namespace {
AddSamples(BdpEstimator * estimator,int64_t * samples,size_t n)58 void AddSamples(BdpEstimator* estimator, int64_t* samples, size_t n) {
59 estimator->AddIncomingBytes(1234567);
60 inc_time();
61 ExecCtx exec_ctx;
62 estimator->SchedulePing();
63 estimator->StartPing();
64 for (size_t i = 0; i < n; i++) {
65 estimator->AddIncomingBytes(samples[i]);
66 }
67 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
68 gpr_time_from_millis(1, GPR_TIMESPAN)));
69 ExecCtx::Get()->InvalidateNow();
70 estimator->CompletePing();
71 }
72
AddSample(BdpEstimator * estimator,int64_t sample)73 void AddSample(BdpEstimator* estimator, int64_t sample) {
74 AddSamples(estimator, &sample, 1);
75 }
76 } // namespace
77
TEST(BdpEstimatorTest,GetEstimate1Sample)78 TEST(BdpEstimatorTest, GetEstimate1Sample) {
79 BdpEstimator est("test");
80 AddSample(&est, 100);
81 est.EstimateBdp();
82 }
83
TEST(BdpEstimatorTest,GetEstimate2Samples)84 TEST(BdpEstimatorTest, GetEstimate2Samples) {
85 BdpEstimator est("test");
86 AddSample(&est, 100);
87 AddSample(&est, 100);
88 est.EstimateBdp();
89 }
90
TEST(BdpEstimatorTest,GetEstimate3Samples)91 TEST(BdpEstimatorTest, GetEstimate3Samples) {
92 BdpEstimator est("test");
93 AddSample(&est, 100);
94 AddSample(&est, 100);
95 AddSample(&est, 100);
96 est.EstimateBdp();
97 }
98
99 namespace {
NextPow2(int64_t v)100 int64_t NextPow2(int64_t v) {
101 v--;
102 v |= v >> 1;
103 v |= v >> 2;
104 v |= v >> 4;
105 v |= v >> 8;
106 v |= v >> 16;
107 v |= v >> 32;
108 v++;
109 return v;
110 }
111 } // namespace
112
113 class BdpEstimatorRandomTest : public ::testing::TestWithParam<size_t> {};
114
TEST_P(BdpEstimatorRandomTest,GetEstimateRandomValues)115 TEST_P(BdpEstimatorRandomTest, GetEstimateRandomValues) {
116 BdpEstimator est("test");
117 const int kMaxSample = 65535;
118 int min = kMaxSample;
119 int max = 0;
120 for (size_t i = 0; i < GetParam(); i++) {
121 int sample = rand() % (kMaxSample + 1);
122 if (sample < min) min = sample;
123 if (sample > max) max = sample;
124 AddSample(&est, sample);
125 if (i >= 3) {
126 EXPECT_LE(est.EstimateBdp(), std::max(int64_t(65536), 2 * NextPow2(max)))
127 << " min:" << min << " max:" << max << " sample:" << sample;
128 }
129 }
130 }
131
132 INSTANTIATE_TEST_SUITE_P(TooManyNames, BdpEstimatorRandomTest,
133 ::testing::Values(3, 4, 6, 9, 13, 19, 28, 42, 63, 94,
134 141, 211, 316, 474, 711));
135
136 } // namespace testing
137 } // namespace grpc_core
138
main(int argc,char ** argv)139 int main(int argc, char** argv) {
140 grpc::testing::TestEnvironment env(&argc, argv);
141 gpr_now_impl = grpc_core::testing::fake_gpr_now;
142 grpc_init();
143 grpc_timer_manager_set_threading(false);
144 ::testing::InitGoogleTest(&argc, argv);
145 int ret = RUN_ALL_TESTS();
146 grpc_shutdown();
147 return ret;
148 }
149