• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/unguessable_token.h"
6 
7 #include <memory>
8 #include <sstream>
9 #include <type_traits>
10 
11 #include "base/values.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace base {
15 
TestSmallerThanOperator(const UnguessableToken & a,const UnguessableToken & b)16 void TestSmallerThanOperator(const UnguessableToken& a,
17                              const UnguessableToken& b) {
18   EXPECT_TRUE(a < b);
19   EXPECT_FALSE(b < a);
20 }
21 
TEST(UnguessableTokenTest,VerifyEveryBit)22 TEST(UnguessableTokenTest, VerifyEveryBit) {
23   absl::optional<UnguessableToken> token = UnguessableToken::Deserialize(1, 2);
24   ASSERT_TRUE(token.has_value());
25   uint64_t high = 1;
26   uint64_t low = 2;
27 
28   for (uint64_t bit = 1; bit != 0; bit <<= 1) {
29     uint64_t new_high = high ^ bit;
30     absl::optional<UnguessableToken> new_token =
31         UnguessableToken::Deserialize(new_high, low);
32     ASSERT_TRUE(new_token.has_value());
33     EXPECT_FALSE(*token == *new_token);
34   }
35 
36   for (uint64_t bit = 1; bit != 0; bit <<= 1) {
37     uint64_t new_low = low ^ bit;
38     absl::optional<UnguessableToken> new_token =
39         UnguessableToken::Deserialize(high, new_low);
40     ASSERT_TRUE(new_token.has_value());
41     EXPECT_FALSE(*token == *new_token);
42   }
43 }
44 
TEST(UnguessableTokenTest,VerifyEqualityOperators)45 TEST(UnguessableTokenTest, VerifyEqualityOperators) {
46   // Deserialize is used for testing purposes.
47   // Use UnguessableToken::Create() in production code instead.
48   UnguessableToken token = UnguessableToken::Deserialize(1, 2).value();
49   UnguessableToken same_token = UnguessableToken::Deserialize(1, 2).value();
50   UnguessableToken diff_token = UnguessableToken::Deserialize(1, 3).value();
51   UnguessableToken empty_token;
52 
53   EXPECT_TRUE(token == token);
54   EXPECT_FALSE(token != token);
55 
56   EXPECT_TRUE(token == same_token);
57   EXPECT_FALSE(token != same_token);
58 
59   EXPECT_FALSE(token == diff_token);
60   EXPECT_FALSE(diff_token == token);
61   EXPECT_TRUE(token != diff_token);
62   EXPECT_TRUE(diff_token != token);
63 
64   EXPECT_TRUE(empty_token == empty_token);
65   EXPECT_FALSE(empty_token != empty_token);
66   for (const UnguessableToken& this_token : {token, same_token, diff_token}) {
67     EXPECT_FALSE(this_token == empty_token);
68     EXPECT_TRUE(this_token != empty_token);
69   }
70 }
71 
TEST(UnguessableTokenTest,VerifyConstructors)72 TEST(UnguessableTokenTest, VerifyConstructors) {
73   UnguessableToken token = UnguessableToken::Create();
74   EXPECT_FALSE(token.is_empty());
75   EXPECT_TRUE(token);
76 
77   UnguessableToken copied_token(token);
78   EXPECT_TRUE(copied_token);
79   EXPECT_EQ(token, copied_token);
80 
81   UnguessableToken uninitialized;
82   EXPECT_TRUE(uninitialized.is_empty());
83   EXPECT_FALSE(uninitialized);
84 
85   EXPECT_TRUE(UnguessableToken().is_empty());
86   EXPECT_FALSE(UnguessableToken());
87 }
88 
TEST(UnguessableTokenTest,VerifySerialization)89 TEST(UnguessableTokenTest, VerifySerialization) {
90   UnguessableToken token = UnguessableToken::Create();
91 
92   uint64_t high = token.GetHighForSerialization();
93   uint64_t low = token.GetLowForSerialization();
94 
95   EXPECT_TRUE(high);
96   EXPECT_TRUE(low);
97 
98   absl::optional<UnguessableToken> Deserialized =
99       UnguessableToken::Deserialize(high, low);
100   ASSERT_TRUE(Deserialized.has_value());
101   EXPECT_EQ(token, *Deserialized);
102 }
103 
104 // Common case (~88% of the time) - no leading zeroes in high_ nor low_.
TEST(UnguessableTokenTest,VerifyToString1)105 TEST(UnguessableTokenTest, VerifyToString1) {
106   UnguessableToken token =
107       UnguessableToken::Deserialize(0x1234567890ABCDEF, 0xFEDCBA0987654321)
108           .value();
109   std::string expected = "1234567890ABCDEFFEDCBA0987654321";
110 
111   EXPECT_EQ(expected, token.ToString());
112 
113   std::string expected_stream = "(1234567890ABCDEFFEDCBA0987654321)";
114   std::stringstream stream;
115   stream << token;
116   EXPECT_EQ(expected_stream, stream.str());
117 }
118 
119 // Less common case - leading zeroes in high_ or low_ (testing with both).
TEST(UnguessableTokenTest,VerifyToString2)120 TEST(UnguessableTokenTest, VerifyToString2) {
121   UnguessableToken token = UnguessableToken::Deserialize(0x123, 0xABC).value();
122   std::string expected = "00000000000001230000000000000ABC";
123 
124   EXPECT_EQ(expected, token.ToString());
125 
126   std::string expected_stream = "(00000000000001230000000000000ABC)";
127   std::stringstream stream;
128   stream << token;
129   EXPECT_EQ(expected_stream, stream.str());
130 }
131 
TEST(UnguessableTokenTest,VerifyToStringUniqueness)132 TEST(UnguessableTokenTest, VerifyToStringUniqueness) {
133   const UnguessableToken token1 =
134       UnguessableToken::Deserialize(0x0000000012345678, 0x0000000123456789)
135           .value();
136   const UnguessableToken token2 =
137       UnguessableToken::Deserialize(0x0000000123456781, 0x0000000023456789)
138           .value();
139   EXPECT_NE(token1.ToString(), token2.ToString());
140 }
141 
TEST(UnguessableTokenTest,VerifyDeserializeZeroes)142 TEST(UnguessableTokenTest, VerifyDeserializeZeroes) {
143   absl::optional<UnguessableToken> token = UnguessableToken::Deserialize(0, 0);
144 
145   EXPECT_FALSE(token.has_value());
146 }
147 
TEST(UnguessableTokenTest,VerifySmallerThanOperator)148 TEST(UnguessableTokenTest, VerifySmallerThanOperator) {
149   // Deserialize is used for testing purposes.
150   // Use UnguessableToken::Create() in production code instead.
151   {
152     SCOPED_TRACE("a.low < b.low and a.high == b.high.");
153     TestSmallerThanOperator(UnguessableToken::Deserialize(0, 1).value(),
154                             UnguessableToken::Deserialize(0, 5).value());
155   }
156   {
157     SCOPED_TRACE("a.low == b.low and a.high < b.high.");
158     TestSmallerThanOperator(UnguessableToken::Deserialize(1, 0).value(),
159                             UnguessableToken::Deserialize(5, 0).value());
160   }
161   {
162     SCOPED_TRACE("a.low < b.low and a.high < b.high.");
163     TestSmallerThanOperator(UnguessableToken::Deserialize(1, 1).value(),
164                             UnguessableToken::Deserialize(5, 5).value());
165   }
166   {
167     SCOPED_TRACE("a.low > b.low and a.high < b.high.");
168     TestSmallerThanOperator(UnguessableToken::Deserialize(1, 10).value(),
169                             UnguessableToken::Deserialize(10, 1).value());
170   }
171 }
172 
TEST(UnguessableTokenTest,VerifyHash)173 TEST(UnguessableTokenTest, VerifyHash) {
174   UnguessableToken token = UnguessableToken::Create();
175 
176   EXPECT_EQ(base::HashInts64(token.GetHighForSerialization(),
177                              token.GetLowForSerialization()),
178             UnguessableTokenHash()(token));
179 }
180 
TEST(UnguessableTokenTest,VerifyBasicUniqueness)181 TEST(UnguessableTokenTest, VerifyBasicUniqueness) {
182   EXPECT_NE(UnguessableToken::Create(), UnguessableToken::Create());
183 
184   UnguessableToken token = UnguessableToken::Create();
185   EXPECT_NE(token.GetHighForSerialization(), token.GetLowForSerialization());
186 }
187 }
188