#include <assert.h>
#include <string.h>

#include "test-utils.h"
#include "checkpoint.h"

static void
test_checkpoint (void)
{
#define EXAMPLE_HASH {{							\
      /* Index i = 0xf*i % 0x100 */					\
      0x00,0x0f,0x1e,0x2d,0x3c,0x4b,0x5a,0x69,0x78,0x87,0x96,0xa5,0xb4,0xc3,0xd2,0xe1, \
      0xf0,0xff,0x0e,0x1d,0x2c,0x3b,0x4a,0x59,0x68,0x77,0x86,0x95,0xa4,0xb3,0xc2,0xd1, \
    }}									\

  static const struct {
    struct sigsum_hash kh;
    struct sigsum_tree_head th;
    const char *exp;
  } tests[] = {
    { {{ 0xde, 0xad, 0xbe, 0xaf }},
      { 10, {{ 0x1c, 0x0e, 0x47, /* Base64 "HA5H" */}}},
      "sigsum.org/v1/tree/deadbeaf00000000000000000000000000000000000000000000000000000000\n"
      "10\n"
      "HA5HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n"
    },
    { EXAMPLE_HASH,
      { ((uint64_t) -1) >> 1, EXAMPLE_HASH},
      "sigsum.org/v1/tree/000f1e2d3c4b5a69788796a5b4c3d2e1f0ff0e1d2c3b4a5968778695a4b3c2d1\n"
      "9223372036854775807\n"
      "AA8eLTxLWml4h5altMPS4fD/Dh0sO0pZaHeGlaSzwtE=\n"
    }
  };

  for (unsigned i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
    {
      uint8_t checkpoint[CHECKPOINT_BODY_MAX_SIZE];
      size_t size = _sigsum_checkpoint_body (checkpoint, &tests[i].kh, &tests[i].th);
      size_t exp_size = strlen (tests[i].exp);
      assert (exp_size <= CHECKPOINT_BODY_MAX_SIZE);
      if (size != exp_size)
	die ("bad checkpoint size %zd (exp %zd) for test %d",
	     size, exp_size, i);
      if (memcmp (checkpoint, tests[i].exp, size) != 0)
	{
	  fprintf (stderr, "bad checkpoint for test %d:\n", i);
	  dump_hex (stderr, size, checkpoint);
	  abort ();
	}
    }
}

static void
test_cosignature_prefix (void)
{
  static const struct {
    uint64_t timestamp;
    const char *exp;
  } tests[] = {
    { 0, "cosignature/v1\ntime 0\n" },
    { 1, "cosignature/v1\ntime 1\n" },
    { 999, "cosignature/v1\ntime 999\n" },
    { ((uint64_t) -1) >> 1, "cosignature/v1\ntime 9223372036854775807\n" },
  };
  for (unsigned i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
    {
      uint8_t prefix[COSIGNATURE_PREFIX_MAX_SIZE];
      size_t size = _sigsum_cosignature_prefix (prefix, tests[i].timestamp);
      size_t exp_size = strlen (tests[i].exp);
      assert (exp_size <= COSIGNATURE_PREFIX_MAX_SIZE);
      if (size != exp_size)
	die ("bad cosignature prefix size %zd (exp %zd) for test %d",
	     size, exp_size, i);
      const uint8_t *prefix_start = prefix + COSIGNATURE_PREFIX_MAX_SIZE - size;
      if (memcmp (prefix_start, tests[i].exp, size) != 0)
	{
	  fprintf (stderr, "bad cosignature prefix for test %d:\n", i);
	  dump_hex (stderr, size, prefix_start);
	  abort ();
	}
    }
}

int
main (void)
{
  test_checkpoint ();
  test_cosignature_prefix ();

  return 0;
}
