blob: e1a769cb9b45147e498ef09133c80f06dffb9aa6 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]3469e7e2010-10-14 20:34:592// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Claudio DeSouzad438f052023-03-30 22:30:455#include "base/uuid.h"
[email protected]3469e7e2010-10-14 20:34:596
avi9b6f42932015-12-26 22:15:147#include <stdint.h>
8
Arthur Sonzogni0844a992024-12-12 11:36:209#include <array>
[email protected]3469e7e2010-10-14 20:34:5910#include <limits>
Daniel Hosseinian2ea7563b2020-11-13 21:26:5411#include <set>
Helmut Januschka39688912024-04-05 01:58:3712#include <string_view>
Daniel Hosseinianaa27a00a2020-11-13 00:39:3413#include <unordered_set>
[email protected]3469e7e2010-10-14 20:34:5914
benchan57d121ac2014-09-05 05:08:3215#include "base/strings/string_util.h"
avi9b6f42932015-12-26 22:15:1416#include "build/build_config.h"
[email protected]3469e7e2010-10-14 20:34:5917#include "testing/gtest/include/gtest/gtest.h"
18
brettw7622fbed2015-06-09 20:20:1419namespace base {
20
Daniel Hosseinian16ab8cf2020-11-12 23:18:3821namespace {
22
Claudio DeSouzad438f052023-03-30 22:30:4523// The format of Uuid version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,
Daniel Hosseinian16ab8cf2020-11-12 23:18:3824// where y is one of [8, 9, a, b].
Claudio DeSouzad438f052023-03-30 22:30:4525bool IsValidV4(const Uuid& guid) {
Daniel Hosseinian16ab8cf2020-11-12 23:18:3826 const std::string& lowercase = guid.AsLowercaseString();
27 return guid.is_valid() && lowercase[14] == '4' &&
28 (lowercase[19] == '8' || lowercase[19] == '9' ||
29 lowercase[19] == 'a' || lowercase[19] == 'b');
30}
31
32} // namespace
33
Claudio DeSouzad438f052023-03-30 22:30:4534TEST(UuidTest, UuidBasicUniqueness) {
Daniel Hosseinian16ab8cf2020-11-12 23:18:3835 constexpr int kIterations = 10;
36 for (int i = 0; i < kIterations; ++i) {
Claudio DeSouzad438f052023-03-30 22:30:4537 const Uuid guid1 = Uuid::GenerateRandomV4();
38 const Uuid guid2 = Uuid::GenerateRandomV4();
Daniel Hosseinian16ab8cf2020-11-12 23:18:3839 EXPECT_NE(guid1, guid2);
40 EXPECT_TRUE(guid1.is_valid());
41 EXPECT_TRUE(IsValidV4(guid1));
42 EXPECT_TRUE(guid2.is_valid());
43 EXPECT_TRUE(IsValidV4(guid2));
44 }
45}
46
47namespace {
48
Helmut Januschka39688912024-04-05 01:58:3749void TestUuidValidity(std::string_view input,
50 bool case_insensitive,
51 bool strict) {
Daniel Hosseinian16ab8cf2020-11-12 23:18:3852 SCOPED_TRACE(input);
53 {
Claudio DeSouzad438f052023-03-30 22:30:4554 const Uuid guid = Uuid::ParseCaseInsensitive(input);
Daniel Hosseinian16ab8cf2020-11-12 23:18:3855 EXPECT_EQ(case_insensitive, guid.is_valid());
56 }
57 {
Claudio DeSouzad438f052023-03-30 22:30:4558 const Uuid guid = Uuid::ParseLowercase(input);
Daniel Hosseinian16ab8cf2020-11-12 23:18:3859 EXPECT_EQ(strict, guid.is_valid());
60 }
61}
62
63} // namespace
64
Claudio DeSouzad438f052023-03-30 22:30:4565TEST(UuidTest, Validity) {
66 // Empty Uuid is invalid.
67 EXPECT_FALSE(Uuid().is_valid());
Daniel Hosseinian16ab8cf2020-11-12 23:18:3868
69 enum Parsability { kDoesntParse, kParsesCaseInsensitiveOnly, kAlwaysParses };
70
71 static constexpr struct {
Helmut Januschka39688912024-04-05 01:58:3772 std::string_view input;
Daniel Hosseinian16ab8cf2020-11-12 23:18:3873 Parsability parsability;
Claudio DeSouzad438f052023-03-30 22:30:4574 } kUuidValidity[] = {
Daniel Hosseinian16ab8cf2020-11-12 23:18:3875 {"invalid", kDoesntParse},
76 {"0123456789ab-cdef-fedc-ba98-76543210", kDoesntParse},
77 {"0123456789abcdeffedcba9876543210", kDoesntParse},
78 {"01234567-89Zz-ZzZz-ZzZz-Zz9876543210", kDoesntParse},
79 {"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", kDoesntParse},
80 {"deadbeefWdeadXbeefYdeadZbeefdeadbeef", kDoesntParse},
81 {"XXXdeadbeefWdeadXbeefYdeadZbeefdeadbeefXXX", kDoesntParse},
82 {"01234567-89aB-cDeF-fEdC-bA9876543210", kParsesCaseInsensitiveOnly},
83 {"DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF", kParsesCaseInsensitiveOnly},
84 {"00000000-0000-0000-0000-000000000000", kAlwaysParses},
85 {"deadbeef-dead-beef-dead-beefdeadbeef", kAlwaysParses},
86 };
87
Claudio DeSouzad438f052023-03-30 22:30:4588 for (const auto& validity : kUuidValidity) {
Daniel Hosseinian16ab8cf2020-11-12 23:18:3889 const bool case_insensitive = validity.parsability != kDoesntParse;
90 const bool strict = validity.parsability == kAlwaysParses;
Claudio DeSouzad438f052023-03-30 22:30:4591 TestUuidValidity(validity.input, case_insensitive, strict);
Daniel Hosseinian16ab8cf2020-11-12 23:18:3892 }
93}
94
Claudio DeSouzad438f052023-03-30 22:30:4595TEST(UuidTest, EqualityAndRoundTrip) {
Avi Drissmane3a3dfa42023-03-27 23:51:0596 static constexpr char kCanonicalStr[] =
97 "deadbeef-dead-4eef-bead-beefdeadbeef";
Daniel Hosseinian16ab8cf2020-11-12 23:18:3898
Claudio DeSouzad438f052023-03-30 22:30:4599 const Uuid from_lower =
100 Uuid::ParseCaseInsensitive(ToLowerASCII(kCanonicalStr));
Avi Drissmane3a3dfa42023-03-27 23:51:05101 EXPECT_EQ(kCanonicalStr, from_lower.AsLowercaseString());
Daniel Hosseinian16ab8cf2020-11-12 23:18:38102
Claudio DeSouzad438f052023-03-30 22:30:45103 const Uuid from_upper =
104 Uuid::ParseCaseInsensitive(ToUpperASCII(kCanonicalStr));
Avi Drissmane3a3dfa42023-03-27 23:51:05105 EXPECT_EQ(kCanonicalStr, from_upper.AsLowercaseString());
Daniel Hosseinian16ab8cf2020-11-12 23:18:38106
107 EXPECT_EQ(from_lower, from_upper);
108
Claudio DeSouzad438f052023-03-30 22:30:45109 // Invalid Uuids are equal.
110 EXPECT_EQ(Uuid(), Uuid());
Daniel Hosseinian16ab8cf2020-11-12 23:18:38111}
112
Claudio DeSouzad438f052023-03-30 22:30:45113TEST(UuidTest, UnorderedSet) {
114 std::unordered_set<Uuid, UuidHash> guid_set;
Daniel Hosseinianaa27a00a2020-11-13 00:39:34115
Claudio DeSouzad438f052023-03-30 22:30:45116 static constexpr char kUuid1[] = "01234567-89ab-cdef-fedc-ba9876543210";
117 guid_set.insert(Uuid::ParseCaseInsensitive(ToLowerASCII(kUuid1)));
Daniel Hosseinianaa27a00a2020-11-13 00:39:34118 EXPECT_EQ(1u, guid_set.size());
Claudio DeSouzad438f052023-03-30 22:30:45119 guid_set.insert(Uuid::ParseCaseInsensitive(ToUpperASCII(kUuid1)));
Daniel Hosseinianaa27a00a2020-11-13 00:39:34120 EXPECT_EQ(1u, guid_set.size());
121
Claudio DeSouzad438f052023-03-30 22:30:45122 static constexpr char kUuid2[] = "deadbeef-dead-beef-dead-beefdeadbeef";
123 guid_set.insert(Uuid::ParseCaseInsensitive(ToLowerASCII(kUuid2)));
Daniel Hosseinianaa27a00a2020-11-13 00:39:34124 EXPECT_EQ(2u, guid_set.size());
Claudio DeSouzad438f052023-03-30 22:30:45125 guid_set.insert(Uuid::ParseCaseInsensitive(ToUpperASCII(kUuid2)));
Daniel Hosseinianaa27a00a2020-11-13 00:39:34126 EXPECT_EQ(2u, guid_set.size());
127}
128
Claudio DeSouzad438f052023-03-30 22:30:45129TEST(UuidTest, Set) {
130 std::set<Uuid> guid_set;
Daniel Hosseinian2ea7563b2020-11-13 21:26:54131
Claudio DeSouzad438f052023-03-30 22:30:45132 static constexpr char kUuid1[] = "01234567-89ab-cdef-0123-456789abcdef";
133 const Uuid guid1 = Uuid::ParseLowercase(kUuid1);
Daniel Hosseinian2ea7563b2020-11-13 21:26:54134 ASSERT_TRUE(guid1.is_valid());
135 guid_set.insert(guid1);
136
Claudio DeSouzad438f052023-03-30 22:30:45137 static constexpr char kUuid2[] = "deadbeef-dead-beef-dead-beefdeadbeef";
138 const Uuid guid2 = Uuid::ParseLowercase(kUuid2);
Daniel Hosseinian2ea7563b2020-11-13 21:26:54139 ASSERT_TRUE(guid2.is_valid());
140 guid_set.insert(guid2);
141
Claudio DeSouzad438f052023-03-30 22:30:45142 // Test that the order of the Uuids was preserved.
Daniel Hosseinian2ea7563b2020-11-13 21:26:54143 auto it = guid_set.begin();
144 EXPECT_EQ(guid1, *it);
145 ++it;
146 EXPECT_EQ(guid2, *it);
147 ++it;
148 EXPECT_EQ(guid_set.end(), it);
149}
150
Claudio DeSouzad438f052023-03-30 22:30:45151TEST(UuidTest, Compare) {
152 static constexpr char kUuid[] = "21abd97f-73e8-4b88-9389-a9fee6abda5e";
153 static constexpr char kUuidLess[] = "1e0dcaca-9e7c-4f4b-bcc6-e4c02b0c99df";
154 static constexpr char kUuidGreater[] = "6eeb1bc8-186b-433c-9d6a-a827bc96b2d4";
Daniel Hosseinian2ea7563b2020-11-13 21:26:54155
Claudio DeSouzad438f052023-03-30 22:30:45156 const Uuid guid = Uuid::ParseLowercase(kUuid);
157 const Uuid guid_eq = Uuid::ParseLowercase(kUuid);
158 const Uuid guid_lt = Uuid::ParseLowercase(kUuidLess);
159 const Uuid guid_gt = Uuid::ParseLowercase(kUuidGreater);
160 const Uuid guid_invalid = Uuid();
Daniel Hosseinian2ea7563b2020-11-13 21:26:54161
162 EXPECT_TRUE(guid_eq == guid);
163 EXPECT_FALSE(guid_eq != guid);
164 EXPECT_FALSE(guid_eq < guid);
165 EXPECT_TRUE(guid_eq <= guid);
166 EXPECT_FALSE(guid_eq > guid);
167 EXPECT_TRUE(guid_eq >= guid);
168
169 EXPECT_FALSE(guid_lt == guid);
170 EXPECT_TRUE(guid_lt != guid);
171 EXPECT_TRUE(guid_lt < guid);
172 EXPECT_TRUE(guid_lt <= guid);
173 EXPECT_FALSE(guid_lt > guid);
174 EXPECT_FALSE(guid_lt >= guid);
175
176 EXPECT_FALSE(guid_gt == guid);
177 EXPECT_TRUE(guid_gt != guid);
178 EXPECT_FALSE(guid_gt < guid);
179 EXPECT_FALSE(guid_gt <= guid);
180 EXPECT_TRUE(guid_gt > guid);
181 EXPECT_TRUE(guid_gt >= guid);
182
Claudio DeSouzad438f052023-03-30 22:30:45183 // Invalid Uuids are the "least".
Daniel Hosseinian2ea7563b2020-11-13 21:26:54184 EXPECT_FALSE(guid_invalid == guid);
185 EXPECT_TRUE(guid_invalid != guid);
186 EXPECT_TRUE(guid_invalid < guid);
187 EXPECT_TRUE(guid_invalid <= guid);
188 EXPECT_FALSE(guid_invalid > guid);
189 EXPECT_FALSE(guid_invalid >= guid);
190}
191
brettw7622fbed2015-06-09 20:20:14192} // namespace base