4 #include "tap-interface.h"
7 #define NUM_RECORDS 1000
9 static bool store_records(struct ntdb_context
*ntdb
)
12 NTDB_DATA key
= { (unsigned char *)&i
, sizeof(i
) };
13 NTDB_DATA data
= { (unsigned char *)&i
, sizeof(i
) };
15 for (i
= 0; i
< NUM_RECORDS
; i
++)
16 if (ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) != 0)
22 unsigned int records
[NUM_RECORDS
];
26 static int trav(struct ntdb_context
*ntdb
, NTDB_DATA key
, NTDB_DATA dbuf
, void *p
)
28 struct trav_data
*td
= p
;
31 memcpy(&val
, dbuf
.dptr
, dbuf
.dsize
);
32 td
->records
[td
->calls
++] = val
;
36 /* Since ntdb_nextkey frees dptr, we need to clone it. */
37 static NTDB_DATA
dup_key(NTDB_DATA key
)
39 void *p
= malloc(key
.dsize
);
40 memcpy(p
, key
.dptr
, key
.dsize
);
45 int main(int argc
, char *argv
[])
51 struct ntdb_context
*ntdb
;
52 union ntdb_attribute seed_attr
;
53 enum NTDB_ERROR ecode
;
54 int flags
[] = { NTDB_INTERNAL
, NTDB_DEFAULT
, NTDB_NOMMAP
,
55 NTDB_INTERNAL
|NTDB_CONVERT
, NTDB_CONVERT
,
56 NTDB_NOMMAP
|NTDB_CONVERT
};
58 seed_attr
.base
.attr
= NTDB_ATTRIBUTE_SEED
;
59 seed_attr
.base
.next
= &tap_log_attr
;
60 seed_attr
.seed
.seed
= 6334326220117065685ULL;
62 plan_tests(sizeof(flags
) / sizeof(flags
[0])
63 * (NUM_RECORDS
*6 + (NUM_RECORDS
-1)*3 + 22) + 1);
64 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
65 ntdb
= ntdb_open("api-firstkey-nextkey.ntdb",
66 flags
[i
]|MAYBE_NOSYNC
,
67 O_RDWR
|O_CREAT
|O_TRUNC
, 0600,
73 ok1(ntdb_firstkey(ntdb
, &k
) == NTDB_ERR_NOEXIST
);
76 k
.dptr
= (unsigned char *)&num
;
77 k
.dsize
= sizeof(num
);
79 ok1(ntdb_store(ntdb
, k
, k
, NTDB_INSERT
) == 0);
80 ok1(ntdb_firstkey(ntdb
, &k
) == NTDB_SUCCESS
);
81 ok1(k
.dsize
== sizeof(num
));
82 ok1(memcmp(k
.dptr
, &num
, sizeof(num
)) == 0);
83 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_ERR_NOEXIST
);
86 k
.dptr
= (unsigned char *)&num
;
87 k
.dsize
= sizeof(num
);
89 ok1(ntdb_store(ntdb
, k
, k
, NTDB_INSERT
) == 0);
90 ok1(ntdb_firstkey(ntdb
, &k
) == NTDB_SUCCESS
);
91 ok1(k
.dsize
== sizeof(num
));
92 memcpy(&num
, k
.dptr
, sizeof(num
));
93 ok1(num
== 0 || num
== 1);
94 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_SUCCESS
);
95 ok1(k
.dsize
== sizeof(j
));
96 memcpy(&j
, k
.dptr
, sizeof(j
));
97 ok1(j
== 0 || j
== 1);
99 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_ERR_NOEXIST
);
102 k
.dptr
= (unsigned char *)&num
;
103 k
.dsize
= sizeof(num
);
105 ok1(ntdb_delete(ntdb
, k
) == 0);
107 ok1(ntdb_delete(ntdb
, k
) == 0);
109 /* Now lots of records. */
110 ok1(store_records(ntdb
));
113 num
= ntdb_traverse(ntdb
, trav
, &td
);
114 ok1(num
== NUM_RECORDS
);
115 ok1(td
.calls
== NUM_RECORDS
);
117 /* Simple loop should match ntdb_traverse */
118 for (j
= 0, ecode
= ntdb_firstkey(ntdb
, &k
); j
< td
.calls
; j
++) {
121 ok1(ecode
== NTDB_SUCCESS
);
122 ok1(k
.dsize
== sizeof(val
));
123 memcpy(&val
, k
.dptr
, k
.dsize
);
124 ok1(td
.records
[j
] == val
);
125 ecode
= ntdb_nextkey(ntdb
, &k
);
128 /* But arbitrary orderings should work too. */
129 for (j
= td
.calls
-1; j
> 0; j
--) {
130 k
.dptr
= (unsigned char *)&td
.records
[j
-1];
131 k
.dsize
= sizeof(td
.records
[j
-1]);
133 ok1(ntdb_nextkey(ntdb
, &k
) == NTDB_SUCCESS
);
134 ok1(k
.dsize
== sizeof(td
.records
[j
]));
135 ok1(memcmp(k
.dptr
, &td
.records
[j
], k
.dsize
) == 0);
139 /* Even delete should work. */
140 for (j
= 0, ecode
= ntdb_firstkey(ntdb
, &k
);
141 ecode
!= NTDB_ERR_NOEXIST
;
143 ok1(ecode
== NTDB_SUCCESS
);
145 ok1(ntdb_delete(ntdb
, k
) == 0);
146 ecode
= ntdb_nextkey(ntdb
, &k
);
149 diag("delete using first/nextkey gave %u of %u records",
151 ok1(j
== NUM_RECORDS
);
155 ok1(tap_log_messages
== 0);
156 return exit_status();