// SPDX-License-Identifier: 0BSD

#include "uuid_dce.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
_Static_assert(sizeof(uuid_t) == 16, "UUIDs are 16 bytes");


static const uuid_t nil;

int main() {
	int status;
	assert(uuid_is_nil((uuid_t *)&nil, &status));
	assert(status == uuid_s_ok);
	assert(!uuid_is_nil(NULL, &status));
	assert(status == uuid_s_error);


	uuid_t uuid;
	uuid_create_nil(&uuid, &status);
	assert(status == uuid_s_ok);
	assert(!memcmp(&uuid, &nil, sizeof(uuid)));
	assert(uuid_is_nil(&uuid, &status));
	assert(status == uuid_s_ok);


	uuid_create(&uuid, &status);  // this generates a V1 UUID
	assert(status == uuid_s_ok);
	assert(memcmp(&uuid, &nil, sizeof(uuid)));
	assert(status == uuid_s_ok);

	if(uuid.data[0] == 0 || uuid.data[0] == 0xFF)  // avoid wrapping below
		uuid.data[0] = 0x80;
	uuid_t uuid_copy = uuid;
	assert(uuid_compare(&uuid, &uuid_copy, &status) == 0);
	assert(status == uuid_s_ok);
	uuid_copy.data[0] -= 1;
	assert(uuid_compare(&uuid, &uuid_copy, &status) >= 0);
	assert(status == uuid_s_ok);
	uuid_copy.data[0] += 2;
	assert(uuid_compare(&uuid, &uuid_copy, &status) <= 0);
	assert(status == uuid_s_ok);


	uuid_t uuid2;
	uuid_create(&uuid2, &status);  // this generates a V1 UUID
	assert(status == uuid_s_ok);
	assert(!uuid_equal(&uuid, &uuid2, &status));
	assert(status == uuid_s_ok);

	uuid_t uuid2_copy = uuid2;
	assert(uuid_equal(&uuid2, &uuid2_copy, &status));
	assert(status == uuid_s_ok);
	assert(!uuid_equal(&uuid2, NULL, &status));
	assert(status == uuid_s_error);
	assert(!uuid_equal(NULL, &uuid2_copy, &status));
	assert(status == uuid_s_error);

	uuid_from_string("f50c5fcc-6b66-11ef-bafc-efdff7d5f2f6", &uuid, &status);
	assert(status == uuid_s_ok);
	assert(!memcmp(uuid.data, (unsigned char[]){0xF5, 0x0C, 0x5F, 0xCC, 0x6B, 0x66, 0x11, 0xEF, 0xBA, 0xFC, 0xEF, 0xDF, 0xF7, 0xD5, 0xF2, 0xF6}, 16));

	assert(uuid_dce_hash(NULL, &status) == 0);
	assert(status == uuid_s_error);
	assert(uuid_dce_hash(&uuid, &status) == 0xCC5F0CF5); // https://pubs.opengroup.org/onlinepubs/9629399/uuid_hash.htm says "may vary between implementations"
	                                                     // but for this one it's the top 4 bytes in little-endian
	assert(status == uuid_s_ok);


	char * str = NULL;
	uuid_to_string((uuid_t *)&nil, NULL, &status);
	assert(status == uuid_s_error);
	uuid_to_string((uuid_t *)&nil, &str, NULL);
	assert(status == uuid_s_error);
	uuid_to_string((uuid_t *)&nil, &str, &status);
	assert(status == uuid_s_ok);
	assert(!strcmp(str, "00000000-0000-0000-0000-000000000000"));
	free(str);

	str = NULL;
	uuid_to_string(&uuid, &str, &status);
	assert(status == uuid_s_ok);
	assert(!strcmp(str, "f50c5fcc-6b66-11ef-bafc-efdff7d5f2f6"));
	free(str);
}
