1 | /* |
2 | * Copyright 2018-present Facebook, Inc. |
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 | * http://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 | |
17 | #include <folly/stats/detail/DigestBuilder-defs.h> |
18 | |
19 | #include <chrono> |
20 | #include <random> |
21 | #include <thread> |
22 | |
23 | #include <folly/Range.h> |
24 | #include <folly/portability/GTest.h> |
25 | |
26 | using namespace folly; |
27 | using namespace folly::detail; |
28 | |
29 | template <size_t MergeSize> |
30 | class SimpleDigest { |
31 | public: |
32 | explicit SimpleDigest(size_t sz) : sz_(sz) {} |
33 | |
34 | SimpleDigest merge(Range<const double*> r) const { |
35 | EXPECT_EQ(MergeSize, r.size()); |
36 | for (size_t i = 0; i < MergeSize; ++i) { |
37 | EXPECT_GE(MergeSize, r[i]); |
38 | } |
39 | return *this; |
40 | } |
41 | |
42 | static SimpleDigest merge(Range<const SimpleDigest*> r) { |
43 | EXPECT_EQ(1, r.size()); |
44 | return *r.begin(); |
45 | } |
46 | |
47 | int64_t getSize() const { |
48 | return sz_; |
49 | } |
50 | |
51 | private: |
52 | int64_t sz_; |
53 | }; |
54 | |
55 | TEST(DigestBuilder, SingleThreadUnfilledBuffer) { |
56 | DigestBuilder<SimpleDigest<999>> builder(1000, 100); |
57 | for (int i = 0; i < 999; ++i) { |
58 | builder.append(i); |
59 | } |
60 | EXPECT_EQ(100, builder.build().getSize()); |
61 | } |
62 | |
63 | TEST(DigestBuilder, SingleThreadFilledBuffer) { |
64 | DigestBuilder<SimpleDigest<1000>> builder(1000, 100); |
65 | for (int i = 0; i < 1000; ++i) { |
66 | builder.append(i); |
67 | } |
68 | EXPECT_EQ(100, builder.build().getSize()); |
69 | } |
70 | |
71 | TEST(DigestBuilder, MultipleThreads) { |
72 | DigestBuilder<SimpleDigest<1000>> builder(1000, 100); |
73 | std::vector<std::thread> threads; |
74 | for (int i = 0; i < 10; ++i) { |
75 | threads.push_back(std::thread([i, &builder]() { |
76 | for (int j = 0; j < 100; ++j) { |
77 | builder.append(i * 100 + j); |
78 | } |
79 | })); |
80 | } |
81 | for (auto& thread : threads) { |
82 | thread.join(); |
83 | } |
84 | |
85 | EXPECT_EQ(100, builder.build().getSize()); |
86 | } |
87 | |