#include "persifs.h"
#include "testutils.h"
#include "testbplustree.h"
#include "superblob.h"
#include "bplustree.h"

#include <amisc.h>
#include <async.h>
#include <arpc.h>
#include <stdlib.h>

const int TEST_COUNT = 1024;
const int TEST_BRANCHT = 8;
const str TEST_FILENAME = "testbplustree.bpt";

int gPasses = 0;

void
testsDone()
{
  warn << "BPlusTree test passes... hooray!\n";
  if (unlink(TEST_FILENAME.cstr()) != 0)
    perror("unlink");

  exit(0);
}

void
testKeyValue(ref<bpt> t, const blockFingerprint &k, blockAddress *v)
{
  blockFingerprint k2 = k;
  blockAddress v2 = *v;
  warn << "searching for " << k << "\n";
  t->search(k2, wrap(&testKeyValue_after_search, k2, v2), wrap(&failCBE));
}

void
testKeyValue_after_search(blockFingerprint k, blockAddress v,
                          blockFingerprint k2, blockAddress v2)
{
  if (k != k2 || v != v2) { 
    warn << "expected key=" << k << " got " << k2 << "\n";
    warn << "expected val=" << v << " got " << v2 << "\n";
    fail("Incorrect result\n");
  }

  gPasses++;
  warn << "OK: " << k << " = " << v << " [" << gPasses << "]\n";
  if (gPasses == TEST_COUNT) {
    testsDone();
  }
}



void
testBPlusTree(int count, ref<qh> q, ref<bpt> t)
{
  for (int i = 0; i < count; i++)
  {
    blockFingerprint k = randomFingerprint();
    blockAddress v = randomAddress();

    warn << "inserting " << k << " = " << v << "(" << i << ")\n";
    t->insert(k, v);
    q->insert(k, v);
  }
//  t->printTree();
  
  q->traverse(wrap(&testKeyValue, t));
}

int
main(int argc, const char **argv)
{
  srandom(0x6824);

  ref<qh> q = New refcounted<qh>();
  bpt::create(TEST_FILENAME, TEST_BRANCHT,
              wrap(&testBPlusTree, TEST_COUNT, q), wrap(&failCBE));
  
  amain();
}
