/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Tests for firmware display library.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "bmpblk_font.h"
#include "gbb_header.h"
#include "host_common.h"
#include "test_common.h"
#include "vboot_common.h"
#include "vboot_display.h"
#include "vboot_nvstorage.h"

/* Mock data */
static VbCommonParams cparams;
static VbNvContext vnc;
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
static char gbb_data[4096 + sizeof(GoogleBinaryBlockHeader)];
static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)gbb_data;
static BmpBlockHeader *bhdr;
static char debug_info[4096];

/* Reset mock data (for use before each test) */
static void ResetMocks(void)
{
	int gbb_used;

	Memset(gbb_data, 0, sizeof(gbb_data));
	gbb->major_version = GBB_MAJOR_VER;
	gbb->minor_version = GBB_MINOR_VER;
	gbb->flags = 0;
	gbb_used = sizeof(GoogleBinaryBlockHeader);

	gbb->hwid_offset = gbb_used;
	strcpy(gbb_data + gbb->hwid_offset, "Test HWID");
	gbb->hwid_size = strlen(gbb_data + gbb->hwid_offset) + 1;
	gbb_used = (gbb_used + gbb->hwid_size + 7) & ~7;

	gbb->bmpfv_offset = gbb_used;
	bhdr = (BmpBlockHeader *)(gbb_data + gbb->bmpfv_offset);
	gbb->bmpfv_size = sizeof(BmpBlockHeader);
	gbb_used = (gbb_used + gbb->bmpfv_size + 7) & ~7;
	memcpy(bhdr->signature, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE);
	bhdr->major_version = BMPBLOCK_MAJOR_VERSION;
	bhdr->minor_version = BMPBLOCK_MINOR_VERSION;
	bhdr->number_of_localizations = 3;

	Memset(&cparams, 0, sizeof(cparams));
	cparams.shared_data_size = sizeof(shared_data);
	cparams.shared_data_blob = shared_data;
	cparams.gbb_data = gbb;
	cparams.gbb_size = sizeof(gbb_data);

	Memset(&vnc, 0, sizeof(vnc));
	VbNvSetup(&vnc);
	VbNvTeardown(&vnc);                   /* So CRC gets generated */

	Memset(&shared_data, 0, sizeof(shared_data));
	VbSharedDataInit(shared, sizeof(shared_data));

	*debug_info = 0;
}

/* Mocks */

VbError_t VbExDisplayDebugInfo(const char *info_str)
{
	strncpy(debug_info, info_str, sizeof(debug_info));
	debug_info[sizeof(debug_info) - 1] = '\0';
	return VBERROR_SUCCESS;
}

/* Test displaying debug info */
static void DebugInfoTest(void)
{
	int i;

	/* Recovery string should be non-null for any code */
	for (i = 0; i < 0x100; i++)
		TEST_PTR_NEQ(RecoveryReasonString(i), NULL, "Non-null reason");

	/* HWID should come from the gbb */
	ResetMocks();
	TEST_EQ(strcmp(VbHWID(&cparams), "Test HWID"), 0, "HWID");

	ResetMocks();
	cparams.gbb_size = 0;
	TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID bad gbb");

	ResetMocks();
	gbb->hwid_size = 0;
	TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID missing");

	ResetMocks();
	gbb->hwid_offset = cparams.gbb_size + 1;
	TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID past end");

	ResetMocks();
	gbb->hwid_size = cparams.gbb_size;
	TEST_EQ(strcmp(VbHWID(&cparams), "{INVALID}"), 0, "HWID overflow");

	/* Display debug info */
	ResetMocks();
	VbDisplayDebugInfo(&cparams, &vnc);
	TEST_NEQ(*debug_info, '\0', "Some debug info was displayed");
}

/* Test localization */
static void LocalizationTest(void)
{
	uint32_t count = 6;

	ResetMocks();
	gbb->bmpfv_size = 0;
	TEST_EQ(VbGetLocalizationCount(&cparams, &count),
		VBERROR_INVALID_GBB, "VbGetLocalizationCount bad gbb");
	TEST_EQ(count, 0, "  count");

	ResetMocks();
	bhdr->signature[0] ^= 0x5a;
	TEST_EQ(VbGetLocalizationCount(&cparams, &count),
		VBERROR_INVALID_BMPFV, "VbGetLocalizationCount bad bmpfv");

	ResetMocks();
	TEST_EQ(VbGetLocalizationCount(&cparams, &count), 0,
		"VbGetLocalizationCount()");
	TEST_EQ(count, 3, "  count");

}

/* Test display key checking */
static void DisplayKeyTest(void)
{
	uint32_t u;

	ResetMocks();
	VbCheckDisplayKey(&cparams, 'q', &vnc);
	TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing");

	ResetMocks();
	VbCheckDisplayKey(&cparams, '\t', &vnc);
	TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display");

	/* Toggle localization */
	ResetMocks();
	VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0);
	VbNvTeardown(&vnc);
	VbCheckDisplayKey(&cparams, VB_KEY_DOWN, &vnc);
	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
	TEST_EQ(u, 2, "DisplayKey up");
	VbCheckDisplayKey(&cparams, VB_KEY_LEFT, &vnc);
	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
	TEST_EQ(u, 1, "DisplayKey left");
	VbCheckDisplayKey(&cparams, VB_KEY_RIGHT, &vnc);
	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
	TEST_EQ(u, 2, "DisplayKey right");
	VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
	TEST_EQ(u, 0, "DisplayKey up");

	/* Reset localization if localization count is invalid */
	ResetMocks();
	VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 1);
	VbNvTeardown(&vnc);
	bhdr->signature[0] ^= 0x5a;
	VbCheckDisplayKey(&cparams, VB_KEY_UP, &vnc);
	VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
	TEST_EQ(u, 0, "DisplayKey invalid");

}

static void FontTest(void)
{
	FontArrayHeader h;
	FontArrayEntryHeader eh[3] = {
		{
			.ascii = 'A',
			.info.original_size = 10,
		},
		{
			.ascii = 'B',
			.info.original_size = 20,
		},
		{
			.ascii = 'C',
			.info.original_size = 30,
		},
	};
	FontArrayEntryHeader *eptr;
	uint8_t buf[sizeof(h) + sizeof(eh)];
	VbFont_t *fptr;
	void *bufferptr;
	uint32_t buffersize;

	/* Create font data */
	h.num_entries = ARRAY_SIZE(eh);
	Memcpy(buf, &h, sizeof(h));
	eptr = (FontArrayEntryHeader *)(buf + sizeof(h));
	Memcpy(eptr, eh, sizeof(eh));

	fptr = VbInternalizeFontData((FontArrayHeader *)buf);
	TEST_PTR_EQ(fptr, buf, "Internalize");

	TEST_PTR_EQ(VbFindFontGlyph(fptr, 'B', &bufferptr, &buffersize),
		    &eptr[1].info, "Glyph found");
	TEST_EQ(buffersize, eptr[1].info.original_size, "  size");
	TEST_PTR_EQ(VbFindFontGlyph(fptr, 'X', &bufferptr, &buffersize),
		    &eptr[0].info, "Glyph not found");
	TEST_EQ(buffersize, eptr[0].info.original_size, "  size");

	/* Test invalid rendering params */
	VbRenderTextAtPos(NULL, 0, 0, 0, fptr);
	VbRenderTextAtPos("ABC", 0, 0, 0, NULL);

	VbDoneWithFontForNow(fptr);

}

int main(void)
{
	DebugInfoTest();
	LocalizationTest();
	DisplayKeyTest();
	FontTest();

	return gTestSuccess ? 0 : 255;
}
