#include "persifs.h"
#include "testutils.h"
#include "testblobindex.h"
#include "blobindex.h"
#include "memblobindex.h"

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

const int TEST_COUNT = 1024;
const str TEST_FILENAME = "testblobindex.bdx";

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


void
testBlobIndex(callback<void>::ref cb, int count, ref<blobIndex> ind)
{
  blockFingerprint fp = randomFingerprint();
  blockAddress addr = randomAddress();

  ind->put(fp, addr,
           wrap(testBlobIndex_after_put, cb, ind, count, fp, addr),
           wrap(failCBE));
}

void
testBlobIndex_after_put(callback<void>::ref cb,
                        ref<blobIndex> ind, int count,
                        blockFingerprint fp, blockAddress addr)
{
  ind->get(fp,
           wrap(testBlobIndex_after_get, cb, ind, count, fp, addr),
           wrap(failCBE));
}

void
testBlobIndex_after_get(callback<void>::ref cb,
                        ref<blobIndex> ind, int count,
                        blockFingerprint fp, blockAddress addr,
                        blockAddress retAddr)
{
  if (addr == retAddr) {
    if (count > 1) {
      delaycb(0, wrap(testBlobIndex, cb, count - 1, ind));
    } else {
      cb();
    }
  } else {
    warn << "put " << fp << "=" << addr << " but got " << retAddr << "\n";
    fail("get did not return put value");
  }
}

void
testMemBlobIndex(callback<void>::ref cb, int count, ref<memBlobIndex> ind)
{
  testBlobIndex(cb, count, ind);
}


void
testDiskBlobIndex(callback<void>::ref cb, int count, ref<diskBlobIndex> ind)
{
  testBlobIndex(cb, count, ind);
}


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

  callback<void>::ref done = wrap(testsDone);

  diskBlobIndex::create(TEST_FILENAME,
                        wrap(testDiskBlobIndex, done, TEST_COUNT),
                        wrap(failCBE));
  
  amain();
}
