xref: /qemu/tests/unit/test-uuid.c (revision 721da0396cfa0a4859cefb57e32cc79d19d80f54)
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