Imported Upstream version 0.19.1
[platform/upstream/p11-kit.git] / trust / tests / test-index.c
1 /*
2  * Copyright (c) 2012 Red Hat Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *     * Redistributions of source code must retain the above
9  *       copyright notice, this list of conditions and the
10  *       following disclaimer.
11  *     * Redistributions in binary form must reproduce the
12  *       above copyright notice, this list of conditions and
13  *       the following disclaimer in the documentation and/or
14  *       other materials provided with the distribution.
15  *     * The names of contributors to this software may not be
16  *       used to endorse or promote products derived from this
17  *       software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30  * DAMAGE.
31  *
32  * Author: Stef Walter <stefw@gnome.org>
33  */
34
35 #include "config.h"
36 #include "test.h"
37 #include "test-trust.h"
38
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "attrs.h"
45 #include "debug.h"
46 #include "index.h"
47 #include "message.h"
48
49 struct {
50         p11_index *index;
51 } test;
52
53 static void
54 setup (void *unused)
55 {
56         test.index = p11_index_new (NULL, NULL, NULL);
57         assert_ptr_not_null (test.index);
58 }
59
60 static void
61 teardown (void *unused)
62 {
63         p11_index_free (test.index);
64         memset (&test, 0, sizeof (test));
65 }
66
67 static void
68 test_take_lookup (void)
69 {
70         CK_ATTRIBUTE original[] = {
71                 { CKA_LABEL, "yay", 3 },
72                 { CKA_VALUE, "eight", 5 },
73                 { CKA_INVALID }
74         };
75
76         CK_ATTRIBUTE *attrs;
77         CK_ATTRIBUTE *check;
78         CK_OBJECT_HANDLE handle;
79         CK_RV rv;
80
81         attrs = p11_attrs_dup (original);
82         rv = p11_index_take (test.index, attrs, &handle);
83         assert (rv == CKR_OK);
84
85         check = p11_index_lookup (test.index, handle);
86         test_check_attrs (original, check);
87
88         check = p11_index_lookup (test.index, 1UL);
89         assert_ptr_eq (NULL, check);
90
91         check = p11_index_lookup (test.index, 0UL);
92         assert_ptr_eq (NULL, check);
93 }
94
95 static void
96 test_add_lookup (void)
97 {
98         CK_ATTRIBUTE original[] = {
99                 { CKA_LABEL, "yay", 3 },
100                 { CKA_VALUE, "eight", 5 },
101                 { CKA_INVALID }
102         };
103
104         CK_ATTRIBUTE *check;
105         CK_OBJECT_HANDLE handle;
106         CK_RV rv;
107
108         rv = p11_index_add (test.index, original, 2, &handle);
109         assert (rv == CKR_OK);
110
111         check = p11_index_lookup (test.index, handle);
112         test_check_attrs (original, check);
113 }
114
115 static void
116 test_size (void)
117 {
118         static CK_ATTRIBUTE original[] = {
119                 { CKA_LABEL, "yay", 3 },
120                 { CKA_VALUE, "eight", 5 },
121                 { CKA_INVALID }
122         };
123
124         CK_RV rv;
125
126         rv = p11_index_add (test.index, original, 2, NULL);
127         assert (rv == CKR_OK);
128
129         rv = p11_index_add (test.index, original, 2, NULL);
130         assert (rv == CKR_OK);
131
132         rv = p11_index_add (test.index, original, 2, NULL);
133         assert (rv == CKR_OK);
134
135         assert_num_eq (3, p11_index_size (test.index));
136 }
137
138 static int
139 compar_ulong (const void *one,
140               const void *two)
141 {
142         const CK_ULONG *u1 = one;
143         const CK_ULONG *u2 = two;
144
145         if (*u1 == *u2)
146                 return 0;
147         if (*u1 < *u2)
148                 return -1;
149         return 1;
150 }
151
152 static void
153 test_snapshot (void)
154 {
155         CK_ATTRIBUTE original[] = {
156                 { CKA_LABEL, "yay", 3 },
157                 { CKA_VALUE, "eight", 5 },
158                 { CKA_INVALID }
159         };
160
161         static const int NUM = 16;
162         CK_OBJECT_HANDLE expected[NUM];
163         CK_OBJECT_HANDLE *snapshot;
164         int i;
165
166         for (i = 0; i < NUM; i++)
167                 p11_index_add (test.index, original, 2, expected + i);
168
169         snapshot = p11_index_snapshot (test.index, NULL, NULL, 0);
170         assert_ptr_not_null (snapshot);
171
172         for (i = 0; i < NUM; i++)
173                 assert (snapshot[i] != 0);
174         assert (snapshot[NUM] == 0);
175
176         qsort (snapshot, NUM, sizeof (CK_OBJECT_HANDLE), compar_ulong);
177
178         for (i = 0; i < NUM; i++)
179                 assert_num_eq (expected[i], snapshot[i]);
180
181         free (snapshot);
182 }
183
184 static void
185 test_snapshot_base (void)
186 {
187         CK_ATTRIBUTE original[] = {
188                 { CKA_LABEL, "yay", 3 },
189                 { CKA_VALUE, "eight", 5 },
190                 { CKA_INVALID }
191         };
192
193         static const int NUM = 16;
194         CK_OBJECT_HANDLE expected[NUM];
195         CK_OBJECT_HANDLE *snapshot;
196         CK_RV rv;
197         int i;
198
199         for (i = 0; i < NUM; i++) {
200                 rv = p11_index_add (test.index, original, 2, expected + i);
201                 assert (rv == CKR_OK);
202         }
203
204         snapshot = p11_index_snapshot (test.index, test.index, NULL, 0);
205         assert_ptr_not_null (snapshot);
206
207         for (i = 0; i < NUM * 2; i++)
208                 assert (snapshot[i] != 0);
209         assert (snapshot[NUM * 2] == 0);
210
211         qsort (snapshot, NUM * 2, sizeof (CK_OBJECT_HANDLE), compar_ulong);
212
213         for (i = 0; i < NUM * 2; i++)
214                 assert_num_eq (expected[i / 2], snapshot[i]);
215
216         free (snapshot);
217 }
218
219 static void
220 test_remove (void)
221 {
222         CK_ATTRIBUTE original[] = {
223                 { CKA_LABEL, "yay", 3 },
224                 { CKA_VALUE, "eight", 5 },
225                 { CKA_INVALID }
226         };
227
228         CK_ATTRIBUTE *attrs;
229         CK_ATTRIBUTE *check;
230         CK_OBJECT_HANDLE handle;
231         CK_RV rv;
232
233         attrs = p11_attrs_dup (original);
234         rv = p11_index_take (test.index, attrs, &handle);
235         assert (rv == CKR_OK);
236
237         check = p11_index_lookup (test.index, handle);
238         assert_ptr_eq (attrs, check);
239
240         rv = p11_index_remove (test.index, 1UL);
241         assert (rv == CKR_OBJECT_HANDLE_INVALID);
242
243         rv = p11_index_remove (test.index, handle);
244         assert (rv == CKR_OK);
245
246         check = p11_index_lookup (test.index, handle);
247         assert_ptr_eq (NULL, check);
248 }
249
250 static void
251 test_set (void)
252 {
253         CK_ATTRIBUTE original[] = {
254                 { CKA_LABEL, "yay", 3 },
255                 { CKA_VALUE, "eight", 5 },
256                 { CKA_INVALID }
257         };
258
259         CK_ATTRIBUTE change = { CKA_LABEL, "naay", 4 };
260
261         CK_ATTRIBUTE changed[] = {
262                 { CKA_LABEL, "naay", 4 },
263                 { CKA_VALUE, "eight", 5 },
264                 { CKA_INVALID }
265         };
266
267         CK_ATTRIBUTE *attrs;
268         CK_ATTRIBUTE *check;
269         CK_OBJECT_HANDLE handle;
270         CK_RV rv;
271
272         attrs = p11_attrs_dup (original);
273         rv = p11_index_take (test.index, attrs, &handle);
274         assert (rv == CKR_OK);
275
276         check = p11_index_lookup (test.index, handle);
277         test_check_attrs (original, check);
278
279         rv = p11_index_set (test.index, handle, &change, 1);
280         assert (rv == CKR_OK);
281
282         check = p11_index_lookup (test.index, handle);
283         test_check_attrs (changed, check);
284
285         rv = p11_index_set (test.index, 1UL, &change, 1);
286         assert (rv == CKR_OBJECT_HANDLE_INVALID);
287 }
288
289 static void
290 test_update (void)
291 {
292         CK_ATTRIBUTE original[] = {
293                 { CKA_LABEL, "yay", 3 },
294                 { CKA_VALUE, "eight", 5 },
295                 { CKA_INVALID }
296         };
297
298         CK_ATTRIBUTE change = { CKA_LABEL, "naay", 4 };
299
300         CK_ATTRIBUTE changed[] = {
301                 { CKA_LABEL, "naay", 4 },
302                 { CKA_VALUE, "eight", 5 },
303                 { CKA_INVALID }
304         };
305
306         CK_ATTRIBUTE *attrs;
307         CK_ATTRIBUTE *check;
308         CK_OBJECT_HANDLE handle;
309         CK_RV rv;
310
311         attrs = p11_attrs_dup (original);
312         rv = p11_index_take (test.index, attrs, &handle);
313         assert (rv == CKR_OK);
314
315         check = p11_index_lookup (test.index, handle);
316         test_check_attrs (original, check);
317
318         attrs = p11_attrs_build (NULL, &change, NULL);
319         rv = p11_index_update (test.index, handle, attrs);
320         assert (rv == CKR_OK);
321
322         check = p11_index_lookup (test.index, handle);
323         test_check_attrs (changed, check);
324
325         attrs = p11_attrs_build (NULL, &change, NULL);
326         rv = p11_index_update (test.index, 1L, attrs);
327         assert (rv == CKR_OBJECT_HANDLE_INVALID);
328 }
329
330 static void
331 test_find (void)
332 {
333         CK_ATTRIBUTE first[] = {
334                 { CKA_LABEL, "yay", 3 },
335                 { CKA_VALUE, "one", 3 },
336                 { CKA_INVALID }
337         };
338
339         CK_ATTRIBUTE second[] = {
340                 { CKA_LABEL, "yay", 3 },
341                 { CKA_VALUE, "two", 3 },
342                 { CKA_INVALID }
343         };
344
345         CK_ATTRIBUTE third[] = {
346                 { CKA_LABEL, "yay", 3 },
347                 { CKA_VALUE, "three", 5 },
348                 { CKA_INVALID }
349         };
350
351         CK_ATTRIBUTE match3[] = {
352                 { CKA_VALUE, "three", 5 },
353                 { CKA_INVALID }
354         };
355
356         CK_ATTRIBUTE match_any[] = {
357                 { CKA_LABEL, "yay", 3 },
358                 { CKA_INVALID }
359         };
360
361         CK_ATTRIBUTE match_none[] = {
362                 { CKA_VALUE, "blonononon", 10 },
363                 { CKA_LABEL, "yay", 3 },
364                 { CKA_INVALID }
365         };
366
367         CK_OBJECT_HANDLE check;
368         CK_OBJECT_HANDLE one;
369         CK_OBJECT_HANDLE two;
370         CK_OBJECT_HANDLE three;
371
372         p11_index_add (test.index, first, 2, &one);
373         p11_index_add (test.index, second, 2, &two);
374         p11_index_add (test.index, third, 2, &three);
375
376         check = p11_index_find (test.index, match3, -1);
377         assert_num_eq (three, check);
378
379         check = p11_index_find (test.index, match3, 1);
380         assert_num_eq (three, check);
381
382         check = p11_index_find (test.index, match_any, -1);
383         assert (check == one || check == two || check == three);
384
385         check = p11_index_find (test.index, match_any, 1);
386         assert (check == one || check == two || check == three);
387
388         check = p11_index_find (test.index, match_none, -1);
389         assert_num_eq (0, check);
390
391         check = p11_index_find (test.index, match_none, 2);
392         assert_num_eq (0, check);
393 }
394
395 static bool
396 handles_are (CK_OBJECT_HANDLE *handles,
397              ...)
398 {
399         CK_OBJECT_HANDLE handle;
400         int count;
401         int num;
402         va_list va;
403         int i;
404
405         if (!handles)
406                 return false;
407
408         /* Count number of handles */
409         for (num = 0; handles[num]; num++);
410
411         va_start (va, handles);
412
413         for (count = 0; true; count++) {
414                 handle = va_arg (va, CK_OBJECT_HANDLE);
415                 if (handle == 0)
416                         break;
417
418                 for (i = 0; handles[i]; i++) {
419                         if (handle == handles[i])
420                                 break;
421                 }
422
423                 if (handles[i] != handle)
424                         return false;
425         }
426
427         va_end (va);
428
429         return (count == num);
430 }
431
432 static void
433 test_find_all (void)
434 {
435         CK_ATTRIBUTE first[] = {
436                 { CKA_LABEL, "odd", 3 },
437                 { CKA_VALUE, "one", 3 },
438                 { CKA_APPLICATION, "test", 4 },
439                 { CKA_INVALID }
440         };
441
442         CK_ATTRIBUTE second[] = {
443                 { CKA_LABEL, "even", 4 },
444                 { CKA_VALUE, "two", 3 },
445                 { CKA_APPLICATION, "test", 4 },
446                 { CKA_INVALID }
447         };
448
449         CK_ATTRIBUTE third[] = {
450                 { CKA_LABEL, "odd", 3 },
451                 { CKA_VALUE, "three", 5 },
452                 { CKA_APPLICATION, "test", 4 },
453                 { CKA_INVALID }
454         };
455
456         CK_ATTRIBUTE match_odd[] = {
457                 { CKA_LABEL, "odd", 3 },
458                 { CKA_APPLICATION, "test", 4 },
459                 { CKA_INVALID }
460         };
461
462         CK_ATTRIBUTE match_3[] = {
463                 { CKA_VALUE, "three", 5 },
464                 { CKA_INVALID }
465         };
466
467         CK_ATTRIBUTE match_any[] = {
468                 { CKA_INVALID }
469         };
470
471         CK_ATTRIBUTE match_none[] = {
472                 { CKA_VALUE, "blonononon", 10 },
473                 { CKA_LABEL, "yay", 3 },
474                 { CKA_INVALID }
475         };
476
477         CK_OBJECT_HANDLE *check;
478         CK_OBJECT_HANDLE one;
479         CK_OBJECT_HANDLE two;
480         CK_OBJECT_HANDLE three;
481
482         p11_index_add (test.index, first, 3, &one);
483         p11_index_add (test.index, second, 3, &two);
484         p11_index_add (test.index, third, 3, &three);
485
486         check = p11_index_find_all (test.index, match_3, -1);
487         assert (handles_are (check, three, 0UL));
488         free (check);
489
490         check = p11_index_find_all (test.index, match_none, -1);
491         assert (handles_are (check, 0UL));
492         free (check);
493
494         check = p11_index_find_all (test.index, match_odd, -1);
495         assert (handles_are (check, one, three, 0UL));
496         free (check);
497
498         check = p11_index_find_all (test.index, match_any, -1);
499         assert (handles_are (check, one, two, three, 0UL));
500         free (check);
501
502         check = p11_index_find_all (test.index, match_none, -1);
503         assert_ptr_not_null (check);
504         assert_num_eq (0, check[0]);
505         free (check);
506
507         /* A double check of this method */
508         one = 0UL;
509         check = &one;
510         assert (!handles_are (check, 29292929, 0UL));
511         assert (!handles_are (NULL, 0UL));
512 }
513
514 static void
515 test_find_realloc (void)
516 {
517         CK_ATTRIBUTE attrs[] = {
518                 { CKA_LABEL, "odd", 3 },
519                 { CKA_VALUE, "one", 3 },
520                 { CKA_APPLICATION, "test", 4 },
521                 { CKA_INVALID }
522         };
523
524         CK_ATTRIBUTE match[] = {
525                 { CKA_INVALID }
526         };
527
528         CK_OBJECT_HANDLE *check;
529         int i;
530
531         for (i = 0; i < 1000; i++)
532                 p11_index_add (test.index, attrs, 3, NULL);
533
534         check = p11_index_find_all (test.index, match, -1);
535         assert_ptr_not_null (check);
536
537         for (i = 0; i < 1000; i++)
538                 assert (check[i] != 0);
539         assert_num_eq (0, check[1000]);
540
541         free (check);
542 }
543
544 static void
545 test_replace_all (void)
546 {
547         CK_ATTRIBUTE first[] = {
548                 { CKA_LABEL, "odd", 3 },
549                 { CKA_VALUE, "one", 3 },
550                 { CKA_APPLICATION, "test", 4 },
551                 { CKA_INVALID }
552         };
553
554         CK_ATTRIBUTE second[] = {
555                 { CKA_LABEL, "even", 4 },
556                 { CKA_VALUE, "two", 3 },
557                 { CKA_APPLICATION, "test", 4 },
558                 { CKA_INVALID }
559         };
560
561         CK_ATTRIBUTE third[] = {
562                 { CKA_LABEL, "odd", 3 },
563                 { CKA_VALUE, "three", 5 },
564                 { CKA_APPLICATION, "test", 4 },
565                 { CKA_INVALID }
566         };
567
568         CK_ATTRIBUTE fifth[] = {
569                 { CKA_LABEL, "odd", 3 },
570                 { CKA_VALUE, "five", 4 },
571                 { CKA_APPLICATION, "test", 4 },
572                 { CKA_INVALID }
573         };
574
575         CK_ATTRIBUTE match[] = {
576                 { CKA_LABEL, "odd", 3 },
577                 { CKA_INVALID }
578         };
579
580         CK_ATTRIBUTE eins[] = {
581                 { CKA_LABEL, "odd", 3 },
582                 { CKA_VALUE, "one", 3 },
583                 { CKA_APPLICATION, "replace", 7 },
584                 { CKA_INVALID }
585         };
586
587         CK_ATTRIBUTE sieben[] = {
588                 { CKA_LABEL, "odd", 3 },
589                 { CKA_VALUE, "seven", 5 },
590                 { CKA_APPLICATION, "replace", 7 },
591                 { CKA_INVALID }
592         };
593
594         CK_ATTRIBUTE neun[] = {
595                 { CKA_LABEL, "odd", 3 },
596                 { CKA_VALUE, "nine", 4 },
597                 { CKA_APPLICATION, "replace", 7 },
598                 { CKA_INVALID }
599         };
600
601         CK_OBJECT_HANDLE check;
602         CK_OBJECT_HANDLE one;
603         CK_OBJECT_HANDLE two;
604         CK_OBJECT_HANDLE three;
605         CK_OBJECT_HANDLE five;
606         p11_array *array;
607         CK_RV rv;
608
609         p11_index_add (test.index, first, 3, &one);
610         assert (one != 0);
611         p11_index_add (test.index, second, 3, &two);
612         assert (two != 0);
613         p11_index_add (test.index, third, 3, &three);
614         assert (three != 0);
615         p11_index_add (test.index, fifth, 3, &five);
616         assert (five != 0);
617
618         array = p11_array_new (p11_attrs_free);
619         p11_array_push (array, p11_attrs_buildn (NULL, eins, 3));
620         p11_array_push (array, p11_attrs_buildn (NULL, sieben, 3));
621         p11_array_push (array, p11_attrs_buildn (NULL, neun, 3));
622
623         rv = p11_index_replace_all (test.index, match, CKA_VALUE, array);
624         assert (rv == CKR_OK);
625
626         assert_num_eq (0, array->num);
627         p11_array_free (array);
628
629         /* eins should have replaced one */
630         check = p11_index_find (test.index, eins, -1);
631         assert_num_eq (one, check);
632
633         /* two should still be around */
634         check = p11_index_find (test.index, second, -1);
635         assert_num_eq (two, check);
636
637         /* three should have been removed */
638         check = p11_index_find (test.index, third, -1);
639         assert_num_eq (0, check);
640
641         /* five should have been removed */
642         check = p11_index_find (test.index, fifth, -1);
643         assert_num_eq (0, check);
644
645         /* sieben should have been added */
646         check = p11_index_find (test.index, sieben, -1);
647         assert (check != one && check != two && check != three && check != five);
648
649         /* neun should have been added */
650         check = p11_index_find (test.index, neun, -1);
651         assert (check != one && check != two && check != three && check != five);
652
653         assert_num_eq (4, p11_index_size (test.index));
654 }
655
656
657 static CK_RV
658 on_build_populate (void *data,
659                    p11_index *index,
660                    CK_ATTRIBUTE **attrs,
661                    CK_ATTRIBUTE *merge)
662 {
663         CK_ATTRIBUTE override[] = {
664                 { CKA_APPLICATION, "vigorous", 8 },
665                 { CKA_LABEL, "naay", 4 },
666                 { CKA_INVALID },
667         };
668
669         assert_str_eq (data, "blah");
670         assert_ptr_not_null (index);
671         assert_ptr_not_null (attrs);
672         assert_ptr_not_null (merge);
673
674         *attrs = p11_attrs_merge (*attrs, merge, true);
675         *attrs = p11_attrs_merge (*attrs, p11_attrs_dup (override), true);
676         return CKR_OK;
677 }
678
679 static void
680 test_build_populate (void)
681 {
682         CK_ATTRIBUTE original[] = {
683                 { CKA_LABEL, "yay", 3 },
684                 { CKA_VALUE, "eight", 5 },
685                 { CKA_INVALID }
686
687         };
688
689         CK_ATTRIBUTE after[] = {
690                 { CKA_LABEL, "naay", 4 },
691                 { CKA_VALUE, "eight", 5 },
692                 { CKA_APPLICATION, "vigorous", 8 },
693                 { CKA_INVALID }
694         };
695
696         CK_OBJECT_HANDLE handle;
697         CK_ATTRIBUTE *check;
698         p11_index *index;
699         CK_RV rv;
700
701         index = p11_index_new (on_build_populate, NULL, "blah");
702         assert_ptr_not_null (index);
703
704         rv = p11_index_add (index, original, 2, &handle);
705         assert (rv == CKR_OK);
706
707         check = p11_index_lookup (index, handle);
708         assert_ptr_not_null (check);
709
710         test_check_attrs (after, check);
711
712         rv = p11_index_set (index, handle, original, 2);
713         assert (rv == CKR_OK);
714
715         check = p11_index_lookup (index, handle);
716         assert_ptr_not_null (check);
717
718         test_check_attrs (after, check);
719
720         p11_index_free (index);
721 }
722
723 static CK_RV
724 on_build_fail (void *data,
725                p11_index *index,
726                CK_ATTRIBUTE **attrs,
727                CK_ATTRIBUTE *merge)
728 {
729         CK_ATTRIBUTE check[] = {
730                 { CKA_LABEL, "nay", 3 },
731                 { CKA_INVALID }
732         };
733
734         assert_str_eq (data, "testo");
735         assert_ptr_not_null (merge);
736
737         if (p11_attrs_match (merge, check))
738                 return CKR_DEVICE_ERROR;
739
740         *attrs = p11_attrs_merge (*attrs, merge, true);
741         return CKR_OK;
742 }
743
744
745 static void
746 test_build_fail (void)
747 {
748         CK_ATTRIBUTE okay[] = {
749                 { CKA_LABEL, "yay", 3 },
750                 { CKA_VALUE, "eight", 5 },
751                 { CKA_INVALID }
752         };
753
754         CK_ATTRIBUTE fails[] = {
755                 { CKA_LABEL, "nay", 3 },
756                 { CKA_VALUE, "eight", 5 },
757                 { CKA_INVALID }
758         };
759
760         CK_OBJECT_HANDLE handle;
761         p11_index *index;
762         CK_RV rv;
763
764         index = p11_index_new (on_build_fail, NULL, "testo");
765         assert_ptr_not_null (index);
766
767         rv = p11_index_add (index, okay, 2, &handle);
768         assert (rv == CKR_OK);
769
770         rv = p11_index_add (index, fails, 2, NULL);
771         assert (rv == CKR_DEVICE_ERROR);
772
773         rv = p11_index_set (index, handle, fails, 2);
774         assert (rv == CKR_DEVICE_ERROR);
775
776         rv = p11_index_set (index, handle, okay, 2);
777         assert (rv == CKR_OK);
778
779         p11_index_free (index);
780 }
781
782 static int on_change_called = 0;
783 static bool on_change_removing = false;
784 static bool on_change_batching = false;
785
786 static void
787 on_change_check (void *data,
788                  p11_index *index,
789                  CK_OBJECT_HANDLE handle,
790                  CK_ATTRIBUTE *attrs)
791 {
792         CK_ATTRIBUTE check[] = {
793                 { CKA_LABEL, "yay", 3 },
794                 { CKA_VALUE, "eight", 5 },
795                 { CKA_INVALID }
796
797         };
798
799         assert_str_eq (data, "change-check");
800         assert_ptr_not_null (index);
801         assert_ptr_not_null (attrs);
802
803         if (!on_change_batching) {
804                 if (on_change_removing)
805                         assert_num_eq (0, handle);
806                 else
807                         assert (handle != 0);
808         }
809
810         test_check_attrs (check, attrs);
811         on_change_called++;
812 }
813
814 static void
815 test_change_called (void)
816 {
817         CK_ATTRIBUTE original[] = {
818                 { CKA_LABEL, "yay", 3 },
819                 { CKA_VALUE, "eight", 5 },
820                 { CKA_INVALID }
821
822         };
823
824         CK_OBJECT_HANDLE handle;
825         p11_index *index;
826         CK_RV rv;
827
828         index = p11_index_new (NULL, on_change_check, "change-check");
829         assert_ptr_not_null (index);
830
831         on_change_removing = false;
832         on_change_called = 0;
833
834         rv = p11_index_add (index, original, 2, NULL);
835         assert (rv == CKR_OK);
836
837         assert_num_eq (1, on_change_called);
838
839         rv = p11_index_add (index, original, 2, NULL);
840         assert (rv == CKR_OK);
841
842         assert_num_eq (2, on_change_called);
843
844         rv = p11_index_add (index, original, 2, &handle);
845         assert (rv == CKR_OK);
846
847         assert_num_eq (3, on_change_called);
848
849         on_change_removing = true;
850
851         rv = p11_index_remove (index, handle);
852         assert (rv == CKR_OK);
853
854         assert_num_eq (4, on_change_called);
855
856         p11_index_free (index);
857 }
858
859 static void
860 test_change_batch (void)
861 {
862         CK_ATTRIBUTE original[] = {
863                 { CKA_LABEL, "yay", 3 },
864                 { CKA_VALUE, "eight", 5 },
865                 { CKA_INVALID }
866
867         };
868
869         CK_OBJECT_HANDLE handle;
870         p11_index *index;
871         CK_RV rv;
872
873         index = p11_index_new (NULL, on_change_check, "change-check");
874         assert_ptr_not_null (index);
875
876         on_change_batching = true;
877         on_change_called = 0;
878
879         p11_index_batch (index);
880
881         assert (p11_index_in_batch (index));
882
883         rv = p11_index_add (index, original, 2, NULL);
884         assert (rv == CKR_OK);
885
886         assert_num_eq (0, on_change_called);
887
888         rv = p11_index_add (index, original, 2, NULL);
889         assert (rv == CKR_OK);
890
891         assert_num_eq (0, on_change_called);
892
893         rv = p11_index_add (index, original, 2, &handle);
894         assert (rv == CKR_OK);
895
896         assert_num_eq (0, on_change_called);
897
898         /* Nested batch is a noop */
899         p11_index_batch (index);
900
901         rv = p11_index_remove (index, handle);
902         assert (rv == CKR_OK);
903
904         assert_num_eq (0, on_change_called);
905
906         /*
907          * Batch finishes when first finish call is called,
908          * even when batches are nested
909          */
910         p11_index_finish (index);
911
912         assert (!p11_index_in_batch (index));
913
914         /*
915          * Only three calls, because later operations on the
916          * same handle override the earlier one.
917          */
918         assert_num_eq (3, on_change_called);
919
920         /* This is a noop */
921         p11_index_finish (index);
922
923         assert (!p11_index_in_batch (index));
924
925         p11_index_free (index);
926 }
927
928 static void
929 on_change_nested (void *data,
930                   p11_index *index,
931                   CK_OBJECT_HANDLE handle,
932                   CK_ATTRIBUTE *attrs)
933 {
934         CK_RV rv;
935
936         CK_ATTRIBUTE second[] = {
937                 { CKA_LABEL, "yay", 3 },
938                 { CKA_VALUE, "eight", 5 },
939                 { CKA_INVALID }
940
941         };
942
943         assert_str_eq (data, "change-nested");
944         on_change_called++;
945
946         /* A nested call */
947         rv = p11_index_add (index, second, 2, NULL);
948         assert (rv == CKR_OK);
949 }
950
951 static void
952 test_change_nested (void)
953 {
954         CK_ATTRIBUTE original[] = {
955                 { CKA_LABEL, "yay", 3 },
956                 { CKA_VALUE, "eight", 5 },
957                 { CKA_INVALID }
958
959         };
960
961         p11_index *index;
962         CK_RV rv;
963
964         index = p11_index_new (NULL, on_change_nested, "change-nested");
965         assert_ptr_not_null (index);
966
967         on_change_called = 0;
968         rv = p11_index_add (index, original, 2, NULL);
969         assert (rv == CKR_OK);
970         assert_num_eq (1, on_change_called);
971
972
973         on_change_called = 0;
974         p11_index_batch (index);
975         rv = p11_index_add (index, original, 2, NULL);
976         assert (rv == CKR_OK);
977         p11_index_finish (index);
978         assert_num_eq (1, on_change_called);
979
980         p11_index_free (index);
981 }
982
983 int
984 main (int argc,
985       char *argv[])
986 {
987         p11_message_quiet ();
988
989         p11_fixture (setup, teardown);
990         p11_test (test_add_lookup, "/index/add_lookup");
991         p11_test (test_take_lookup, "/index/take_lookup");
992         p11_test (test_size, "/index/size");
993         p11_test (test_remove, "/index/remove");
994         p11_test (test_snapshot, "/index/snapshot");
995         p11_test (test_snapshot_base, "/index/snapshot_base");
996         p11_test (test_set, "/index/set");
997         p11_test (test_update, "/index/update");
998         p11_test (test_find, "/index/find");
999         p11_test (test_find_all, "/index/find_all");
1000         p11_test (test_find_realloc, "/index/find_realloc");
1001         p11_test (test_replace_all, "/index/replace_all");
1002
1003         p11_fixture (NULL, NULL);
1004         p11_test (test_build_populate, "/index/build_populate");
1005         p11_test (test_build_fail, "/index/build_fail");
1006         p11_test (test_change_called, "/index/change_called");
1007         p11_test (test_change_batch, "/index/change_batch");
1008         p11_test (test_change_nested, "/index/change_nested");
1009         return p11_test_run (argc, argv);
1010 }