blob: d00553e7efdb6286592cd67f67fb9bb1126cb8de [file] [log] [blame]
/*
* 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.
*
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lib/lib_vpd.h"
enum {
TEST_OK = 0,
TEST_FAIL = 1,
};
#define CU8 (const uint8_t *) /* for compiler warning on sign bit */
int testEncodeLen() {
unsigned char output[10];
int generated;
/* fail cases */
assert(VPD_ERR_INVALID == encodeLen(-1, output, 0, &generated));
assert(VPD_ERR_OVERFLOW == encodeLen(0x7f, output, 0, &generated));
/* success case - 1 byte output, all zeros */
assert(VPD_OK == encodeLen(0x00, output, 1, &generated));
assert(1 == generated);
assert(0x00 == output[0]);
/* success case - 1 byte output */
assert(VPD_OK == encodeLen(0x7f, output, 1, &generated));
assert(1 == generated);
assert(0x7f == output[0]);
/* 2 bytes of output */
assert(VPD_ERR_OVERFLOW == encodeLen(0x80, output, 1, &generated));
/* success */
assert(VPD_OK == encodeLen(0x80, output, 2, &generated));
assert(2 == generated);
assert(0x81 == output[0]);
assert(0x00 == output[1]);
/* 3 bytes of output */
assert(VPD_ERR_OVERFLOW == encodeLen(0x100040, output, 0, &generated));
assert(VPD_ERR_OVERFLOW == encodeLen(0x100040, output, 1, &generated));
assert(VPD_ERR_OVERFLOW == encodeLen(0x100040, output, 2, &generated));
/* success */
assert(VPD_OK == encodeLen(0x100040, output, 3, &generated));
assert(3 == generated);
assert(0xc0 == output[0]);
assert(0x80 == output[1]);
assert(0x40 == output[2]);
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testDecodeLen() {
uint32_t length;
uint32_t consumed;
{ /* max_len is 0. No more char in string. */
uint8_t encoded[] = { 0x00 };
assert(VPD_ERR_DECODE == decodeLen(0, encoded, &length, &consumed));
}
{ /* just decode one byte */
uint8_t encoded[] = { 0x00 };
assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));
assert(consumed == sizeof(encoded));
assert(length == 0);
}
{ /* just decode one byte */
uint8_t encoded[] = { 0x7F };
assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));
assert(consumed == sizeof(encoded));
assert(length == 0x7F);
}
{ /* more bit is set, but reachs end of string. */
uint8_t encoded[] = { 0x80 };
assert(VPD_ERR_DECODE == decodeLen(
sizeof(encoded), encoded, &length, &consumed));
}
{ /* decode 2 bytes, but reachs end of string. */
uint8_t encoded[] = { 0x81, 0x02 };
assert(VPD_ERR_DECODE == decodeLen(1, encoded, &length, &consumed));
}
{ /* more bit is set, but reachs end of string. */
uint8_t encoded[] = { 0x81, 0x82 };
assert(VPD_ERR_DECODE == decodeLen(sizeof(encoded), encoded, &length, &consumed));
}
{ /* decode 2 bytes, normal case */
uint8_t encoded[] = { 0x81, 0x02 };
assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));
assert(consumed == sizeof(encoded));
assert(length == 0x82);
}
{ /* decode 2 bytes, normal case (bot reach end of string). */
uint8_t encoded[] = { 0xFF, 0x7F, 0xFF };
assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));
assert(consumed == 2);
assert(length == 0x3FFF);
}
{ /* weird case, but still valid. */
uint8_t encoded[] = { 0x80, 0x00 };
assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));
assert(consumed == sizeof(encoded));
assert(length == 0);
}
{ /* test max length */
uint8_t encoded[] = { 0x87, 0xFF, 0xFF, 0xFF, 0x7F };
assert(VPD_OK == decodeLen(sizeof(encoded), encoded, &length, &consumed));
assert(consumed == sizeof(encoded));
assert(length == 0x7FFFFFFF);
}
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testEncodeVpdString() {
unsigned char expected[] = {
VPD_TYPE_STRING,
0x03, 'K', 'E', 'Y',
0x05, 'V', 'A', 'L', 'U', 'E',
};
unsigned char buf[256];
int generated = 0;
assert(VPD_OK ==
encodeVpdString(CU8"KEY", CU8"VALUE",
VPD_AS_LONG_AS, sizeof(buf), buf, &generated));
assert(sizeof(expected) == generated);
assert(!memcmp(expected, buf, generated));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testEncodeVpdStringPadding() {
unsigned char expected[] = {
VPD_TYPE_STRING,
0x03, 'K', 'E', 'Y',
0x08, 'V', 'A', 'L', 'U', 'E', '\0', '\0', '\0',
};
unsigned char buf[256];
int generated = 0;
assert(VPD_OK == encodeVpdString(CU8"KEY", CU8"VALUE",
8, sizeof(buf), buf, &generated));
assert(sizeof(expected) == generated);
assert(!memcmp(expected, buf, generated));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testEncodeMultiStrings() {
unsigned char expected[] = {
VPD_TYPE_STRING,
0x03, 'M', 'A', 'C',
0x08, '0', '1', '2', '3', '4', '5', '6', '7',
VPD_TYPE_STRING,
0x07, 'P', 'r', 'o', 'd', '/', 'I', 'd',
0x0c, 'M', 'a', 'r', 'i', 'o', '0', '9', '2', '8', '4', '\0', '\0',
};
unsigned char buf[256];
int generated = 0;
assert(VPD_OK == encodeVpdString(CU8"MAC", CU8"01234567",
0x08, sizeof(buf), buf, &generated));
assert(VPD_OK == encodeVpdString(CU8"Prod/Id", CU8"Mario09284",
0x0c, sizeof(buf), buf, &generated));
assert(sizeof(expected) == generated);
assert(!memcmp(expected, buf, generated));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testContainer() {
unsigned char expected[] = {
VPD_TYPE_STRING,
0x03, 'K', 'E', 'Y',
0x08, 'V', 'A', 'L', 'U', 'E', '\0', '\0', '\0',
};
unsigned char buf[256];
int generated = 0;
struct PairContainer container;
initContainer(&container);
setString(&container, CU8"KEY", CU8"VALUE", 8);
encodeContainer(&container, sizeof(buf), buf, &generated);
assert(sizeof(expected) == generated);
assert(!memcmp(expected, buf, generated));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
/* Based on previous test cases:
*
* KEY=VALUE --> encode --> decode --> expected KEY=VALUE
*/
int testDecodeVpdString() {
unsigned char expected[] = {
VPD_TYPE_STRING,
0x03, 'K', 'E', 'Y',
0x08, 'V', 'A', 'L', 'U', 'E', '\0', '\0', '\0',
};
unsigned char buf[256];
uint32_t consumed = 0;
struct PairContainer container;
int encode_consumed = 0;
initContainer(&container);
assert(VPD_OK == decodeToContainer(&container, sizeof(expected), expected,
&consumed));
assert(sizeof(expected) == consumed);
encodeContainer(&container, sizeof(buf), buf, &encode_consumed);
assert(sizeof(expected) == encode_consumed);
assert(!memcmp(expected, buf, encode_consumed));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testDeleteEmptyContainer() {
struct PairContainer container;
initContainer(&container);
assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));
/* still good for add */
setString(&container, CU8"FIRST", CU8"1", 8);
assert(NULL != findString(&container, CU8"FIRST", NULL));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testDeleteFirstOfOne() {
struct PairContainer container;
initContainer(&container);
/* test the case that only one string in container. */
setString(&container, CU8"FIRST", CU8"1", 8);
assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));
assert(VPD_OK == deleteKey(&container, CU8"FIRST"));
assert(NULL == findString(&container, CU8"FIRST", NULL));
/* still good for add */
setString(&container, CU8"SECOND", CU8"2", 12);
assert(NULL != findString(&container, CU8"SECOND", NULL));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testDeleteFirstOfTwo() {
struct PairContainer container;
initContainer(&container);
/* add 2 and remove the first one */
setString(&container, CU8"FIRST", CU8"1", 8);
setString(&container, CU8"SECOND", CU8"2", 8);
assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));
assert(VPD_OK == deleteKey(&container, CU8"FIRST"));
assert(NULL == findString(&container, CU8"FIRST", NULL));
assert(NULL != findString(&container, CU8"SECOND", NULL));
/* still good for add */
setString(&container, CU8"FIRST", CU8"1", 9);
assert(NULL != findString(&container, CU8"FIRST", NULL));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testDeleteSecondOfTwo() {
struct PairContainer container;
initContainer(&container);
/* add 2 and remove the last one */
setString(&container, CU8"FIRST", CU8"1", 8);
setString(&container, CU8"SECOND", CU8"2", 8);
assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));
assert(VPD_OK == deleteKey(&container, CU8"SECOND"));
assert(NULL != findString(&container, CU8"FIRST", NULL));
assert(NULL == findString(&container, CU8"SECOND", NULL));
/* still good for add */
setString(&container, CU8"SECOND", CU8"2", 5);
assert(NULL != findString(&container, CU8"SECOND", NULL));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int testDeleteSecondOfThree() {
unsigned char expected[] = {
VPD_TYPE_STRING,
0x05, 'F', 'I', 'R', 'S', 'T',
0x03, '1', '\0', '\0',
VPD_TYPE_STRING,
0x05, 'T', 'H', 'I', 'R', 'D',
0x04, '3', '\0', '\0', '\0',
};
unsigned char buf[256];
int generated = 0;
struct PairContainer container;
initContainer(&container);
/* add 3 and remove the middle one */
setString(&container, CU8"FIRST", CU8"1", 3);
setString(&container, CU8"SECOND", CU8"2", 2);
setString(&container, CU8"THIRD", CU8"3", 4);
assert(VPD_FAIL == deleteKey(&container, CU8"NON_EXISTED_KEY"));
assert(VPD_OK == deleteKey(&container, CU8"SECOND"));
assert(NULL != findString(&container, CU8"FIRST", NULL));
assert(NULL == findString(&container, CU8"SECOND", NULL));
assert(NULL != findString(&container, CU8"THIRD", NULL));
/* expect the middle one is removed. */
encodeContainer(&container, sizeof(buf), buf, &generated);
assert(sizeof(expected) == generated);
assert(!memcmp(expected, buf, generated));
/* still good if we delete all */
assert(VPD_OK == deleteKey(&container, CU8"THIRD"));
assert(VPD_OK == deleteKey(&container, CU8"FIRST"));
/* still good for add */
setString(&container, CU8"FORTH", CU8"4", 4);
assert(NULL != findString(&container, CU8"FORTH", NULL));
setString(&container, CU8"FIFTH", CU8"5", 5);
assert(NULL != findString(&container, CU8"FIFTH", NULL));
printf("[PASS] %s()\n", __FUNCTION__);
return TEST_OK;
}
int main() {
assert(TEST_OK == testEncodeLen());
assert(TEST_OK == testDecodeLen());
assert(TEST_OK == testEncodeVpdString());
assert(TEST_OK == testEncodeVpdStringPadding());
assert(TEST_OK == testEncodeMultiStrings());
assert(TEST_OK == testContainer());
assert(TEST_OK == testDecodeVpdString());
assert(TEST_OK == testDeleteEmptyContainer());
assert(TEST_OK == testDeleteFirstOfOne());
assert(TEST_OK == testDeleteFirstOfTwo());
assert(TEST_OK == testDeleteSecondOfTwo());
assert(TEST_OK == testDeleteSecondOfThree());
printf("SUCCESS!\n");
return 0;
}