1 /*
2 * Copyright 2021 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "kll.h"
17
18 #include "kll-quantiles.pb.h"
19
20 #include <gtest/gtest.h>
21
22 namespace dist_proc {
23 namespace aggregation {
24
25 namespace {
26
27 using zetasketch::android::AggregatorStateProto;
28 using zetasketch::android::kll_quantiles_state;
29 using zetasketch::android::KllQuantilesStateProto;
30
31 ////////////////////////////////////////////////////////////////////////////////
32 // --------------------- Tests for SerializeToProto ------------------------- //
33
TEST(KllQuantileSerializationTest,AggregatorProtoFieldsAreCorrectlyPopulated)34 TEST(KllQuantileSerializationTest, AggregatorProtoFieldsAreCorrectlyPopulated) {
35 std::unique_ptr<KllQuantile> aggregator = KllQuantile::Create();
36 for (int i = 0; i < 50; i++) {
37 aggregator->Add(i);
38 }
39 EXPECT_EQ(aggregator->num_values(), 50);
40
41 AggregatorStateProto aggregator_state = aggregator->SerializeToProto();
42 ASSERT_TRUE(aggregator_state.has_num_values());
43 EXPECT_EQ(aggregator_state.num_values(), 50);
44 EXPECT_EQ(aggregator_state.type(), zetasketch::android::KLL_QUANTILES);
45 EXPECT_EQ(aggregator_state.type(), 113);
46 EXPECT_EQ(aggregator_state.value_type(), zetasketch::android::DefaultOpsType::INT64);
47 EXPECT_EQ(aggregator_state.value_type(), 4);
48 }
49
TEST(KllQuantileSerializationTest,QuantilesProtoFieldsAreCorrectlyPopulated)50 TEST(KllQuantileSerializationTest, QuantilesProtoFieldsAreCorrectlyPopulated) {
51 std::unique_ptr<KllQuantile> aggregator = KllQuantile::Create();
52 for (int i = 1; i <= 10; i++) {
53 aggregator->Add(i);
54 }
55 EXPECT_EQ(aggregator->num_values(), 10);
56
57 AggregatorStateProto aggregator_state = aggregator->SerializeToProto();
58 EXPECT_EQ(aggregator_state.num_values(), 10);
59
60 EXPECT_EQ(aggregator_state.type(), zetasketch::android::KLL_QUANTILES);
61 ASSERT_TRUE(aggregator_state.HasExtension(kll_quantiles_state));
62 const KllQuantilesStateProto& quantiles_state =
63 aggregator_state.GetExtension(kll_quantiles_state);
64
65 ASSERT_TRUE(quantiles_state.has_k());
66 EXPECT_GE(quantiles_state.k(), 300);
67 EXPECT_LT(quantiles_state.k(), 5000);
68
69 ASSERT_TRUE(quantiles_state.has_inv_eps());
70 EXPECT_EQ(quantiles_state.inv_eps(), 1000);
71
72 // Min, max
73 ASSERT_TRUE(quantiles_state.has_min());
74 EXPECT_EQ(quantiles_state.min(), "\x1");
75 ASSERT_TRUE(quantiles_state.has_max());
76 EXPECT_EQ(quantiles_state.max(), "\xA");
77
78 // Compactors
79 EXPECT_EQ(quantiles_state.compactors_size(), 1);
80 const KllQuantilesStateProto::Compactor& compactor = quantiles_state.compactors(0);
81 ASSERT_TRUE(compactor.has_packed_values());
82 EXPECT_EQ(compactor.packed_values(), "\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA");
83
84 ASSERT_FALSE(quantiles_state.has_sampler());
85 }
86
TEST(KllQuantileSerializationTest,QuantilesProtoFieldsAreCorrectlyPopulatedNonDefaultInvDeltaEps)87 TEST(KllQuantileSerializationTest, QuantilesProtoFieldsAreCorrectlyPopulatedNonDefaultInvDeltaEps) {
88 KllQuantileOptions options;
89 options.set_inv_delta(1000);
90 options.set_inv_eps(40);
91 std::unique_ptr<KllQuantile> aggregator = KllQuantile::Create(options);
92 for (int i = 5; i < 200; i++) {
93 aggregator->Add(i);
94 }
95 EXPECT_EQ(aggregator->num_values(), 195);
96
97 AggregatorStateProto aggregator_state = aggregator->SerializeToProto();
98 EXPECT_EQ(aggregator_state.num_values(), 195);
99
100 ASSERT_TRUE(aggregator_state.HasExtension(kll_quantiles_state));
101 const KllQuantilesStateProto& quantiles_state =
102 aggregator_state.GetExtension(kll_quantiles_state);
103
104 ASSERT_TRUE(quantiles_state.has_k());
105 EXPECT_GE(quantiles_state.k(), 15);
106 EXPECT_LT(quantiles_state.k(), 200);
107
108 ASSERT_TRUE(quantiles_state.has_inv_eps());
109 EXPECT_EQ(quantiles_state.inv_eps(), 40);
110
111 // Min, max
112 ASSERT_TRUE(quantiles_state.has_min());
113 EXPECT_EQ(quantiles_state.min(), "\x5");
114 ASSERT_TRUE(quantiles_state.has_max());
115 EXPECT_EQ(quantiles_state.max(), "\xC7\x1");
116
117 EXPECT_GT(quantiles_state.compactors_size(), 1);
118 }
119
TEST(KllQuantileSerializationTest,QuantilesProtoFieldsAreCorrectlyPopulatedNonDefaultK)120 TEST(KllQuantileSerializationTest, QuantilesProtoFieldsAreCorrectlyPopulatedNonDefaultK) {
121 KllQuantileOptions options;
122 options.set_k(6000);
123 std::unique_ptr<KllQuantile> aggregator = KllQuantile::Create(options);
124 for (int i = 10; i <= 1000; i++) {
125 aggregator->Add(i);
126 }
127 EXPECT_EQ(aggregator->num_values(), 991);
128
129 AggregatorStateProto aggregator_state = aggregator->SerializeToProto();
130 EXPECT_EQ(aggregator_state.num_values(), 991);
131
132 ASSERT_TRUE(aggregator_state.HasExtension(kll_quantiles_state));
133 const KllQuantilesStateProto& quantiles_state =
134 aggregator_state.GetExtension(kll_quantiles_state);
135
136 ASSERT_TRUE(quantiles_state.has_k());
137 EXPECT_EQ(quantiles_state.k(), 6000);
138
139 // Min, max
140 ASSERT_TRUE(quantiles_state.has_min());
141 EXPECT_EQ(quantiles_state.min(), "\xA");
142 ASSERT_TRUE(quantiles_state.has_max());
143 EXPECT_EQ(quantiles_state.max(), "\xE8\a");
144
145 EXPECT_EQ(quantiles_state.compactors_size(), 1);
146 }
147
TEST(KllQuantileSerializationTest,EmptyQuantilesProto)148 TEST(KllQuantileSerializationTest, EmptyQuantilesProto) {
149 std::unique_ptr<KllQuantile> aggregator = KllQuantile::Create();
150
151 AggregatorStateProto aggregator_state = aggregator->SerializeToProto();
152 EXPECT_EQ(aggregator->num_values(), 0);
153
154 EXPECT_EQ(aggregator_state.type(), zetasketch::android::KLL_QUANTILES);
155 ASSERT_TRUE(aggregator_state.HasExtension(kll_quantiles_state));
156 aggregator_state.GetExtension(kll_quantiles_state);
157
158 const KllQuantilesStateProto& quantiles_state =
159 aggregator_state.GetExtension(kll_quantiles_state);
160
161 ASSERT_TRUE(quantiles_state.has_k());
162 EXPECT_GE(quantiles_state.k(), 1000);
163 EXPECT_LT(quantiles_state.k(), 5000);
164
165 ASSERT_TRUE(quantiles_state.has_inv_eps());
166 EXPECT_EQ(quantiles_state.inv_eps(), 1000);
167
168 ASSERT_FALSE(quantiles_state.has_min());
169 ASSERT_FALSE(quantiles_state.has_max());
170
171 EXPECT_EQ(quantiles_state.compactors_size(), 0);
172 ASSERT_FALSE(quantiles_state.has_sampler());
173 }
174 } // namespace
175
176 } // namespace aggregation
177 } // namespace dist_proc
178