mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 15:00:12 +00:00
c877c0b419
Instead of bundling our own copies of Russ's C TAP Harness, start using source pulled from his git repository using the src/external import mechanism. Note that we are not currently building the floating point (is_double) portion of the harness. In the process of doing so, we also upgrade our test harness to the latest upstream version, 1.11. This is somewhat problematic, as there have been some significant code changes since the version bundled with OpenAFS. Work around these by *) Referencing the basic.h header as <tests/tap/basic.h>, rather than just <tap/basic.h>, to match the new upstream layout *) Changing the include path so that the tests/ directory can be found within it. Change-Id: I63efbb30248165e5729005b0a791e7eb7afb051d Reviewed-on: http://gerrit.openafs.org/7374 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Russ Allbery <rra@stanford.edu> Reviewed-by: Derrick Brashear <shadow@dementix.org>
167 lines
3.3 KiB
C
167 lines
3.3 KiB
C
#include <afsconfig.h>
|
|
#include <afs/param.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <tests/tap/basic.h>
|
|
|
|
#include <afs/opr.h>
|
|
#include <opr/rbtree.h>
|
|
|
|
struct intnode {
|
|
struct opr_rbtree_node node;
|
|
int value;
|
|
};
|
|
|
|
int _checkTree(struct opr_rbtree_node *node)
|
|
{
|
|
struct opr_rbtree_node *left, *right;
|
|
int lheight, rheight;
|
|
|
|
if (node == NULL)
|
|
return 1;
|
|
|
|
left = node->left;
|
|
right = node->right;
|
|
|
|
/* Leaf nodes are always black */
|
|
if (node->red && ((left && left->red) || (right &&right->red))) {
|
|
printf("Consecutive red nodes\n");
|
|
return 0;
|
|
}
|
|
|
|
/* XXX - Check ordering in nodes */
|
|
|
|
lheight = _checkTree(left);
|
|
rheight = _checkTree(right);
|
|
|
|
if (lheight !=0 && rheight !=0 && lheight != rheight) {
|
|
printf("Left and right branches have differing number of black nodes\n");
|
|
return 0;
|
|
}
|
|
|
|
if (lheight !=0 && rheight !=0)
|
|
return node->red ? lheight : lheight+1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
checkTree(struct opr_rbtree *head) {
|
|
return _checkTree(head->root);
|
|
}
|
|
|
|
int
|
|
insertNode(struct opr_rbtree *head, int value) {
|
|
|
|
struct intnode *inode;
|
|
struct opr_rbtree_node *parent, **childptr;
|
|
|
|
inode = malloc(sizeof(struct intnode));
|
|
inode->value = value;
|
|
|
|
childptr = &head->root;
|
|
parent = NULL;
|
|
|
|
while (*childptr) {
|
|
struct intnode *tnode;
|
|
parent = *childptr;
|
|
tnode = opr_containerof(parent, struct intnode, node);
|
|
|
|
if (value < tnode->value)
|
|
childptr = &(*childptr)->left;
|
|
else if (value > tnode->value)
|
|
childptr = &(*childptr)->right;
|
|
else
|
|
return -1;
|
|
}
|
|
opr_rbtree_insert(head, parent, childptr, &inode->node);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
countNodes(struct opr_rbtree *head) {
|
|
struct opr_rbtree_node *node;
|
|
int count;
|
|
|
|
node = opr_rbtree_first(head);
|
|
if (node == NULL)
|
|
return 0;
|
|
|
|
count = 1;
|
|
while ((node = opr_rbtree_next(node)))
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
/* Now, insert 1000 nodes into the tree, making sure with each insertion that
|
|
* the tree is still valid, and has the correct number of nodes
|
|
*/
|
|
int
|
|
createTree(struct opr_rbtree *head)
|
|
{
|
|
int counter;
|
|
|
|
for (counter = 1000; counter>0; counter--) {
|
|
while (insertNode(head, random())!=0);
|
|
if (!checkTree(head)) {
|
|
printf("Tree check failed at %d\n", 1001 - counter);
|
|
return 0;
|
|
}
|
|
if (countNodes(head) != 1001 - counter ) {
|
|
printf("Tree has fewer nodes than inserted : %d", 1001 - counter);
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* Randomly remove nodes from the tree, this is really, really inefficient, but
|
|
* hey
|
|
*/
|
|
int
|
|
destroyTree(struct opr_rbtree *head)
|
|
{
|
|
int counter;
|
|
|
|
for (counter = 1000; counter>0; counter--) {
|
|
struct opr_rbtree_node *node;
|
|
int remove, i;
|
|
|
|
remove = random() % counter;
|
|
node = opr_rbtree_first(head);
|
|
for (i=0; i<remove; i++)
|
|
node = opr_rbtree_next(node);
|
|
|
|
opr_rbtree_remove(head, node);
|
|
if (countNodes(head) != counter-1) {
|
|
printf("Tree has lost nodes after %d deletions", 1001 - counter);
|
|
return 0;
|
|
}
|
|
|
|
if (!checkTree(head)) {
|
|
printf("Tree check failed at %d removals\n", 1001 - counter);
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
struct opr_rbtree head;
|
|
|
|
plan(3);
|
|
|
|
opr_rbtree_init(&head);
|
|
ok(1, "Initialising the tree works");
|
|
|
|
ok(createTree(&head), "Creating tree with 1000 nodes works");
|
|
ok(destroyTree(&head), "Tree retains consistency as nodes deleted");
|
|
|
|
return 0;
|
|
}
|