171 lines
5.0 KiB
C
171 lines
5.0 KiB
C
/* Test SHA-256 and source include identity handling. */
|
|
|
|
#include <hawk.h>
|
|
#include <hawk-sha256.h>
|
|
#include <hawk-str.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "tap.h"
|
|
|
|
struct source_t
|
|
{
|
|
const hawk_ooch_t* name;
|
|
const hawk_ooch_t* text;
|
|
hawk_oow_t pos;
|
|
hawk_uint8_t id[2];
|
|
hawk_uint8_t id_len;
|
|
};
|
|
|
|
static struct source_t source[] =
|
|
{
|
|
{ HAWK_NULL, HAWK_NULL, 0, { 0x00, 0x00 }, 0 },
|
|
{ HAWK_T("a"), HAWK_T("function fa() { return 1; }\n"), 0, { 0x11, 0x00 }, 1 },
|
|
{ HAWK_T("alias-a"), HAWK_T("function fa() { return 1; }\n"), 0, { 0x11, 0x00 }, 1 },
|
|
{ HAWK_T("b"), HAWK_T("function fb() { return 2; }\n"), 0, { 0x11, 0x00 }, 2 }
|
|
};
|
|
|
|
static hawk_ooi_t source_io (hawk_t* hawk, hawk_sio_cmd_t cmd, hawk_sio_arg_t* arg, hawk_ooch_t* data, hawk_oow_t size)
|
|
{
|
|
struct source_t* src;
|
|
hawk_oow_t i, len, rem;
|
|
|
|
switch (cmd)
|
|
{
|
|
case HAWK_SIO_CMD_OPEN:
|
|
src = &source[0];
|
|
if (arg->name)
|
|
{
|
|
for (i = 1; i < HAWK_COUNTOF(source); i++)
|
|
{
|
|
if (hawk_comp_oocstr(arg->name, source[i].name, 0) == 0)
|
|
{
|
|
src = &source[i];
|
|
break;
|
|
}
|
|
}
|
|
if (i >= HAWK_COUNTOF(source))
|
|
{
|
|
hawk_seterrnum(hawk, HAWK_NULL, HAWK_ENOENT);
|
|
return -1;
|
|
}
|
|
arg->path = (hawk_ooch_t*)src->name;
|
|
memcpy(arg->unique_id, src->id, src->id_len);
|
|
arg->unique_id_len = src->id_len;
|
|
}
|
|
src->pos = 0;
|
|
arg->handle = src;
|
|
return 1;
|
|
|
|
case HAWK_SIO_CMD_CLOSE:
|
|
return 0;
|
|
|
|
case HAWK_SIO_CMD_READ:
|
|
src = (struct source_t*)arg->handle;
|
|
len = hawk_count_oocstr(src->text);
|
|
rem = len - src->pos;
|
|
if (size > rem) size = rem;
|
|
if (size > 0)
|
|
{
|
|
memcpy(data, &src->text[src->pos], size * HAWK_SIZEOF(*data));
|
|
src->pos += size;
|
|
}
|
|
return size;
|
|
|
|
default:
|
|
hawk_seterrnum(hawk, HAWK_NULL, HAWK_EINTERN);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static int parse_source (hawk_t* hawk, const hawk_ooch_t* text)
|
|
{
|
|
hawk_sio_cbs_t sio;
|
|
source[0].text = text;
|
|
sio.in = source_io;
|
|
sio.out = HAWK_NULL;
|
|
return hawk_parse(hawk, &sio);
|
|
}
|
|
|
|
static int hex_digit (hawk_bch_t c)
|
|
{
|
|
if (c >= '0' && c <= '9') return c - '0';
|
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
|
return -1;
|
|
}
|
|
|
|
static int digest_matches (const hawk_uint8_t* digest, const hawk_bch_t* expected)
|
|
{
|
|
hawk_oow_t i;
|
|
for (i = 0; i < HAWK_SHA256_DIGEST_LEN; i++)
|
|
{
|
|
int hi = hex_digit(expected[i * 2]);
|
|
int lo = hex_digit(expected[i * 2 + 1]);
|
|
if (hi < 0 || lo < 0 || digest[i] != (hawk_uint8_t)((hi << 4) | lo)) return 0;
|
|
}
|
|
return expected[HAWK_SHA256_DIGEST_LEN * 2] == '\0';
|
|
}
|
|
|
|
int main (void)
|
|
{
|
|
static const hawk_bch_t abc[] = "abc";
|
|
static const hawk_bch_t long_input[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
|
static const hawk_ooch_t distinct_includes[] = HAWK_T(
|
|
"@pragma implicit off\n"
|
|
"@include_once \"a\";\n"
|
|
"@include_once \"b\";\n"
|
|
"BEGIN { fa(); fb(); }\n");
|
|
static const hawk_ooch_t duplicate_once[] = HAWK_T(
|
|
"@include_once \"a\";\n"
|
|
"@include_once \"alias-a\";\n"
|
|
"BEGIN { fa(); }\n");
|
|
static const hawk_ooch_t include_then_once[] = HAWK_T(
|
|
"@include \"a\";\n"
|
|
"@include_once \"alias-a\";\n"
|
|
"BEGIN { fa(); }\n");
|
|
static const hawk_ooch_t once_then_include[] = HAWK_T(
|
|
"@include_once \"a\";\n"
|
|
"@include \"alias-a\";\n");
|
|
hawk_sha256_ctx_t ctx;
|
|
hawk_uint8_t digest[HAWK_SHA256_DIGEST_LEN];
|
|
hawk_bch_t thousand_a[1000];
|
|
hawk_t* hawk;
|
|
int i;
|
|
|
|
no_plan();
|
|
|
|
hawk_sha256_digest(digest, "", 0);
|
|
OK(digest_matches(digest, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), "SHA-256 empty input");
|
|
|
|
hawk_sha256_digest(digest, abc, HAWK_SIZEOF(abc) - 1);
|
|
OK(digest_matches(digest, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), "SHA-256 abc");
|
|
|
|
hawk_sha256_init(&ctx);
|
|
hawk_sha256_update(&ctx, &abc[0], 1);
|
|
hawk_sha256_update(&ctx, &abc[1], 1);
|
|
hawk_sha256_update(&ctx, &abc[2], 1);
|
|
hawk_sha256_final(&ctx, digest);
|
|
OK(digest_matches(digest, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), "SHA-256 incremental updates");
|
|
|
|
hawk_sha256_digest(digest, long_input, HAWK_SIZEOF(long_input) - 1);
|
|
OK(digest_matches(digest, "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"), "SHA-256 two-block padding");
|
|
|
|
memset(thousand_a, 'a', HAWK_SIZEOF(thousand_a));
|
|
hawk_sha256_init(&ctx);
|
|
for (i = 0; i < 1000; i++) hawk_sha256_update(&ctx, thousand_a, HAWK_SIZEOF(thousand_a));
|
|
hawk_sha256_final(&ctx, digest);
|
|
OK(digest_matches(digest, "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"), "SHA-256 one million bytes");
|
|
|
|
hawk = hawk_openstd(0, HAWK_NULL);
|
|
OK(hawk != HAWK_NULL, "open interpreter");
|
|
if (hawk)
|
|
{
|
|
OK(parse_source(hawk, distinct_includes) >= 0, "include IDs with a common prefix and different lengths stay distinct");
|
|
OK(parse_source(hawk, duplicate_once) >= 0, "include_once skips an alias with the same ID");
|
|
OK(parse_source(hawk, include_then_once) >= 0, "include_once observes an earlier regular include");
|
|
OK(parse_source(hawk, once_then_include) <= -1, "regular include is not suppressed by include_once history");
|
|
hawk_close(hawk);
|
|
}
|
|
|
|
return exit_status();
|
|
}
|