xref: /aosp_15_r20/external/cronet/base/unguessable_token_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/unguessable_token.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <sstream>
9*6777b538SAndroid Build Coastguard Worker #include <type_traits>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/hash/hash.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
13*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker namespace base {
16*6777b538SAndroid Build Coastguard Worker 
TestSmallerThanOperator(const UnguessableToken & a,const UnguessableToken & b)17*6777b538SAndroid Build Coastguard Worker void TestSmallerThanOperator(const UnguessableToken& a,
18*6777b538SAndroid Build Coastguard Worker                              const UnguessableToken& b) {
19*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(a < b);
20*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(b < a);
21*6777b538SAndroid Build Coastguard Worker }
22*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyEveryBit)23*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyEveryBit) {
24*6777b538SAndroid Build Coastguard Worker   std::optional<UnguessableToken> token = UnguessableToken::Deserialize(1, 2);
25*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(token.has_value());
26*6777b538SAndroid Build Coastguard Worker   uint64_t high = 1;
27*6777b538SAndroid Build Coastguard Worker   uint64_t low = 2;
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker   for (uint64_t bit = 1; bit != 0; bit <<= 1) {
30*6777b538SAndroid Build Coastguard Worker     uint64_t new_high = high ^ bit;
31*6777b538SAndroid Build Coastguard Worker     std::optional<UnguessableToken> new_token =
32*6777b538SAndroid Build Coastguard Worker         UnguessableToken::Deserialize(new_high, low);
33*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(new_token.has_value());
34*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(*token == *new_token);
35*6777b538SAndroid Build Coastguard Worker   }
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker   for (uint64_t bit = 1; bit != 0; bit <<= 1) {
38*6777b538SAndroid Build Coastguard Worker     uint64_t new_low = low ^ bit;
39*6777b538SAndroid Build Coastguard Worker     std::optional<UnguessableToken> new_token =
40*6777b538SAndroid Build Coastguard Worker         UnguessableToken::Deserialize(high, new_low);
41*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(new_token.has_value());
42*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(*token == *new_token);
43*6777b538SAndroid Build Coastguard Worker   }
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyEqualityOperators)46*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyEqualityOperators) {
47*6777b538SAndroid Build Coastguard Worker   // Deserialize is used for testing purposes.
48*6777b538SAndroid Build Coastguard Worker   // Use UnguessableToken::Create() in production code instead.
49*6777b538SAndroid Build Coastguard Worker   UnguessableToken token = UnguessableToken::Deserialize(1, 2).value();
50*6777b538SAndroid Build Coastguard Worker   UnguessableToken same_token = UnguessableToken::Deserialize(1, 2).value();
51*6777b538SAndroid Build Coastguard Worker   UnguessableToken diff_token = UnguessableToken::Deserialize(1, 3).value();
52*6777b538SAndroid Build Coastguard Worker   UnguessableToken empty_token;
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(token == token);
55*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(token != token);
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(token == same_token);
58*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(token != same_token);
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(token == diff_token);
61*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(diff_token == token);
62*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(token != diff_token);
63*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(diff_token != token);
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(empty_token == empty_token);
66*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(empty_token != empty_token);
67*6777b538SAndroid Build Coastguard Worker   for (const UnguessableToken& this_token : {token, same_token, diff_token}) {
68*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(this_token == empty_token);
69*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(this_token != empty_token);
70*6777b538SAndroid Build Coastguard Worker   }
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyConstructors)73*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyConstructors) {
74*6777b538SAndroid Build Coastguard Worker   UnguessableToken token = UnguessableToken::Create();
75*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(token.is_empty());
76*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(token);
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker   UnguessableToken copied_token(token);
79*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(copied_token);
80*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(token, copied_token);
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker   UnguessableToken uninitialized;
83*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(uninitialized.is_empty());
84*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(uninitialized);
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(UnguessableToken().is_empty());
87*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(UnguessableToken());
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifySerialization)90*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifySerialization) {
91*6777b538SAndroid Build Coastguard Worker   UnguessableToken token = UnguessableToken::Create();
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   uint64_t high = token.GetHighForSerialization();
94*6777b538SAndroid Build Coastguard Worker   uint64_t low = token.GetLowForSerialization();
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(high);
97*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(low);
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   std::optional<UnguessableToken> Deserialized =
100*6777b538SAndroid Build Coastguard Worker       UnguessableToken::Deserialize(high, low);
101*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(Deserialized.has_value());
102*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(token, *Deserialized);
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker // Common case (~88% of the time) - no leading zeroes in high_ nor low_.
TEST(UnguessableTokenTest,VerifyToString1)106*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyToString1) {
107*6777b538SAndroid Build Coastguard Worker   UnguessableToken token =
108*6777b538SAndroid Build Coastguard Worker       UnguessableToken::Deserialize(0x1234567890ABCDEF, 0xFEDCBA0987654321)
109*6777b538SAndroid Build Coastguard Worker           .value();
110*6777b538SAndroid Build Coastguard Worker   std::string expected = "1234567890ABCDEFFEDCBA0987654321";
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(expected, token.ToString());
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker   std::string expected_stream = "(1234567890ABCDEFFEDCBA0987654321)";
115*6777b538SAndroid Build Coastguard Worker   std::stringstream stream;
116*6777b538SAndroid Build Coastguard Worker   stream << token;
117*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(expected_stream, stream.str());
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker 
120*6777b538SAndroid Build Coastguard Worker // Less common case - leading zeroes in high_ or low_ (testing with both).
TEST(UnguessableTokenTest,VerifyToString2)121*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyToString2) {
122*6777b538SAndroid Build Coastguard Worker   UnguessableToken token = UnguessableToken::Deserialize(0x123, 0xABC).value();
123*6777b538SAndroid Build Coastguard Worker   std::string expected = "00000000000001230000000000000ABC";
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(expected, token.ToString());
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker   std::string expected_stream = "(00000000000001230000000000000ABC)";
128*6777b538SAndroid Build Coastguard Worker   std::stringstream stream;
129*6777b538SAndroid Build Coastguard Worker   stream << token;
130*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(expected_stream, stream.str());
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyToStringUniqueness)133*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyToStringUniqueness) {
134*6777b538SAndroid Build Coastguard Worker   const UnguessableToken token1 =
135*6777b538SAndroid Build Coastguard Worker       UnguessableToken::Deserialize(0x0000000012345678, 0x0000000123456789)
136*6777b538SAndroid Build Coastguard Worker           .value();
137*6777b538SAndroid Build Coastguard Worker   const UnguessableToken token2 =
138*6777b538SAndroid Build Coastguard Worker       UnguessableToken::Deserialize(0x0000000123456781, 0x0000000023456789)
139*6777b538SAndroid Build Coastguard Worker           .value();
140*6777b538SAndroid Build Coastguard Worker   EXPECT_NE(token1.ToString(), token2.ToString());
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyDeserializeZeroes)143*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyDeserializeZeroes) {
144*6777b538SAndroid Build Coastguard Worker   std::optional<UnguessableToken> token = UnguessableToken::Deserialize(0, 0);
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(token.has_value());
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyDeserializeFromString)149*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyDeserializeFromString) {
150*6777b538SAndroid Build Coastguard Worker   auto expected = UnguessableToken::CreateForTesting(1, 2);
151*6777b538SAndroid Build Coastguard Worker   auto actual = UnguessableToken::DeserializeFromString(
152*6777b538SAndroid Build Coastguard Worker       "00000000000000010000000000000002");
153*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(actual.has_value());
154*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(actual.value() == expected);
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyDeserializeFromInvalidString)157*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyDeserializeFromInvalidString) {
158*6777b538SAndroid Build Coastguard Worker   const char* invalid_representations[] = {
159*6777b538SAndroid Build Coastguard Worker       // Not a hex string representing 128 bits.
160*6777b538SAndroid Build Coastguard Worker       "1234",
161*6777b538SAndroid Build Coastguard Worker       // A string with valid length of 128 bits but 'X' is not a hex value.
162*6777b538SAndroid Build Coastguard Worker       "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
163*6777b538SAndroid Build Coastguard Worker       // A invalid hex string because of the lower case letters.
164*6777b538SAndroid Build Coastguard Worker       "0123456789abcdef0123456789abcdef",
165*6777b538SAndroid Build Coastguard Worker       // A zeroed out token is not a valid `UnguessableToken`.
166*6777b538SAndroid Build Coastguard Worker       "00000000000000000000000000000000"};
167*6777b538SAndroid Build Coastguard Worker   for (auto* invalid_representation : invalid_representations) {
168*6777b538SAndroid Build Coastguard Worker     auto actual =
169*6777b538SAndroid Build Coastguard Worker         UnguessableToken::DeserializeFromString(invalid_representation);
170*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(actual.has_value())
171*6777b538SAndroid Build Coastguard Worker         << "'" << invalid_representation
172*6777b538SAndroid Build Coastguard Worker         << "' should not be deserialized to an UnguessableToken.";
173*6777b538SAndroid Build Coastguard Worker     ;
174*6777b538SAndroid Build Coastguard Worker   }
175*6777b538SAndroid Build Coastguard Worker }
176*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifySmallerThanOperator)177*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifySmallerThanOperator) {
178*6777b538SAndroid Build Coastguard Worker   // Deserialize is used for testing purposes.
179*6777b538SAndroid Build Coastguard Worker   // Use UnguessableToken::Create() in production code instead.
180*6777b538SAndroid Build Coastguard Worker   {
181*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE("a.low < b.low and a.high == b.high.");
182*6777b538SAndroid Build Coastguard Worker     TestSmallerThanOperator(UnguessableToken::Deserialize(0, 1).value(),
183*6777b538SAndroid Build Coastguard Worker                             UnguessableToken::Deserialize(0, 5).value());
184*6777b538SAndroid Build Coastguard Worker   }
185*6777b538SAndroid Build Coastguard Worker   {
186*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE("a.low == b.low and a.high < b.high.");
187*6777b538SAndroid Build Coastguard Worker     TestSmallerThanOperator(UnguessableToken::Deserialize(1, 0).value(),
188*6777b538SAndroid Build Coastguard Worker                             UnguessableToken::Deserialize(5, 0).value());
189*6777b538SAndroid Build Coastguard Worker   }
190*6777b538SAndroid Build Coastguard Worker   {
191*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE("a.low < b.low and a.high < b.high.");
192*6777b538SAndroid Build Coastguard Worker     TestSmallerThanOperator(UnguessableToken::Deserialize(1, 1).value(),
193*6777b538SAndroid Build Coastguard Worker                             UnguessableToken::Deserialize(5, 5).value());
194*6777b538SAndroid Build Coastguard Worker   }
195*6777b538SAndroid Build Coastguard Worker   {
196*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE("a.low > b.low and a.high < b.high.");
197*6777b538SAndroid Build Coastguard Worker     TestSmallerThanOperator(UnguessableToken::Deserialize(1, 10).value(),
198*6777b538SAndroid Build Coastguard Worker                             UnguessableToken::Deserialize(10, 1).value());
199*6777b538SAndroid Build Coastguard Worker   }
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyHash)202*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyHash) {
203*6777b538SAndroid Build Coastguard Worker   UnguessableToken token = UnguessableToken::Create();
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(base::HashInts64(token.GetHighForSerialization(),
206*6777b538SAndroid Build Coastguard Worker                              token.GetLowForSerialization()),
207*6777b538SAndroid Build Coastguard Worker             UnguessableTokenHash()(token));
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker 
TEST(UnguessableTokenTest,VerifyBasicUniqueness)210*6777b538SAndroid Build Coastguard Worker TEST(UnguessableTokenTest, VerifyBasicUniqueness) {
211*6777b538SAndroid Build Coastguard Worker   EXPECT_NE(UnguessableToken::Create(), UnguessableToken::Create());
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker   UnguessableToken token = UnguessableToken::Create();
214*6777b538SAndroid Build Coastguard Worker   EXPECT_NE(token.GetHighForSerialization(), token.GetLowForSerialization());
215*6777b538SAndroid Build Coastguard Worker }
216*6777b538SAndroid Build Coastguard Worker }
217