/*
 * testnvisitor.cpp --
 *
 * Tests of the e4_NodeVisitor class.
 *
 * Copyright (c) 2000-2003, JYL Software Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF
 * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#ifndef	_WIN32
#include <unistd.h>
#endif
#include "test.h"

#define TNV_NODELIMIT	256

static int
test_nodevisitor1()
{
    e4_Node n1, n2, n3;
    int i = 0, rank = 0;

    /*
     * Test node visitor construction from a storage.
     */

    {
	e4_Storage s;

	if (!clean_storage("foo.db", s)) {
	    fprintf(stderr, "test nodevisitor1 failed (step 0)\n");
	    return 1;
	}
	if (!s.IsValid()) {
	    fprintf(stderr, "test nodevisitor1 failed (step 1)\n");
	    return 1;
	}
	if (!s.GetRootNode(n1) || !n1.IsValid() || !n1.IsRoot()) {
	    fprintf(stderr, "test nodevisitor1 failed (step 2)\n");
	    return 1;
	}

	/*
	 * After this loop the storage contains 2*TNV_NODELIMIT + 1 nodes.
	 * +1 for the root node (;-).
	 */

	for (i = 0; i < TNV_NODELIMIT; i++) {
	    if (!n1.AddNode("foo", E4_IOLAST, rank, n2) || !n2.IsValid() ||
		n2.IsDetached()) {
		fprintf(stderr, "test nodevisitor1 failed (step 3.1.%d)\n", i);
		return 1;
	    }
	    if (!n1.IsValid()) {
		fprintf(stderr, "test nodevisitor1 failed (step 3.2.%d)\n", i);
		return 1;
	    }
	    if (!n2.AddNode("v", E4_IOLAST, rank, n3)) {
		fprintf(stderr, "test nodevisitor1 failed (step 3.3.%d)\n", i);
		return 1;
	    }
	    if (!n3.IsValid()) {
		fprintf(stderr, "test nodevisitor1 failed (step 3.4.%d)\n", i);
		return 1;
	    }
	}

	e4_NodeVisitor v(s);

	if (!v.IsValid()) {
	    fprintf(stderr, "test nodevisitor1 failed (step 4)\n");
	    return 1;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor1 failed (step 5)\n");
	    return 1;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor1 failed (step 6)\n");
	    return 1;
	}
	for (i = 0; !v.IsDone(); i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if (i != 1) {
	    fprintf(stderr, "test nodevisitor1 failed (step 7)\n");
	    return 1;
	}
	s.Delete();
	if (s.IsValid()) {
	    fprintf(stderr, "test nodevisitor1 failed (step 8)\n");
	    return 1;
	}
    }

    return 0;
}

static int
test_nodevisitor2()
{
    e4_Node n1, n2, n3;
    int i = 0, rank = 0;

    /*
     * Test node visitor construction from a storage
     * using e4_NodeVisitor::SetStorage().
     */

    {
	e4_Storage s;

	if (!clean_storage("foo.db", s)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 0)\n");
	    return 2;
	}
	if (!s.IsValid()) {
	    fprintf(stderr, "test nodevisitor2 failed (step 1)\n");
	    return 2;
	}

	if (!s.GetRootNode(n1) || !n1.IsValid() || !n1.IsRoot()) {
	    fprintf(stderr, "test nodevisitor2 failed (step 2)\n");
	    return 2;
	}

	/*
	 * After this loop the storage contains 2*TNV_NODELIMIT + 1 nodes.
	 * +1 for the root node (;-).
	 */

	for (i = 0; i < TNV_NODELIMIT; i++) {
	    if (!n1.AddNode("foo", E4_IOLAST, rank, n2) || !n2.IsValid() ||
		n2.IsDetached()) {
		fprintf(stderr, "test nodevisitor2 failed (step 3.1.%d)\n", i);
		return 2;
	    }
	    if (!n1.IsValid()) {
		fprintf(stderr, "test nodevisitor2 failed (step 3.2.%d)\n", i);
		return 2;
	    }
	    if (!n2.AddNode("v", E4_IOLAST, rank, n3)) {
		fprintf(stderr, "test nodevisitor2 failed (step 3.3.%d)\n", i);
		return 2;
	    }
	    if (!n3.IsValid()) {
		fprintf(stderr, "test nodevisitor2 failed (step 3.4.%d)\n", i);
		return 2;
	    }
	}

	e4_NodeVisitor v;

	if (v.IsValid()) {
	    fprintf(stderr, "test nodevisitor2 failed (step 4)\n");
	    return 2;
	}
	if (!v.SetStorage(s, E4_DCATTACHED)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 5)\n");
	    return 2;
	}
	if (!v.IsValid()) {
	    fprintf(stderr, "test nodevisitor2 failed (step 6)\n");
	    return 2;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 7)\n");
	    return 2;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 8)\n");
	    return 2;
	}
	for (i = 0; !v.IsDone(); i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if (i != 1) {
	    fprintf(stderr, "test nodevisitor2 failed (step 9)\n");
	    return 2;
	}

	e4_NodeVisitor v1;

	if (!v.SetStorage(s, E4_DCATTACHED)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 10)\n");
	    return 2;
	}
	if (!v1.SetStorage(s, E4_DCATTACHED)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 11)\n");
	    return 2;
	}
	if (!v1.IsValid()) {
	    fprintf(stderr, "test nodevisitor2 failed (step 12)\n");
	    return 2;
	}
	if (v != v1) {
	    fprintf(stderr, "test nodevisitor2 failed (step 13)\n");
	    return 2;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v1.NextNode(n1)) {
	    if (!v1.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v1.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 14)\n");
	    return 2;
	}
	if (v == v1) {
	    fprintf(stderr, "test nodevisitor2 failed (step 15)\n");
	    return 2;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v1.NextNode(n1)) {
	    if (!v1.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v1.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 16) %d %d\n",
		    v1.IsDone(), i);
	    return 2;
	}
	for (i = 0; !v1.IsDone(); i++, v1.NextNode(n1)) {
	    if (!v1.CurrentNode(n1)) {
		break;
	    }
	}
	if (i != 1) {
	    fprintf(stderr, "test nodevisitor2 failed (step 17)\n");
	    return 2;
	}

	/*
	 * Reset the visitor after visiting all nodes.
	 */

	if (!v.SetStorage(s, E4_DCATTACHED)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 18)\n");
	    return 2;
	}
	if ((!v.IsValid()) || (v.IsDone())) {
	    fprintf(stderr, "test nodevisitor2 failed (step 19)\n");
	    return 2;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 20)\n");
	    return 2;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 21)\n");
	    return 2;
	}
	for (i = 0; !v.IsDone(); i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if (i != 1) {
	    fprintf(stderr, "test nodevisitor2 failed (step 22)\n");
	    return 2;
	}

	/*
	 * Test that setting the visitor to an invalid storage fails.
	 */

	if (v.SetStorage(invalidStorage, E4_DCATTACHED)) {
	    fprintf(stderr, "test nodevisitor2 failed (step 23)\n");
	    return 2;
	}
	s.Delete();
	if (s.IsValid()) {
	    fprintf(stderr, "test nodevisitor2 failed (step 24)\n");
	    return 2;
	}
    }

    return 0;
}

static int
test_nodevisitor5()
{
    e4_Node n1, n2, n3;
    int i = 0, rank = 0;

    /*
     * Test node visitor construction from a node.
     */

    {
	e4_Storage s;

	if (!clean_storage("foo.db", s)) { 
	    fprintf(stderr, "test nodevisitor5 failed (step 0)\n");
	    return 5;
	}
	if (!s.IsValid()) {
	    fprintf(stderr, "test nodevisitor5 failed (step 1)\n");
	    return 5;
	}
	if (!s.GetRootNode(n1) || !n1.IsValid() || !n1.IsRoot()) {
	    fprintf(stderr, "test nodevisitor5 failed (step 2)\n");
	    return 5;
	}

	/*
	 * After this loop the storage contains 2*TNV_NODELIMIT + 1 nodes.
	 * +1 for the root node (;-).
	 */

	for (i = 0; i < TNV_NODELIMIT; i++) {
	    if (!n1.AddNode("foo", E4_IOLAST, rank, n2) || !n2.IsValid() ||
		n2.IsDetached()) {
		fprintf(stderr, "test nodevisitor5 failed (step 3.1.%d)\n", i);
		return 5;
	    }
	    if (!n1.IsValid()) {
		fprintf(stderr, "test nodevisitor5 failed (step 3.2.%d)\n", i);
		return 5;
	    }
	    if (!n2.AddNode("v", E4_IOLAST, rank, n3)) {
		fprintf(stderr, "test nodevisitor5 failed (step 3.3.%d)\n", i);
		return 5;
	    }
	    if (!n3.IsValid()) {
		fprintf(stderr, "test nodevisitor5 failed (step 3.4.%d)\n", i);
		return 5;
	    }
	}

	e4_NodeVisitor v(n1);

	if (!v.IsValid()) {
	    fprintf(stderr, "test nodevisitor5 failed (step 4)\n");
	    return 5;
	}
	for (i = 0; i < (2*TNV_NODELIMIT) + 1; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v.IsDone()) || (i != (2*TNV_NODELIMIT)+1)) {
	    fprintf(stderr,
		    "test nodevisitor5 failed (step 5), %d vs %d, %d\n",
		    i, (2*TNV_NODELIMIT)+1, v.IsDone());
	    return 5;
	}
	s.Delete();
	if (s.IsValid()) {
	    fprintf(stderr, "test nodevisitor5 failed (step 6)\n");
	    return 5;
	}
    }

    return 0;
}

static int
test_nodevisitor6()
{
    e4_Node n1, n2, n3, nh;
    int i = 0, rank = 0;

    /*
     * Test node visitor construction from a node using
     * e4_NodeVisitor::SetNode().
     */

    {
	e4_Storage s;

	if (!clean_storage("foo.db", s)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 0)\n");
	    return 6;
	}
	if (!s.IsValid()) {
	    fprintf(stderr, "test nodevisitor6 failed (step 1)\n");
	    return 6;
	}
	if (!s.GetRootNode(n1) || !n1.IsValid() || !n1.IsRoot()) {
	    fprintf(stderr, "test nodevisitor6 failed (step 2)\n");
	    return 6;
	}

	/*
	 * After this loop the storage contains 2*TNV_NODELIMIT + 1 nodes.
	 * +1 for the root node (;-).
	 */

	for (i = 0; i < TNV_NODELIMIT; i++) {
	    if (!n1.AddNode("foo", E4_IOLAST, rank, n2) || !n2.IsValid() ||
		n2.IsDetached()) {
		fprintf(stderr, "test nodevisitor6 failed (step 3.1.%d)\n", i);
		return 6;
	    }
	    if (!n1.IsValid()) {
		fprintf(stderr, "test nodevisitor6 failed (step 3.2.%d)\n", i);
		return 6;
	    }
	    if (!n2.AddNode("v", E4_IOLAST, rank, n3)) {
		fprintf(stderr, "test nodevisitor6 failed (step 3.3.%d)\n", i);
		return 6;
	    }
	    if (!n3.IsValid()) {
		fprintf(stderr, "test nodevisitor6 failed (step 3.4.%d)\n", i);
		return 6;
	    }
	}
	nh = n2;

	e4_NodeVisitor v;

	if (v.IsValid()) {
	    fprintf(stderr, "test nodevisitor6 failed (step 4)\n");
	    return 6;
	}
	if (!v.SetNode(nh)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 5)\n");
	    return 6;
	}
	if (!v.IsValid()) {
	    fprintf(stderr, "test nodevisitor6 failed (step 6)\n");
	    return 6;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 7)\n");
	    return 6;
	}
	for (i = 0; i < TNV_NODELIMIT + 1; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v.IsDone()) || (i != TNV_NODELIMIT + 1)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 8)\n");
	    return 6;
	}

	e4_NodeVisitor v1;

	if (!v.SetNode(nh)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 9)\n");
	    return 6;
	}
	if (!v1.SetNode(nh)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 10)\n");
	    return 6;
	}
	if (!v1.IsValid()) {
	    fprintf(stderr, "test nodevisitor6 failed (step 11)\n");
	    return 6;
	}
	if (v1 != v) {
	    fprintf(stderr, "test nodevisitor6 failed (step 12)\n");
	    return 6;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v1.NextNode(n1)) {
	    if (!v1.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v1.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 13)\n");
	    return 6;
	}
	if (v == v1) {
	    fprintf(stderr, "test nodevisitor6 failed (step 14)\n");
	    return 6;
	}
	for (i = 0; i < TNV_NODELIMIT + 1; i++, v1.NextNode(n1)) {
	    if (!v1.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v1.IsDone()) || (i != TNV_NODELIMIT + 1)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 15)\n");
	    return 6;
	}

	/*
	 * Reset the visitor after visiting all nodes.
	 */

	if (!v.SetNode(nh)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 16)\n");
	    return 6;
	}
	if ((!v.IsValid()) || (v.IsDone())) {
	    fprintf(stderr, "test nodevisitor6 failed (step 17)\n");
	    return 6;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 18)\n");
	    return 6;
	}
	for (i = 0; i < TNV_NODELIMIT + 1; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v.IsDone()) || (i != TNV_NODELIMIT + 1)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 19)\n");
	    return 6;
	}

	/*
	 * Test that setting the visitor to an invalid node fails.
	 */

	if (v.SetNode(invalidNode)) {
	    fprintf(stderr, "test nodevisitor6 failed (step 20)\n");
	    return 6;
	}
	s.Delete();
	if (s.IsValid()) {
	    fprintf(stderr, "test nodevisitor6 failed (step 21)\n");
	    return 6;
	}
    }

    return 0;
}

static int
test_nodevisitor7()
{
    e4_Node r, n1, n2;
    int i = 0, rank = 0;
    e4_Vertex f;

    /*
     * Test node visitor construction from a vertex.
     */

    {
	e4_Storage s;

	if (!clean_storage("foo.db", s)) {
	    fprintf(stderr, "test nodevisitor7 failed (step 0)\n");
	    return 7;
	}
	if (!s.IsValid()) {
	    fprintf(stderr, "test nodevisitor7 failed (step 1)\n");
	    return 7;
	}
	if (!s.GetRootNode(r) || !r.IsValid() || !r.IsRoot()) {
	    fprintf(stderr, "test nodevisitor7 failed (step 2)\n");
	    return 7;
	}

	/*
	 * After this loop the storage contains (2*TNV_NODELIMIT) + 1 nodes.
	 */

	for (i = 0; i < TNV_NODELIMIT; i++) {
	    if (!r.AddNode("f", E4_IOLAST, rank, n1)) {
		fprintf(stderr, "test nodevisitor7 failed (step 3.1.%d)\n", i);
		return 7;
	    }
	    if (!n1.IsValid()) {
		fprintf(stderr, "test nodevisitor7 failed (step 3.2.%d)\n", i);
		return 7;
	    }
	    if (!n1.AddNodeRef("f", E4_IOLAST, rank, n2, f)) {
		fprintf(stderr, "test nodevisitor7 failed (step 3.3.%d)\n", i);
		return 7;
	    }
	    if (!n2.IsValid()) {
		fprintf(stderr, "test nodevisitor7 failed (step 3.4.%d)\n", i);
		return 7;
	    }
	}

	e4_NodeVisitor v(f);

	if (!v.IsValid()) {
	    fprintf(stderr, "test nodevisitor7 failed (step 4)\n");
	    return 7;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor7 failed (step 5)\n");
	    return 7;
	}
	for (i = 0; i < TNV_NODELIMIT + 1; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v.IsDone()) || (i != TNV_NODELIMIT + 1)) {
	    fprintf(stderr, "test nodevisitor7 failed (step 6)\n");
	    return 7;
	}
	s.Delete();
	if (s.IsValid()) {
	    fprintf(stderr, "test nodevisitor7 failed (step 7)\n");
	    return 7;
	}
    }

    return 0;
}

static int
test_nodevisitor8()
{
    e4_Node r, n1, n2;
    int i = 0, rank = 0;
    e4_Vertex f;

    /*
     * Test node visitor construction from a vertex using
     * e4_NodeVisitor::SetVertex().
     */

    {
	e4_Storage s;

	if (!clean_storage("foo.db", s)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 0)\n");
	    return 8;
	}
	if (!s.IsValid()) {
	    fprintf(stderr, "test nodevisitor8 failed (step 1)\n");
	    return 8;
	}
	if (!s.GetRootNode(r) || !r.IsValid() || !r.IsRoot()) {
	    fprintf(stderr, "test nodevisitor8 failed (step 2)\n");
	    return 8;
	}

	/*
	 * After this loop the storage contains (2*TNV_NODELIMIT) + 1 nodes.
	 */

	for (i = 0; i < TNV_NODELIMIT; i++) {
	    if (!r.AddNode("f", E4_IOLAST, rank, n1)) {
		fprintf(stderr, "test nodevisitor8 failed (step 3.1.%d)\n", i);
		return 8;
	    }
	    if (!n1.IsValid()) {
		fprintf(stderr, "test nodevisitor8 failed (step 3.2.%d)\n", i);
		return 8;
	    }
	    if (!n1.AddNodeRef("f", E4_IOLAST, rank, n2, f)) {
		fprintf(stderr, "test nodevisitor8 failed (step 3.3.%d)\n", i);
		return 8;
	    }
	    if (!n2.IsValid()) {
		fprintf(stderr, "test nodevisitor8 failed (step 3.4.%d)\n", i);
		return 8;
	    }
	}

	e4_NodeVisitor v;

	if (v.IsValid()) {
	    fprintf(stderr, "test nodevisitor8 failed (step 4)\n");
	    return 8;
	}
	if (!v.SetVertex(f)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 5)\n");
	    return 8;
	}
	if (!v.IsValid()) {
	    fprintf(stderr, "test nodevisitor8 failed (step 6)\n");
	    return 8;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 7)\n");
	    return 8;
	}
	for (i = 0; i < TNV_NODELIMIT + 1; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v.IsDone()) || (i != TNV_NODELIMIT + 1)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 8)\n");
	    return 8;
	}

	e4_NodeVisitor v1;

	if (!v.SetVertex(f)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 9)\n");
	    return 8;
	}
	if (!v1.SetVertex(f)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 10)\n");
	    return 8;
	}
	if (!v1.IsValid()) {
	    fprintf(stderr, "test nodevisitor8 failed (step 11)\n");
	    return 8;
	}
	if (v1 != v) {
	    fprintf(stderr, "test nodevisitor8 failed (step 12)\n");
	    return 8;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v1.NextNode(n1)) {
	    if (!v1.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v1.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 13)\n");
	    return 8;
	}
	if (v == v1) {
	    fprintf(stderr, "test nodevisitor8 failed (step 14)\n");
	    return 8;
	}
	for (i = 0; i < TNV_NODELIMIT + 1; i++, v1.NextNode(n1)) {
	    if (!v1.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v1.IsDone()) || (i != TNV_NODELIMIT + 1)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 15)\n");
	    return 8;
	}

	/*
	 * Reset the visitor after visiting all nodes.
	 */

	if (!v.SetVertex(f)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 16)\n");
	    return 8;
	}
	if ((!v.IsValid()) || (v.IsDone())) {
	    fprintf(stderr, "test nodevisitor8 failed (step 17)\n");
	    return 8;
	}
	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 18)\n");
	    return 8;
	}
	for (i = 0; i < TNV_NODELIMIT + 1; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((!v.IsDone()) || (i != TNV_NODELIMIT + 1)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 19)\n");
	    return 8;
	}

	/*
	 * Test that setting the visitor to an invalid vertex fails.
	 */

	if (v.SetVertex(invalidVertex)) {
	    fprintf(stderr, "test nodevisitor8 failed (step 20)\n");
	    return 8;
	}
	s.Delete();
	if (s.IsValid()) {
	    fprintf(stderr, "test nodevisitor8 failed (step 21)\n");
	    return 8;
	}
    }

    return 0;
}

static int
test_nodevisitor9()
{
    e4_Node r, n1, n2;
    e4_Vertex f;
    int i = 0, rank = 0;

    /*
     * Test node visitor construction from a storage.
     */

    {
	e4_Storage s;

	if (!clean_storage("foo.db", s)) {
	    fprintf(stderr, "test nodevisitor9 failed (step 0)\n");
	    return 9;
	}
	if (!s.IsValid()) {
	    fprintf(stderr, "test nodevisitor9 failed (step 1)\n");
	    return 9;
	}
	if (!s.GetRootNode(r) || !r.IsValid() || !r.IsRoot()) {
	    fprintf(stderr, "test nodevisitor9 failed (step 2)\n");
	    return 9;
	}

	/*
	 * After this loop the storage contains (2*TNV_NODELIMIT) + 1 nodes.
	 */

	for (i = 0; i < TNV_NODELIMIT; i++) {
	    if (!r.AddNode("f", E4_IOLAST, rank, n1)) {
		fprintf(stderr, "test nodevisitor9 failed (step 3.1.%d)\n", i);
		return 9;
	    }
	    if (!n1.IsValid()) {
		fprintf(stderr, "test nodevisitor9 failed (step 3.2.%d)\n", i);
		return 9;
	    }
	    if (!n1.AddNodeRef("f", E4_IOLAST, rank, n2, f)) {
		fprintf(stderr, "test nodevisitor9 failed (step 3.3.%d)\n", i);
		return 9;
	    }
	    if (!n2.IsValid()) {
		fprintf(stderr, "test nodevisitor9 failed (step 3.4.%d)\n", i);
		return 9;
	    }
	}

	e4_NodeVisitor v(s);

	if (!v.IsValid()) {
	    fprintf(stderr, "test nodevisitor9 failed (step 4)\n");
	    return 9;
	}

	for (i = 0; i < TNV_NODELIMIT; i++, v.NextNode(n1)) {
	    if (!v.CurrentNode(n1)) {
		break;
	    }
	}
	if ((v.IsDone()) || (i != TNV_NODELIMIT)) {
	    fprintf(stderr, "test nodevisitor9 failed (step 5)\n");
	    return 9;
	}

	s.Delete();

	if (s.IsValid()) {
	    fprintf(stderr, "test nodevisitor9 failed (step 6)\n");
	    return 9;
	}
	if (!v.IsDone()) {
	    fprintf(stderr, "test nodevisitor9 failed (step 7)\n");
	    return 9;
	}
	if (v.IsValid()) {
	    fprintf(stderr, "test nodevisitor9 failed (step 8)\n");
	    return 9;
	}
    }

    return 0;
}

int
test_nodevisitor()
{
    int result = 0;

    fprintf(stderr, "Running e4_NodeVisitor tests: ");
    result = test_nodevisitor1();
    if (result != 0) {
	return result;
    }
    fprintf(stderr, ".");
    result = test_nodevisitor2();
    if (result != 0) {
	return result;
    }
    fprintf(stderr, ".");

    /*
     * Tests test_nodevisitor3 and test_nodevisitor4 were removed.
     */

    result = test_nodevisitor5();
    if (result != 0) {
	return result;
    }
    fprintf(stderr, ".");
    result = test_nodevisitor6();
    if (result != 0) {
	return result;
    }
    fprintf(stderr, ".");
    result = test_nodevisitor7();
    if (result != 0) {
	return result;
    }
    fprintf(stderr, ".");
    result = test_nodevisitor8();
    if (result != 0) {
	return result;
    }
    fprintf(stderr, ".");
    result = test_nodevisitor9();
    if (result != 0) {
	return result;
    }
    fprintf(stderr, ".\n");
    return result;
}
