1c739cdddSFam Zheng /*
2c739cdddSFam Zheng * QEMU UUID Library
3c739cdddSFam Zheng *
4c739cdddSFam Zheng * Copyright (c) 2016 Red Hat, Inc.
5c739cdddSFam Zheng *
6c739cdddSFam Zheng * This library is free software; you can redistribute it and/or
7c739cdddSFam Zheng * modify it under the terms of the GNU Lesser General Public
8c739cdddSFam Zheng * License as published by the Free Software Foundation; either
98cbff3c1SGan Qixin * version 2.1 of the License, or (at your option) any later version.
10c739cdddSFam Zheng *
11c739cdddSFam Zheng * This library is distributed in the hope that it will be useful,
12c739cdddSFam Zheng * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c739cdddSFam Zheng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14c739cdddSFam Zheng * Lesser General Public License for more details.
15c739cdddSFam Zheng *
16c739cdddSFam Zheng * You should have received a copy of the GNU Lesser General Public
17c739cdddSFam Zheng * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18c739cdddSFam Zheng *
19c739cdddSFam Zheng */
20c739cdddSFam Zheng
21c739cdddSFam Zheng #include "qemu/osdep.h"
22c739cdddSFam Zheng #include "qemu/uuid.h"
23c739cdddSFam Zheng
24c739cdddSFam Zheng struct {
25c739cdddSFam Zheng const char *uuidstr;
26c739cdddSFam Zheng QemuUUID uuid;
27c739cdddSFam Zheng bool uuidstr_is_valid;
28c739cdddSFam Zheng bool check_unparse;
29c739cdddSFam Zheng } uuid_test_data[] = {
30c739cdddSFam Zheng { /* Normal */
31c739cdddSFam Zheng "586ece27-7f09-41e0-9e74-e901317e9d42",
32c739cdddSFam Zheng { { {
33c739cdddSFam Zheng 0x58, 0x6e, 0xce, 0x27, 0x7f, 0x09, 0x41, 0xe0,
34c739cdddSFam Zheng 0x9e, 0x74, 0xe9, 0x01, 0x31, 0x7e, 0x9d, 0x42,
35c739cdddSFam Zheng } } },
36c739cdddSFam Zheng true, true,
37c739cdddSFam Zheng }, { /* NULL */
38c739cdddSFam Zheng "00000000-0000-0000-0000-000000000000",
39c739cdddSFam Zheng { },
40c739cdddSFam Zheng true, true,
41c739cdddSFam Zheng }, { /* Upper case */
42c739cdddSFam Zheng "0CC6C752-3961-4028-A286-C05CC616D396",
43c739cdddSFam Zheng { { {
44c739cdddSFam Zheng 0x0c, 0xc6, 0xc7, 0x52, 0x39, 0x61, 0x40, 0x28,
45c739cdddSFam Zheng 0xa2, 0x86, 0xc0, 0x5c, 0xc6, 0x16, 0xd3, 0x96,
46c739cdddSFam Zheng } } },
47c739cdddSFam Zheng true, false,
48c739cdddSFam Zheng }, { /* Mixed case */
49c739cdddSFam Zheng "0CC6C752-3961-4028-a286-c05cc616D396",
50c739cdddSFam Zheng { { {
51c739cdddSFam Zheng 0x0c, 0xc6, 0xc7, 0x52, 0x39, 0x61, 0x40, 0x28,
52c739cdddSFam Zheng 0xa2, 0x86, 0xc0, 0x5c, 0xc6, 0x16, 0xd3, 0x96,
53c739cdddSFam Zheng } } },
54c739cdddSFam Zheng true, false,
55c739cdddSFam Zheng }, { /* Empty */
56c739cdddSFam Zheng ""
57c739cdddSFam Zheng }, { /* Too short */
58c739cdddSFam Zheng "abc",
59c739cdddSFam Zheng }, { /* Non-hex */
60c739cdddSFam Zheng "abcdefgh-0000-0000-0000-000000000000",
61c739cdddSFam Zheng }, { /* No '-' */
62c739cdddSFam Zheng "0cc6c75239614028a286c05cc616d396",
63c739cdddSFam Zheng }, { /* '-' in wrong position */
64c739cdddSFam Zheng "0cc6c-7523961-4028-a286-c05cc616d396",
65c739cdddSFam Zheng }, { /* Double '-' */
66c739cdddSFam Zheng "0cc6c752--3961-4028-a286-c05cc616d396",
67c739cdddSFam Zheng }, { /* Too long */
68c739cdddSFam Zheng "0000000000000000000000000000000000000000000000",
69c739cdddSFam Zheng }, { /* Invalid char in the beginning */
70c739cdddSFam Zheng ")cc6c752-3961-4028-a286-c05cc616d396",
71c739cdddSFam Zheng }, { /* Invalid char in the beginning, in extra */
72c739cdddSFam Zheng ")0cc6c752-3961-4028-a286-c05cc616d396",
73c739cdddSFam Zheng }, { /* Invalid char in the middle */
74c739cdddSFam Zheng "0cc6c752-39*1-4028-a286-c05cc616d396",
75c739cdddSFam Zheng }, { /* Invalid char in the middle, in extra */
76c739cdddSFam Zheng "0cc6c752-39*61-4028-a286-c05cc616d396",
77c739cdddSFam Zheng }, { /* Invalid char in the end */
78c739cdddSFam Zheng "0cc6c752-3961-4028-a286-c05cc616d39&",
79c739cdddSFam Zheng }, { /* Invalid char in the end, in extra */
80c739cdddSFam Zheng "0cc6c752-3961-4028-a286-c05cc616d396&",
81c739cdddSFam Zheng }, { /* Short end and trailing space */
82c739cdddSFam Zheng "0cc6c752-3961-4028-a286-c05cc616d39 ",
83c739cdddSFam Zheng }, { /* Leading space and short end */
84c739cdddSFam Zheng " 0cc6c752-3961-4028-a286-c05cc616d39",
85c739cdddSFam Zheng },
86c739cdddSFam Zheng };
87c739cdddSFam Zheng
uuid_is_valid(QemuUUID * uuid)88c739cdddSFam Zheng static inline bool uuid_is_valid(QemuUUID *uuid)
89c739cdddSFam Zheng {
90c739cdddSFam Zheng return qemu_uuid_is_null(uuid) ||
91c739cdddSFam Zheng ((uuid->data[6] & 0xf0) == 0x40 && (uuid->data[8] & 0xc0) == 0x80);
92c739cdddSFam Zheng }
93c739cdddSFam Zheng
test_uuid_generate(void)94c739cdddSFam Zheng static void test_uuid_generate(void)
95c739cdddSFam Zheng {
96bfab1aedSRoman Kagan QemuUUID uuid_not_null = { { {
97bfab1aedSRoman Kagan 0x58, 0x6e, 0xce, 0x27, 0x7f, 0x09, 0x41, 0xe0,
98bfab1aedSRoman Kagan 0x9e, 0x74, 0xe9, 0x01, 0x31, 0x7e, 0x9d, 0x42
99bfab1aedSRoman Kagan } } };
100c739cdddSFam Zheng QemuUUID uuid;
101c739cdddSFam Zheng int i;
102c739cdddSFam Zheng
103c739cdddSFam Zheng for (i = 0; i < 100; ++i) {
104c739cdddSFam Zheng qemu_uuid_generate(&uuid);
105c739cdddSFam Zheng g_assert(uuid_is_valid(&uuid));
106bfab1aedSRoman Kagan g_assert_false(qemu_uuid_is_null(&uuid));
107bfab1aedSRoman Kagan g_assert_false(qemu_uuid_is_equal(&uuid_not_null, &uuid));
108c739cdddSFam Zheng }
109c739cdddSFam Zheng }
110c739cdddSFam Zheng
test_uuid_is_null(void)111c739cdddSFam Zheng static void test_uuid_is_null(void)
112c739cdddSFam Zheng {
113c739cdddSFam Zheng QemuUUID uuid_null = { };
114c739cdddSFam Zheng QemuUUID uuid_not_null = { { {
115c739cdddSFam Zheng 0x58, 0x6e, 0xce, 0x27, 0x7f, 0x09, 0x41, 0xe0,
116c739cdddSFam Zheng 0x9e, 0x74, 0xe9, 0x01, 0x31, 0x7e, 0x9d, 0x42
117c739cdddSFam Zheng } } };
118c739cdddSFam Zheng QemuUUID uuid_not_null_2 = { { { 1 } } };
119c739cdddSFam Zheng
120c739cdddSFam Zheng g_assert(qemu_uuid_is_null(&uuid_null));
121c739cdddSFam Zheng g_assert_false(qemu_uuid_is_null(&uuid_not_null));
122c739cdddSFam Zheng g_assert_false(qemu_uuid_is_null(&uuid_not_null_2));
123c739cdddSFam Zheng }
124c739cdddSFam Zheng
test_uuid_parse(void)125c739cdddSFam Zheng static void test_uuid_parse(void)
126c739cdddSFam Zheng {
127c739cdddSFam Zheng int i, r;
128c739cdddSFam Zheng
129c739cdddSFam Zheng for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
130c739cdddSFam Zheng QemuUUID uuid;
131c739cdddSFam Zheng bool is_valid = uuid_test_data[i].uuidstr_is_valid;
132c739cdddSFam Zheng
133c739cdddSFam Zheng r = qemu_uuid_parse(uuid_test_data[i].uuidstr, &uuid);
134c739cdddSFam Zheng g_assert_cmpint(!r, ==, is_valid);
135c739cdddSFam Zheng if (is_valid) {
136c739cdddSFam Zheng g_assert_cmpint(is_valid, ==, uuid_is_valid(&uuid));
137c739cdddSFam Zheng g_assert_cmpmem(&uuid_test_data[i].uuid, sizeof(uuid),
138c739cdddSFam Zheng &uuid, sizeof(uuid));
139c739cdddSFam Zheng }
140c739cdddSFam Zheng }
141c739cdddSFam Zheng }
142c739cdddSFam Zheng
test_uuid_unparse(void)143c739cdddSFam Zheng static void test_uuid_unparse(void)
144c739cdddSFam Zheng {
145c739cdddSFam Zheng int i;
146c739cdddSFam Zheng
147c739cdddSFam Zheng for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
148*721da039SCédric Le Goater char out[UUID_STR_LEN];
149c739cdddSFam Zheng
150c739cdddSFam Zheng if (!uuid_test_data[i].check_unparse) {
151c739cdddSFam Zheng continue;
152c739cdddSFam Zheng }
153c739cdddSFam Zheng qemu_uuid_unparse(&uuid_test_data[i].uuid, out);
154c739cdddSFam Zheng g_assert_cmpstr(uuid_test_data[i].uuidstr, ==, out);
155c739cdddSFam Zheng }
156c739cdddSFam Zheng }
157c739cdddSFam Zheng
test_uuid_unparse_strdup(void)158c739cdddSFam Zheng static void test_uuid_unparse_strdup(void)
159c739cdddSFam Zheng {
160c739cdddSFam Zheng int i;
161c739cdddSFam Zheng
162c739cdddSFam Zheng for (i = 0; i < ARRAY_SIZE(uuid_test_data); i++) {
163c739cdddSFam Zheng char *out;
164c739cdddSFam Zheng
165c739cdddSFam Zheng if (!uuid_test_data[i].check_unparse) {
166c739cdddSFam Zheng continue;
167c739cdddSFam Zheng }
168c739cdddSFam Zheng out = qemu_uuid_unparse_strdup(&uuid_test_data[i].uuid);
169c739cdddSFam Zheng g_assert_cmpstr(uuid_test_data[i].uuidstr, ==, out);
170d9c05e50SMarc-André Lureau g_free(out);
171c739cdddSFam Zheng }
172c739cdddSFam Zheng }
173c739cdddSFam Zheng
test_uuid_hash(void)174a6ceee59SAlbert Esteve static void test_uuid_hash(void)
175a6ceee59SAlbert Esteve {
176a6ceee59SAlbert Esteve QemuUUID uuid;
177a6ceee59SAlbert Esteve int i;
178a6ceee59SAlbert Esteve
179a6ceee59SAlbert Esteve for (i = 0; i < 100; i++) {
180a6ceee59SAlbert Esteve qemu_uuid_generate(&uuid);
181a6ceee59SAlbert Esteve /* Obtain the UUID hash */
182a6ceee59SAlbert Esteve uint32_t hash_a = qemu_uuid_hash(&uuid);
183a6ceee59SAlbert Esteve int data_idx = g_random_int_range(0, 15);
184a6ceee59SAlbert Esteve /* Change a single random byte of the UUID */
185a6ceee59SAlbert Esteve if (uuid.data[data_idx] < 0xFF) {
186a6ceee59SAlbert Esteve uuid.data[data_idx]++;
187a6ceee59SAlbert Esteve } else {
188a6ceee59SAlbert Esteve uuid.data[data_idx]--;
189a6ceee59SAlbert Esteve }
190a6ceee59SAlbert Esteve /* Obtain the UUID hash again */
191a6ceee59SAlbert Esteve uint32_t hash_b = qemu_uuid_hash(&uuid);
192a6ceee59SAlbert Esteve /*
193a6ceee59SAlbert Esteve * Both hashes shall be different (avoid collision)
194a6ceee59SAlbert Esteve * for any change in the UUID fields
195a6ceee59SAlbert Esteve */
196a6ceee59SAlbert Esteve g_assert_cmpint(hash_a, !=, hash_b);
197a6ceee59SAlbert Esteve }
198a6ceee59SAlbert Esteve }
199a6ceee59SAlbert Esteve
main(int argc,char ** argv)200c739cdddSFam Zheng int main(int argc, char **argv)
201c739cdddSFam Zheng {
202c739cdddSFam Zheng g_test_init(&argc, &argv, NULL);
203c739cdddSFam Zheng g_test_add_func("/uuid/is_null", test_uuid_is_null);
204bfab1aedSRoman Kagan g_test_add_func("/uuid/generate", test_uuid_generate);
205c739cdddSFam Zheng g_test_add_func("/uuid/parse", test_uuid_parse);
206c739cdddSFam Zheng g_test_add_func("/uuid/unparse", test_uuid_unparse);
207c739cdddSFam Zheng g_test_add_func("/uuid/unparse_strdup", test_uuid_unparse_strdup);
208a6ceee59SAlbert Esteve g_test_add_func("/uuid/hash", test_uuid_hash);
209c739cdddSFam Zheng
210c739cdddSFam Zheng return g_test_run();
211c739cdddSFam Zheng }
212