1 /*
2 * Copyright (C) 2019 The Android Open Source Project
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 "perfetto/ext/base/uuid.h"
18
19 #include <array>
20 #include <optional>
21
22 #include "perfetto/base/logging.h"
23 #include "test/gtest_and_gmock.h"
24
25 namespace perfetto {
26 namespace base {
27 namespace {
28
TEST(UuidTest,DefaultConstructorIsBlank)29 TEST(UuidTest, DefaultConstructorIsBlank) {
30 Uuid a;
31 Uuid b;
32 EXPECT_EQ(a, b);
33 EXPECT_EQ(a.msb(), 0);
34 EXPECT_EQ(a.lsb(), 0);
35 }
36
TEST(UuidTest,TwoUuidsShouldBeDifferent)37 TEST(UuidTest, TwoUuidsShouldBeDifferent) {
38 Uuid a = Uuidv4();
39 Uuid b = Uuidv4();
40 EXPECT_NE(a, b);
41 EXPECT_EQ(a, a);
42 EXPECT_EQ(b, b);
43 }
44
TEST(UuidTest,CanRoundTripUuid)45 TEST(UuidTest, CanRoundTripUuid) {
46 Uuid uuid = Uuidv4();
47 EXPECT_EQ(Uuid(uuid.ToString()), uuid);
48 }
49
TEST(UuidTest,SetGet)50 TEST(UuidTest, SetGet) {
51 Uuid a = Uuidv4();
52 Uuid b;
53 b.set_lsb_msb(a.lsb(), a.msb());
54 EXPECT_EQ(a, b);
55 }
56
TEST(UuidTest,LsbMsbConstructor)57 TEST(UuidTest, LsbMsbConstructor) {
58 Uuid uuid(-6605018796207623390, 1314564453825188563);
59 EXPECT_EQ(uuid.ToPrettyString(), "123e4567-e89b-12d3-a456-426655443322");
60 }
61
TEST(UuidTest,UuidToPrettyString)62 TEST(UuidTest, UuidToPrettyString) {
63 Uuid uuid;
64 uuid.set_lsb_msb(-6605018796207623390, 1314564453825188563);
65 EXPECT_EQ(uuid.ToPrettyString(), "123e4567-e89b-12d3-a456-426655443322");
66 }
67
TEST(UuidTest,BoolOperator)68 TEST(UuidTest, BoolOperator) {
69 Uuid uuid;
70 EXPECT_FALSE(uuid);
71
72 uuid.set_lsb(1);
73 EXPECT_TRUE(uuid);
74
75 uuid.set_lsb(0);
76 EXPECT_FALSE(uuid);
77
78 uuid.set_msb(0x80000000);
79 EXPECT_TRUE(uuid);
80
81 uuid = Uuid();
82 EXPECT_FALSE(uuid);
83
84 uuid = Uuidv4();
85 EXPECT_TRUE(uuid);
86 }
87
88 // Generate kRounds UUIDs and check that, for each bit, we see roughly as many
89 // zeros as ones.
90 // Marking as DISABLED as this really checks the STD implementation not our
91 // code. Invoke manually only when needed.
TEST(UuidTest,DISABLED_BitRandomDistribution)92 TEST(UuidTest, DISABLED_BitRandomDistribution) {
93 const int kRounds = 100000;
94 std::array<int64_t, 128> bit_count{};
95 for (int i = 0; i < kRounds; i++) {
96 Uuid uuid = Uuidv4();
97 for (size_t b = 0; b < 64; b++) {
98 bit_count[b] += (uint64_t(uuid.lsb()) & (1ull << b)) ? 1 : -1;
99 bit_count[64 + b] += (uint64_t(uuid.msb()) & (1ull << b)) ? 1 : -1;
100 }
101 }
102
103 // By adding +1 / -1 for each one/zero, `bit_count` contains for each bit,
104 // their embalance. In an ideal world we expect `bit_count` to be 0 at each
105 // position. In practice we accept a 2% embalance to pass the test.
106 int64_t max_diff = 0;
107 for (size_t i = 0; i < bit_count.size(); i++)
108 max_diff = std::max(max_diff, std::abs(bit_count[i]));
109
110 const double diff_pct =
111 100.0 * static_cast<double>(max_diff) / static_cast<double>(kRounds);
112 PERFETTO_DLOG("Max bit embalance: %.2f %%", diff_pct);
113
114 // Local runs show a 1% embalance. We take a 5x margin for the test.
115 ASSERT_LT(diff_pct, 5.0);
116 }
117
118 } // namespace
119 } // namespace base
120 } // namespace perfetto
121