3 #include "tap-interface.h"
10 #define NUM_RECORDS 1000
12 static bool store_records(struct ntdb_context
*ntdb
)
15 NTDB_DATA key
= { (unsigned char *)&i
, sizeof(i
) };
16 NTDB_DATA data
= { (unsigned char *)&i
, sizeof(i
) };
18 for (i
= 0; i
< NUM_RECORDS
; i
++)
19 if (ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) != 0)
25 unsigned int records
[NUM_RECORDS
];
29 static int trav(struct ntdb_context
*ntdb
, NTDB_DATA key
, NTDB_DATA dbuf
, void *p
)
31 struct trav_data
*td
= p
;
34 memcpy(&val
, dbuf
.dptr
, dbuf
.dsize
);
35 td
->records
[td
->calls
++] = val
;
39 /* Since ntdb_nextkey frees dptr, we need to clone it. */
40 static NTDB_DATA
dup_key(NTDB_DATA key
)
42 void *p
= malloc(key
.dsize
);
43 memcpy(p
, key
.dptr
, key
.dsize
);
48 int main(int argc
, char *argv
[])
54 struct ntdb_context
*ntdb
;
55 union ntdb_attribute seed_attr
;
56 enum NTDB_ERROR ecode
;
57 int flags
[] = { NTDB_INTERNAL
, NTDB_DEFAULT
, NTDB_NOMMAP
,
58 NTDB_INTERNAL
|NTDB_CONVERT
, NTDB_CONVERT
,
59 NTDB_NOMMAP
|NTDB_CONVERT
};
61 seed_attr
.base
.attr
= NTDB_ATTRIBUTE_SEED
;
62 seed_attr
.base
.next
= &tap_log_attr
;
63 seed_attr
.seed
.seed
= 6334326220117065685ULL;
65 plan_tests(sizeof(flags
) / sizeof(flags
[0])
66 * (NUM_RECORDS
*6 + (NUM_RECORDS
-1)*3 + 22) + 1);
67 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
68 ntdb
= ntdb_open("api-firstkey-nextkey.ntdb",
69 flags
[i
]|MAYBE_NOSYNC
,
70 O_RDWR
|O_CREAT
|O_TRUNC
, 0600,
76 ok1(ntdb_firstkey(ntdb
, &k
) == NTDB_ERR_NOEXIST
);
79 k
.dptr
= (unsigned char *)&num
;
80 k
.dsize
= sizeof(num
);
82 ok1(ntdb_store(ntdb
, k
, k
, NTDB_INSERT
) == 0);
83 ok1(ntdb_firstkey(ntdb
, &k
) == NTDB_SUCCESS
);
84 ok1(k
.dsize
== sizeof(num
));
85 ok1(memcmp(k
.dptr
, &num
, sizeof(num
)) == 0);
86 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_ERR_NOEXIST
);
89 k
.dptr
= (unsigned char *)&num
;
90 k
.dsize
= sizeof(num
);
92 ok1(ntdb_store(ntdb
, k
, k
, NTDB_INSERT
) == 0);
93 ok1(ntdb_firstkey(ntdb
, &k
) == NTDB_SUCCESS
);
94 ok1(k
.dsize
== sizeof(num
));
95 memcpy(&num
, k
.dptr
, sizeof(num
));
96 ok1(num
== 0 || num
== 1);
97 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_SUCCESS
);
98 ok1(k
.dsize
== sizeof(j
));
99 memcpy(&j
, k
.dptr
, sizeof(j
));
100 ok1(j
== 0 || j
== 1);
102 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_ERR_NOEXIST
);
105 k
.dptr
= (unsigned char *)&num
;
106 k
.dsize
= sizeof(num
);
108 ok1(ntdb_delete(ntdb
, k
) == 0);
110 ok1(ntdb_delete(ntdb
, k
) == 0);
112 /* Now lots of records. */
113 ok1(store_records(ntdb
));
116 num
= ntdb_traverse(ntdb
, trav
, &td
);
117 ok1(num
== NUM_RECORDS
);
118 ok1(td
.calls
== NUM_RECORDS
);
120 /* Simple loop should match ntdb_traverse */
121 for (j
= 0, ecode
= ntdb_firstkey(ntdb
, &k
); j
< td
.calls
; j
++) {
124 ok1(ecode
== NTDB_SUCCESS
);
125 ok1(k
.dsize
== sizeof(val
));
126 memcpy(&val
, k
.dptr
, k
.dsize
);
127 ok1(td
.records
[j
] == val
);
128 ecode
= ntdb_nextkey(ntdb
, &k
);
131 /* But arbitrary orderings should work too. */
132 for (j
= td
.calls
-1; j
> 0; j
--) {
133 k
.dptr
= (unsigned char *)&td
.records
[j
-1];
134 k
.dsize
= sizeof(td
.records
[j
-1]);
136 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_SUCCESS
);
137 ok1(k
.dsize
== sizeof(td
.records
[j
]));
138 ok1(memcmp(k
.dptr
, &td
.records
[j
], k
.dsize
) == 0);
142 /* Even delete should work. */
143 for (j
= 0, ecode
= ntdb_firstkey(ntdb
, &k
);
144 ecode
!= NTDB_ERR_NOEXIST
;
146 ok1(ecode
== NTDB_SUCCESS
);
148 ok1(ntdb_delete(ntdb
, k
) == 0);
149 ecode
= ntdb_nextkey(ntdb
, &k
);
152 diag("delete using first/nextkey gave %u of %u records",
154 ok1(j
== NUM_RECORDS
);
158 ok1(tap_log_messages
== 0);
159 return exit_status();