mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys: add base64 encoding/decoding module
- suppressed cppcheck warning for `unassignedVariable` for the encode/decode arrays in stream encode/decode tests as these arrays are assigned by the according `base64_[en|de]code()` function.
This commit is contained in:
parent
b0045b21df
commit
a0898dbb9f
1
sys/base64/Makefile
Normal file
1
sys/base64/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
219
sys/base64/base64.c
Normal file
219
sys/base64/base64.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup base64
|
||||
* @{
|
||||
* @file base64.c
|
||||
* @brief Functions to encode and decode base64
|
||||
*
|
||||
* @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
#define BASE64_CAPITAL_UPPER_BOUND (25) /**< base64 'Z' */
|
||||
#define BASE64_SMALL_UPPER_BOUND (51) /**< base64 'z' */
|
||||
#define BASE64_NUMBER_UPPER_BOUND (61) /**< base64 '9' */
|
||||
#define BASE64_PLUS (62) /**< base64 '+' */
|
||||
#define BASE64_SLASH (63) /**< base64 '/' */
|
||||
#define BASE64_EQUALS (0xFE) /**< no base64 symbol '=' */
|
||||
#define BASE64_NOT_DEFINED (0xFF) /**< no base64 symbol */
|
||||
|
||||
/*
|
||||
* returns the corresponding ascii symbol value for the given base64 code
|
||||
*/
|
||||
static char getsymbol(unsigned char code)
|
||||
{
|
||||
if (code == BASE64_SLASH) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
if (code == BASE64_PLUS) {
|
||||
return '+';
|
||||
}
|
||||
|
||||
if (code <= BASE64_CAPITAL_UPPER_BOUND) {
|
||||
return (code + 'A');
|
||||
}
|
||||
|
||||
if (code <= BASE64_SMALL_UPPER_BOUND) {
|
||||
return (code + ('z' - BASE64_SMALL_UPPER_BOUND));
|
||||
}
|
||||
|
||||
if (code <= BASE64_NUMBER_UPPER_BOUND) {
|
||||
return (code + ('9' - BASE64_NUMBER_UPPER_BOUND));
|
||||
}
|
||||
|
||||
return (char)BASE64_NOT_DEFINED;
|
||||
}
|
||||
|
||||
int base64_encode(unsigned char *data_in, size_t data_in_size, \
|
||||
unsigned char *base64_out, size_t *base64_out_size)
|
||||
{
|
||||
size_t padding_bytes = ((data_in_size % 3) ? (3 - (data_in_size % 3)) : 0);
|
||||
size_t required_size = (4 * (data_in_size + 2 - ((data_in_size + 2) % 3)) / 3) + padding_bytes;
|
||||
|
||||
if (data_in == NULL) {
|
||||
return BASE64_ERROR_DATA_IN;
|
||||
}
|
||||
|
||||
if (data_in_size < 1) {
|
||||
return BASE64_ERROR_DATA_IN_SIZE;
|
||||
}
|
||||
|
||||
if (*base64_out_size < required_size) {
|
||||
*base64_out_size = required_size;
|
||||
return BASE64_ERROR_BUFFER_OUT_SIZE;
|
||||
}
|
||||
|
||||
if (base64_out == NULL) {
|
||||
return BASE64_ERROR_BUFFER_OUT;
|
||||
}
|
||||
|
||||
int iterate_base64_buffer = 0;
|
||||
unsigned char nNum = 0;
|
||||
int nLst = 0;
|
||||
int njump = 0;
|
||||
unsigned char tmpval;
|
||||
|
||||
for (int i = 0; i < (int)(data_in_size); ++i) {
|
||||
njump++;
|
||||
tmpval = *(data_in + i);
|
||||
|
||||
nNum = (tmpval >> (2 * njump));
|
||||
|
||||
if (njump == 4) {
|
||||
nNum = nLst << (8 - 2 * njump);
|
||||
njump = 0;
|
||||
nLst = 0;
|
||||
--i;
|
||||
}
|
||||
else {
|
||||
nNum += nLst << (8 - 2 * njump);
|
||||
nLst = tmpval & ((1 << njump * 2) - 1);
|
||||
}
|
||||
|
||||
base64_out[iterate_base64_buffer++] = getsymbol(nNum);
|
||||
}
|
||||
|
||||
/* The last character is not finished yet */
|
||||
njump++;
|
||||
|
||||
if (njump == 4) {
|
||||
nNum = (tmpval >> (2 * njump));
|
||||
}
|
||||
|
||||
nNum = nLst << (8 - 2 * njump);
|
||||
base64_out[iterate_base64_buffer++] = getsymbol(nNum);
|
||||
|
||||
/* if required we append '=' for the required dividability */
|
||||
while (iterate_base64_buffer % 4) {
|
||||
base64_out[iterate_base64_buffer++] = '=';
|
||||
}
|
||||
|
||||
*base64_out_size = iterate_base64_buffer;
|
||||
|
||||
return BASE64_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the corresponding base64 code for the given ascii symbol
|
||||
*/
|
||||
static int getcode(char symbol)
|
||||
{
|
||||
if (symbol == '/') {
|
||||
return BASE64_SLASH;
|
||||
}
|
||||
|
||||
if (symbol == '+') {
|
||||
return BASE64_PLUS;
|
||||
}
|
||||
|
||||
if (symbol == '=') {
|
||||
/* indicates a padded base64 end */
|
||||
return BASE64_EQUALS;
|
||||
}
|
||||
|
||||
if (symbol < '0') {
|
||||
/* indicates that the given symbol is not base64 and should be ignored */
|
||||
return BASE64_NOT_DEFINED;
|
||||
}
|
||||
|
||||
if (symbol <= '9' && symbol >= '0') {
|
||||
return (symbol + (BASE64_NUMBER_UPPER_BOUND - '9'));
|
||||
}
|
||||
|
||||
if (symbol <= 'Z' && symbol >= 'A') {
|
||||
return (symbol - 'A');
|
||||
}
|
||||
|
||||
if (symbol <= 'z' && symbol >= 'a') {
|
||||
return (symbol + (BASE64_SMALL_UPPER_BOUND - 'z'));
|
||||
}
|
||||
|
||||
/* indicates that the given symbol is not base64 and should be ignored */
|
||||
return BASE64_NOT_DEFINED;
|
||||
}
|
||||
|
||||
int base64_decode(unsigned char *base64_in, size_t base64_in_size, \
|
||||
unsigned char *data_out, size_t *data_out_size)
|
||||
{
|
||||
size_t required_size = ((base64_in_size / 4) * 3);
|
||||
|
||||
if (base64_in == NULL) {
|
||||
return BASE64_ERROR_DATA_IN;
|
||||
}
|
||||
|
||||
if (base64_in_size < 4) {
|
||||
return BASE64_ERROR_DATA_IN_SIZE;
|
||||
}
|
||||
|
||||
if (*data_out_size < required_size) {
|
||||
*data_out_size = required_size;
|
||||
return BASE64_ERROR_BUFFER_OUT_SIZE;
|
||||
}
|
||||
|
||||
if (data_out == NULL) {
|
||||
return BASE64_ERROR_BUFFER_OUT;
|
||||
}
|
||||
|
||||
int iterate_data_buffer = 0;
|
||||
unsigned char nNum = 0;
|
||||
int nLst = getcode(base64_in[0]) << 2;
|
||||
int code = 0;
|
||||
|
||||
int mask = 2;
|
||||
|
||||
for (int i = 1; i < (int)(base64_in_size); i++) {
|
||||
code = getcode(base64_in[i]);
|
||||
|
||||
if (code == BASE64_NOT_DEFINED || code == BASE64_EQUALS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int nm = (0xFF << (2 * mask));
|
||||
|
||||
nNum = nLst + ((code & (0xFF & nm)) >> (2 * mask));
|
||||
nLst = (code & (0xFF & ~nm)) << (8 - (2 * mask));
|
||||
|
||||
(mask != 3) ? data_out[iterate_data_buffer++] = nNum : nNum;
|
||||
(mask == 0) ? mask = 3 : mask--;
|
||||
}
|
||||
|
||||
if (code == BASE64_EQUALS) {
|
||||
/* add the last character to the data_out buffer */
|
||||
data_out[iterate_data_buffer] = nNum;
|
||||
}
|
||||
|
||||
*data_out_size = iterate_data_buffer;
|
||||
return BASE64_SUCCESS;
|
||||
}
|
82
sys/include/base64.h
Normal file
82
sys/include/base64.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_base64 base64 encoder decoder
|
||||
* @ingroup sys
|
||||
* @brief base64 encoder and decoder
|
||||
* @{
|
||||
*
|
||||
* @brief encoding and decoding functions for base64
|
||||
* @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef _BASE64_ENCODER_DECODER_H
|
||||
#define _BASE64_ENCODER_DECODER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BASE64_SUCCESS (0) /**< return value for success */
|
||||
#define BASE64_ERROR_BUFFER_OUT (-1) /**< error value for invalid output buffer pointer */
|
||||
#define BASE64_ERROR_BUFFER_OUT_SIZE (-2) /**< error value for invalid output buffer size */
|
||||
#define BASE64_ERROR_DATA_IN (-3) /**< error value for invalid input buffer */
|
||||
#define BASE64_ERROR_DATA_IN_SIZE (-4) /**< error value for invalid output buffer size */
|
||||
|
||||
/**
|
||||
* @brief Encodes a given datum to base64 and save the result to the given destination.
|
||||
* @param[in] data_in pointer to the datum to encode
|
||||
* @param[in] data_in_size the size of `data_in`
|
||||
* @param[out] base64_out pointer to store the encoded base64 string
|
||||
* @param[in,out] base64_out_size pointer to the variable containing the size of `base64_out.`
|
||||
This value is overwritten with the estimated size used for
|
||||
the encoded base64 string on BASE64_ERROR_BUFFER_OUT_SIZE.
|
||||
This value is overwritten with the actual used size for the
|
||||
encoded base64 string on BASE64_SUCCESS.
|
||||
|
||||
* @returns BASE64_SUCCESS on success,
|
||||
BASE64_ERROR_BUFFER_OUT_SIZE on insufficient size for encoding to `base64_out`,
|
||||
BASE64_ERROR_BUFFER_OUT if `base64_out` equals NULL
|
||||
but the `base64_out_size` is sufficient,
|
||||
BASE64_ERROR_DATA_IN if `data_in` equals NULL,
|
||||
BASE64_ERROR_DATA_IN_SIZE if `data_in_size` is less then 1.
|
||||
*/
|
||||
int base64_encode(unsigned char *data_in, size_t data_in_size, \
|
||||
unsigned char *base64_out, size_t *base64_out_size);
|
||||
|
||||
/**
|
||||
* @brief Decodes a given base64 string and save the result to the given destination.
|
||||
* @param[out] base64_in pointer to store the encoded base64 string
|
||||
* @param[in] base64_in_size pointer to the variable containing the size of `base64_out.`
|
||||
* @param[in] data_out pointer to the datum to encode
|
||||
* @param[in, out] data_out_size the size of `data_out`.
|
||||
This value is overwritten with the estimated size used for the
|
||||
decoded string on BASE64_ERROR_BUFFER_OUT_SIZE.
|
||||
This value is overwritten with the actual used size for the
|
||||
decoded string on BASE64_SUCCESS.
|
||||
|
||||
* @returns BASE64_SUCCESS on success,
|
||||
BASE64_ERROR_BUFFER_OUT_SIZE on insufficient size for decoding to `data_out`,
|
||||
BASE64_ERROR_BUFFER_OUT if `data_out` equals NULL
|
||||
but the size for `data_out_size` is sufficient,
|
||||
BASE64_ERROR_DATA_IN if `base64_in` equals NULL,
|
||||
BASE64_ERROR_DATA_IN_SIZE if `base64_in_size` is less then 4.
|
||||
*/
|
||||
int base64_decode(unsigned char *base64_in, size_t base64_in_size, \
|
||||
unsigned char *data_out, size_t *data_out_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
#endif /* _BASE64_ENCODER_DECODER_H */
|
3
tests/unittests/tests-base64/Makefile
Normal file
3
tests/unittests/tests-base64/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = tests-base64
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
1
tests/unittests/tests-base64/Makefile.include
Normal file
1
tests/unittests/tests-base64/Makefile.include
Normal file
@ -0,0 +1 @@
|
||||
USEMODULE += base64
|
324
tests/unittests/tests-base64/tests-base64.c
Normal file
324
tests/unittests/tests-base64/tests-base64.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martin Landsmann
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#define TEST_BASE64_SHOW_OUTPUT (0) /**< set if encoded/decoded string is displayed */
|
||||
|
||||
#if (TEST_BASE64_SHOW_OUTPUT == 1)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "embUnit.h"
|
||||
#include "tests-base64.h"
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
static void test_base64_01_encode_string(void)
|
||||
{
|
||||
unsigned char data_in[] = "Hello RIOT this is a base64 test!\n"
|
||||
"This should work as intended.";
|
||||
|
||||
unsigned char expected_encoding[] = "SGVsbG8gUklPVCB0aGlzIGlzIGEgYmFzZTY0IHR"
|
||||
"lc3QhClRoaXMgc2hvdWxkIHdvcmsgYXMgaW50ZW5kZWQu";
|
||||
|
||||
size_t data_in_size = strlen((char *)data_in);
|
||||
|
||||
size_t base64_out_size = 0;
|
||||
unsigned char base64_out[ strlen((char *)expected_encoding) ];
|
||||
|
||||
/*
|
||||
* @Note:
|
||||
* The first encoding attempt fails, but reveals the required out size.
|
||||
*
|
||||
* This size is a lower bound estimation,
|
||||
* thus it can require few more bytes then the actual used size for the output.
|
||||
*/
|
||||
int ret = base64_encode(data_in, data_in_size, NULL, &base64_out_size);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_ERROR_BUFFER_OUT_SIZE, ret);
|
||||
|
||||
ret = base64_encode(data_in, data_in_size, base64_out, &base64_out_size);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
for (int i = 0; i < (int)base64_out_size; ++i) {
|
||||
TEST_ASSERT_MESSAGE(base64_out[i] == expected_encoding[i], \
|
||||
"encoding failed!(produced unexpected output)");
|
||||
}
|
||||
|
||||
#if (TEST_BASE64_SHOW_OUTPUT == 1)
|
||||
puts("Test 01 Encoded:");
|
||||
|
||||
for (int i = 0; i < (int)base64_out_size; ++i) {
|
||||
printf("%c", base64_out[i]);
|
||||
}
|
||||
|
||||
printf("\nFrom:\n%s\n", (char *)data_in);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_base64_02_decode_base64(void)
|
||||
{
|
||||
unsigned char encoded_base64[] = "SGVsbG8gUklPVCB0aGlzIGlzIGEgYmFzZTY0IHRlc3Q"
|
||||
"hClRoaXMgc2hvdWxkIHdvcmsgYXMgaW50ZW5kZWQu";
|
||||
|
||||
unsigned char expected_string[] = "Hello RIOT this is a base64 test!\n"
|
||||
"This should work as intended.";
|
||||
|
||||
size_t base64_size = strlen((char *)encoded_base64);
|
||||
|
||||
size_t data_out_size = 0;
|
||||
unsigned char data_out[ strlen((char *)expected_string) ];
|
||||
|
||||
int ret = base64_decode(encoded_base64, base64_size, NULL, &data_out_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_ERROR_BUFFER_OUT_SIZE, ret);
|
||||
|
||||
ret = base64_decode(encoded_base64, base64_size, NULL, &data_out_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_ERROR_BUFFER_OUT, ret);
|
||||
|
||||
ret = base64_decode(encoded_base64, base64_size, data_out, &data_out_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
for (int i = 0; i < (int)data_out_size; ++i) {
|
||||
TEST_ASSERT_MESSAGE(data_out[i] == expected_string[i], \
|
||||
"decoding failed!(produced unexpected output)");
|
||||
}
|
||||
|
||||
#if (TEST_BASE64_SHOW_OUTPUT == 1)
|
||||
puts("Test 02 Decoded:");
|
||||
|
||||
for (int i = 0; i < (int)data_out_size; ++i) {
|
||||
printf("%c", data_out[i]);
|
||||
}
|
||||
|
||||
printf("\nFrom:\n%s\n", (char *)encoded_base64);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_base64_03_single_character(void)
|
||||
{
|
||||
size_t element_size = 1;
|
||||
unsigned char element[] = "1";
|
||||
|
||||
size_t elementDecodeSize = 3;
|
||||
unsigned char elementDecode[3];
|
||||
|
||||
size_t element_base64_out_size = 10;
|
||||
unsigned char element_base64_out[10];
|
||||
|
||||
int ret = base64_encode(element, element_size, \
|
||||
element_base64_out, &element_base64_out_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
ret = base64_decode(element_base64_out, element_base64_out_size, \
|
||||
elementDecode, &elementDecodeSize);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
for (int i = 0; i < (int)elementDecodeSize; ++i) {
|
||||
TEST_ASSERT_MESSAGE(element[i] == elementDecode[i], \
|
||||
"decoding failed!(produced unexpected output)");
|
||||
}
|
||||
}
|
||||
|
||||
static void test_base64_04_free_conversion(void)
|
||||
{
|
||||
size_t elements = 255;
|
||||
unsigned char elm[elements];
|
||||
|
||||
size_t elem_base64_out_size = 0;
|
||||
unsigned char elm_base64_out[((elements / 3) * 4) + (elements / 10)];
|
||||
|
||||
size_t elem_base64_out_decoded_size = 0;
|
||||
unsigned char elem_base64_out_decoded[ elements + 10 ];
|
||||
|
||||
/* fill some values */
|
||||
for (int i = 0; i < (int)elements; ++i) {
|
||||
elm[i] = i;
|
||||
}
|
||||
|
||||
int ret = base64_encode(elm, elements, NULL, &elem_base64_out_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_ERROR_BUFFER_OUT_SIZE, ret);
|
||||
|
||||
ret = base64_encode(elm, elements, elm_base64_out, &elem_base64_out_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
ret = base64_decode(elm_base64_out, elem_base64_out_size, \
|
||||
NULL, &elem_base64_out_decoded_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_ERROR_BUFFER_OUT_SIZE, ret);
|
||||
|
||||
ret = base64_decode(elm_base64_out, elem_base64_out_size, \
|
||||
elem_base64_out_decoded, &elem_base64_out_decoded_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
for (int i = 0; i < (int)elements; ++i) {
|
||||
TEST_ASSERT_MESSAGE(elem_base64_out_decoded[i] == elm[i], \
|
||||
"decoding failed!(produced unexpected output)");
|
||||
}
|
||||
}
|
||||
|
||||
static void test_base64_05_decode_larger(void)
|
||||
{
|
||||
unsigned char decodeit[] = "SG93IG11Y2ggd29vZCB3b3VsZCBhIHdvb2RjaHVjayBjaHVj"
|
||||
"awppZiBhIHdvb2RjaHVjayBjb3VsZCBjaHVjayB3b29kPwpI"
|
||||
"ZSB3b3VsZCBjaHVjaywgaGUgd291bGQsIGFzIG11Y2ggYXMg"
|
||||
"aGUgY291bGQsCmFuZCBjaHVjayBhcyBtdWNoIHdvb2QgYXMg"
|
||||
"YSB3b29kY2h1Y2sgd291bGQKaWYgYSB3b29kY2h1Y2sgY291"
|
||||
"bGQgY2h1Y2sgd29vZC4==";
|
||||
|
||||
size_t data_size = 199;
|
||||
unsigned char data[data_size];
|
||||
|
||||
size_t decodeit_size = strlen((char *)decodeit);
|
||||
|
||||
int ret = base64_decode(decodeit, decodeit_size, data, &data_size);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
#if (TEST_BASE64_SHOW_OUTPUT == 1)
|
||||
puts("Test 05 Decoded:");
|
||||
|
||||
for (int i = 0; i < (int)data_size; ++i) {
|
||||
printf("%c", data[i]);
|
||||
}
|
||||
|
||||
printf("\nFrom:\n%s\n", (char *)decodeit);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_base64_06_stream_encode(void)
|
||||
{
|
||||
/*
|
||||
* @Note:
|
||||
* In this test we divide the `stream_encode[]` input for the encoding
|
||||
* into several portions (chunks).
|
||||
*
|
||||
* Every chunk is encoded and appended to the base64 `encode_result[]`.
|
||||
* To enable appending further, the chunks MUST be dividable by 3.
|
||||
* Only the final chunk MAY be prime to 3. (it is in this test)
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char stream_encode[] = "Peter Piper picked a peck of pickled peppers."
|
||||
"\nA peck of pickled peppers Peter Piper picked."
|
||||
"\nIf Peter Piper picked a peck of pickled peppers,"
|
||||
"\nWhere's the peck of pickled peppers Peter Piper picked?";
|
||||
|
||||
/* required output size +2 extra bytes */
|
||||
size_t encoded_size = 264 + 2;
|
||||
/* cppcheck-suppress unassignedVariable */
|
||||
unsigned char encode_result[encoded_size];
|
||||
/* the above array is used/assigned in base64_encode() using its pointer. */
|
||||
|
||||
int remain = strlen((char *)stream_encode);
|
||||
int out_iter = 0;
|
||||
|
||||
int ret = BASE64_SUCCESS;
|
||||
|
||||
for (int i = 3; i < remain; (i += 3)) {
|
||||
size_t size_used = encoded_size - out_iter;
|
||||
ret = base64_encode(stream_encode + (strlen((char *)stream_encode) - remain), \
|
||||
i, encode_result + out_iter, &size_used);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
out_iter += size_used;
|
||||
remain -= i;
|
||||
}
|
||||
|
||||
/* this final chunk we want to encode and append is prime to 3 */
|
||||
size_t finish = encoded_size - out_iter;
|
||||
ret = base64_encode(stream_encode + (strlen((char *)stream_encode) - remain), \
|
||||
remain, encode_result + out_iter, &finish);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
#if (TEST_BASE64_SHOW_OUTPUT == 1)
|
||||
out_iter += finish;
|
||||
puts("Test 06 Encoded:");
|
||||
|
||||
for (int i = 0; i < (int)out_iter; ++i) {
|
||||
printf("%c", encode_result[i]);
|
||||
}
|
||||
|
||||
printf("\nFrom:\n%s\n", (char *)stream_encode);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_base64_07_stream_decode(void)
|
||||
{
|
||||
/* @Note:
|
||||
* Here we decode the base64 string `encoded[]`
|
||||
*
|
||||
* Every base64 chunk is decoded and appended to `stream_decoded[]`.
|
||||
* The chunks passed to decode MUST be dividable by 4.
|
||||
*/
|
||||
|
||||
unsigned char encoded[] = "UGV0ZXIgUGlwZXIgcGlja2VkIGEgcGVjayBvZiBwaWNrbGVkIH"
|
||||
"BlcHBlcnMuCkEgcGVjayBvZiBwaWNrbGVkIHBlcHBlcnMgUGV0"
|
||||
"ZXIgUGlwZXIgcGlja2VkLgpJZiBQZXRlciBQaXBlciBwaWNrZW"
|
||||
"QgYSBwZWNrIG9mIHBpY2tsZWQgcGVwcGVycywKV2hlcmUncyB0"
|
||||
"aGUgcGVjayBvZiBwaWNrbGVkIHBlcHBlcnMgUGV0ZXIgUGlwZX"
|
||||
"IgcGlja2VkPw==";
|
||||
|
||||
/* required output size +2 extra bytes */
|
||||
size_t decoded_size = 196 + 2;
|
||||
|
||||
/* cppcheck-suppress unassignedVariable */
|
||||
unsigned char stream_decoded[decoded_size];
|
||||
/* the above array is used/assigned in base64_decode() using its pointer. */
|
||||
|
||||
size_t encoded_size = strlen((char *)encoded);
|
||||
int remain = encoded_size;
|
||||
int out_iter = 0;
|
||||
|
||||
int ret = BASE64_SUCCESS;
|
||||
|
||||
for (int i = 4; i < remain; (i += 4)) {
|
||||
size_t size_used = decoded_size - out_iter;
|
||||
ret = base64_decode(encoded + (encoded_size - remain), \
|
||||
i, stream_decoded + out_iter, &size_used);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
out_iter += size_used;
|
||||
remain -= i;
|
||||
}
|
||||
|
||||
size_t finish = decoded_size - out_iter;
|
||||
ret = base64_decode(encoded + (encoded_size - remain), \
|
||||
remain, stream_decoded + out_iter, &finish);
|
||||
TEST_ASSERT_EQUAL_INT(BASE64_SUCCESS, ret);
|
||||
|
||||
#if (TEST_BASE64_SHOW_OUTPUT == 1)
|
||||
out_iter += finish;
|
||||
puts("Test 07 Decoded:");
|
||||
|
||||
for (int i = 0; i < (int)out_iter; ++i) {
|
||||
printf("%c", stream_decoded[i]);
|
||||
}
|
||||
|
||||
printf("\nFrom:\n%s\n", (char *)encoded);
|
||||
#endif
|
||||
}
|
||||
|
||||
Test *tests_base64_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_base64_01_encode_string),
|
||||
new_TestFixture(test_base64_02_decode_base64),
|
||||
new_TestFixture(test_base64_03_single_character),
|
||||
new_TestFixture(test_base64_04_free_conversion),
|
||||
new_TestFixture(test_base64_05_decode_larger),
|
||||
new_TestFixture(test_base64_06_stream_encode),
|
||||
new_TestFixture(test_base64_07_stream_decode),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(base64_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&base64_tests;
|
||||
}
|
||||
|
||||
void tests_base64(void)
|
||||
{
|
||||
TESTS_RUN(tests_base64_tests());
|
||||
}
|
43
tests/unittests/tests-base64/tests-base64.h
Normal file
43
tests/unittests/tests-base64/tests-base64.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martin Landsmann
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup unittests
|
||||
* @{
|
||||
*
|
||||
* @file tests-base64.h
|
||||
* @brief Unittests for the ``base64`` module
|
||||
*
|
||||
* @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>
|
||||
*/
|
||||
#ifndef __TESTS_BASE64_H_
|
||||
#define __TESTS_BASE64_H_
|
||||
#include "embUnit/embUnit.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The entry point of this test suite.
|
||||
*/
|
||||
void tests_base64(void);
|
||||
|
||||
/**
|
||||
* @brief Generates tests for base64
|
||||
*
|
||||
* @return embUnit tests if successful, NULL if not.
|
||||
*/
|
||||
Test *tests_base64_tests(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TESTS_BASE64_H_ */
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user