/* 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 <stdint.h>
#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;
}
