1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Add base64 encode/decode.

This commit is contained in:
David Steele 2017-10-18 11:14:26 -04:00
parent 2d56de00fc
commit f4524aeaa9
14 changed files with 588 additions and 0 deletions

View File

@ -63,6 +63,10 @@
<release-item>
<p>Add C memory contexts.</p>
</release-item>
<release-item>
<p>Add base64 encode/decode.</p>
</release-item>
</release-refactor-list>
</release-core-list>

View File

@ -25,6 +25,7 @@ C includes
These includes are from the src directory. There is no Perl-specific code in them.
***********************************************************************************************************************************/
#include "common/encode.h"
#include "common/error.h"
#include "config/config.h"
#include "config/configRule.h"
@ -35,6 +36,13 @@ Helper macros
***********************************************************************************************************************************/
#include "LibC.h"
/***********************************************************************************************************************************
XSH includes
These includes define data structures that are required for the C to Perl interface but are not part of the regular C source.
***********************************************************************************************************************************/
#include "xs/common/encode.xsh"
/***********************************************************************************************************************************
Constant include
@ -58,6 +66,7 @@ INCLUDE: const-xs.inc
#
# These modules should map 1-1 with C modules in src directory.
# ----------------------------------------------------------------------------------------------------------------------------------
INCLUDE: xs/common/encode.xs
INCLUDE: xs/config/config.xs
INCLUDE: xs/config/configRule.xs
INCLUDE: xs/postgres/pageChecksum.xs

View File

@ -101,6 +101,17 @@ my $rhExport =
libCVersion
)],
},
'encode' =>
{
&BLD_EXPORTTYPE_CONSTANT => [qw(
ENCODE_TYPE_BASE64
)],
&BLD_EXPORTTYPE_SUB => [qw(
encodeToStr decodeToBin
)],
},
};
####################################################################################################################################

48
libc/xs/common/encode.xs Normal file
View File

@ -0,0 +1,48 @@
# ----------------------------------------------------------------------------------------------------------------------------------
# Binary to String Encode/Decode Perl Exports
# ----------------------------------------------------------------------------------------------------------------------------------
MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC
####################################################################################################################################
SV *
encodeToStr(encodeType, source)
int encodeType
SV *source
CODE:
RETVAL = NULL;
STRLEN sourceSize;
unsigned char *sourcePtr = (unsigned char *)SvPV(source, sourceSize);
ERROR_XS_BEGIN()
{
RETVAL = newSV(encodeToStrSize(encodeType, sourceSize));
SvPOK_only(RETVAL);
encodeToStr(encodeType, sourcePtr, sourceSize, (char *)SvPV_nolen(RETVAL));
SvCUR_set(RETVAL, encodeToStrSize(encodeType, sourceSize));
}
ERROR_XS_END();
OUTPUT:
RETVAL
####################################################################################################################################
SV *
decodeToBin(encodeType, source)
int encodeType
const char *source
CODE:
RETVAL = NULL;
ERROR_XS_BEGIN()
{
RETVAL = newSV(decodeToBinSize(encodeType, source));
SvPOK_only(RETVAL);
decodeToBin(encodeType, source, (unsigned char *)SvPV_nolen(RETVAL));
SvCUR_set(RETVAL, decodeToBinSize(encodeType, source));
}
ERROR_XS_END();
OUTPUT:
RETVAL

View File

@ -0,0 +1,7 @@
/***********************************************************************************************************************************
Binary to String Encode/Decode XS Header
***********************************************************************************************************************************/
#include "../src/common/encode.h"
// Encode types
#define ENCODE_TYPE_BASE64 ((int)encodeBase64)

102
src/common/encode.c Normal file
View File

@ -0,0 +1,102 @@
/***********************************************************************************************************************************
Binary to String Encode/Decode
***********************************************************************************************************************************/
#include <string.h>
#include "common/encode.h"
#include "common/encode/base64.h"
#include "common/error.h"
/***********************************************************************************************************************************
Macro to handle invalid encode type errors
***********************************************************************************************************************************/
#define ENCODE_TYPE_INVALID_ERROR(encodeType) \
ERROR_THROW(AssertError, "invalid encode type %d", encodeType);
/***********************************************************************************************************************************
Encode binary data to a printable string
***********************************************************************************************************************************/
void
encodeToStr(EncodeType encodeType, const unsigned char *source, int sourceSize, char *destination)
{
if (encodeType == encodeBase64)
encodeToStrBase64(source, sourceSize, destination);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
}
/***********************************************************************************************************************************
Size of the string returned by encodeToStr()
***********************************************************************************************************************************/
int
encodeToStrSize(EncodeType encodeType, int sourceSize)
{
int destinationSize = 0;
if (encodeType == encodeBase64)
destinationSize = encodeToStrSizeBase64(sourceSize);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
return destinationSize;
}
/***********************************************************************************************************************************
Decode a string to binary data
***********************************************************************************************************************************/
void
decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination)
{
if (encodeType == encodeBase64)
decodeToBinBase64(source, destination);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
}
/***********************************************************************************************************************************
Size of the binary data returned by decodeToBin()
***********************************************************************************************************************************/
int
decodeToBinSize(EncodeType encodeType, const char *source)
{
int destinationSize = 0;
if (encodeType == encodeBase64)
destinationSize = decodeToBinSizeBase64(source);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
return destinationSize;
}
/***********************************************************************************************************************************
Check that the encoded string is valid
***********************************************************************************************************************************/
bool
decodeToBinValid(EncodeType encodeType, const char *source)
{
bool valid = true;
ERROR_TRY()
{
decodeToBinValidate(encodeType, source);
}
ERROR_CATCH(FormatError)
{
valid = false;
}
return valid;
}
/***********************************************************************************************************************************
Validate the encoded string
***********************************************************************************************************************************/
void
decodeToBinValidate(EncodeType encodeType, const char *source)
{
if (encodeType == encodeBase64)
decodeToBinValidateBase64(source);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
}

26
src/common/encode.h Normal file
View File

@ -0,0 +1,26 @@
/***********************************************************************************************************************************
Binary to String Encode/Decode
These high-level functions are preferred to the low-level functions for each encoding type in the encode subdirectory.
***********************************************************************************************************************************/
#ifndef ENCODE_H
#define ENCODE_H
#include "common/type.h"
/***********************************************************************************************************************************
Encoding types
***********************************************************************************************************************************/
typedef enum {encodeBase64} EncodeType;
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
void encodeToStr(EncodeType encodeType, const unsigned char *source, int sourceSize, char *destination);
int encodeToStrSize(EncodeType encodeType, int sourceSize);
void decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination);
int decodeToBinSize(EncodeType encodeType, const char *source);
bool decodeToBinValid(EncodeType encodeType, const char *source);
void decodeToBinValidate(EncodeType encodeType, const char *source);
#endif

176
src/common/encode/base64.c Normal file
View File

@ -0,0 +1,176 @@
/***********************************************************************************************************************************
Base64 Binary to String Encode/Decode
***********************************************************************************************************************************/
#include <string.h>
#include "common/encode/base64.h"
#include "common/error.h"
/***********************************************************************************************************************************
Encode binary data to a printable string
***********************************************************************************************************************************/
static const char encodeBase64Lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void
encodeToStrBase64(const unsigned char *source, int sourceSize, char *destination)
{
int destinationIdx = 0;
// Encode the string from three bytes to four characters
for (int sourceIdx = 0; sourceIdx < sourceSize; sourceIdx += 3)
{
// First two characters are always used
destination[destinationIdx++] = encodeBase64Lookup[source[sourceIdx] >> 2];
destination[destinationIdx++] =
encodeBase64Lookup[((source[sourceIdx] & 0x03) << 4) | ((source[sourceIdx + 1] & 0xf0) >> 4)];
// Last two may be coded as = if there are less than three characters
if (sourceSize - sourceIdx > 1)
{
destination[destinationIdx++] =
encodeBase64Lookup[((source[sourceIdx + 1] & 0x0f) << 2) | ((source[sourceIdx + 2] & 0xc0) >> 6)];
}
else
destination[destinationIdx++] = 0x3d;
if (sourceSize - sourceIdx > 2)
destination[destinationIdx++] = encodeBase64Lookup[source[sourceIdx + 2] & 0x3f];
else
destination[destinationIdx++] = 0x3d;
}
// Zero-terminate the string
destination[destinationIdx] = 0;
}
/***********************************************************************************************************************************
Size of the destination param required by encodeToStrBase64() minus space for the null terminator
***********************************************************************************************************************************/
int
encodeToStrSizeBase64(int sourceSize)
{
// Calculate how many groups of three are in the source
int encodeGroupTotal = sourceSize / 3;
// Increase by one if there is a partial group
if (sourceSize % 3 != 0)
encodeGroupTotal++;
// Four characters are needed to encode each group
return encodeGroupTotal * 4;
}
/***********************************************************************************************************************************
Decode a string to binary data
***********************************************************************************************************************************/
static const int decodeBase64Lookup[256] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
void
decodeToBinBase64(const char *source, unsigned char *destination)
{
// Validate encoded string
decodeToBinValidateBase64(source);
int destinationIdx = 0;
// Decode the binary data from four characters to three bytes
for (int sourceIdx = 0; sourceIdx < strlen(source); sourceIdx += 4)
{
// Always decode the first character
destination[destinationIdx++] =
(unsigned char)(decodeBase64Lookup[(int)source[sourceIdx]] << 2 | decodeBase64Lookup[(int)source[sourceIdx + 1]] >> 4);
// Second character is optional
if (source[sourceIdx + 2] != 0x3d)
{
destination[destinationIdx++] = (unsigned char)
(decodeBase64Lookup[(int)source[sourceIdx + 1]] << 4 | decodeBase64Lookup[(int)source[sourceIdx + 2]] >> 2);
}
// Third character is optional
if (source[sourceIdx + 3] != 0x3d)
{
destination[destinationIdx++] = (unsigned char)
(((decodeBase64Lookup[(int)source[sourceIdx + 2]] << 6) & 0xc0) | decodeBase64Lookup[(int)source[sourceIdx + 3]]);
}
}
}
/***********************************************************************************************************************************
Size of the destination param required by decodeToBinBase64()
***********************************************************************************************************************************/
int
decodeToBinSizeBase64(const char *source)
{
// Validate encoded string
decodeToBinValidateBase64(source);
// Start with size calculated directly from source length
int sourceSize = strlen(source);
int destinationSize = sourceSize / 4 * 3;
// Subtract last character if it is not present
if (source[sourceSize - 1] == 0x3d)
{
destinationSize--;
// Subtract second to last character if it is not present
if (source[sourceSize - 2] == 0x3d)
destinationSize--;
}
return destinationSize;
}
/***********************************************************************************************************************************
Validate the encoded string
***********************************************************************************************************************************/
void
decodeToBinValidateBase64(const char *source)
{
// Check for the correct length
int sourceSize = strlen(source);
if (sourceSize % 4 != 0)
ERROR_THROW(FormatError, "base64 size %d is not evenly divisible by 4", sourceSize);
// Check all characters
for (int sourceIdx = 0; sourceIdx < sourceSize; sourceIdx++)
{
// Check terminators
if (source[sourceIdx] == 0x3d)
{
// Make sure they are only in the last two positions
if (sourceIdx < sourceSize - 2)
ERROR_THROW(FormatError, "base64 '=' character may only appear in last two positions");
// If second to last char is = then last char must also be
if (sourceIdx == sourceSize - 2 && source[sourceSize - 1] != 0x3d)
ERROR_THROW(FormatError, "base64 last character must be '=' if second to last is");
}
else
{
// Error on any invalid characters
if (decodeBase64Lookup[(int)source[sourceIdx]] == -1)
ERROR_THROW(FormatError, "base64 invalid character found at position %d", sourceIdx);
}
}
}

View File

@ -0,0 +1,20 @@
/***********************************************************************************************************************************
Base64 Binary to String Encode/Decode
The high-level functions in encode.c should be used in preference to these low-level functions.
***********************************************************************************************************************************/
#ifndef BASE64_H
#define BASE64_H
#include "common/type.h"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
void encodeToStrBase64(const unsigned char *source, int sourceSize, char *destination);
int encodeToStrSizeBase64(int sourceSize);
void decodeToBinBase64(const char *source, unsigned char *destination);
int decodeToBinSizeBase64(const char *source);
void decodeToBinValidateBase64(const char *source);
#endif

View File

@ -30,6 +30,7 @@ Define errors
***********************************************************************************************************************************/
ERROR_DEFINE(ERROR_CODE_MIN, AssertError, RuntimeError);
ERROR_DEFINE(ERROR_CODE_MIN + 04, FormatError, RuntimeError);
ERROR_DEFINE(ERROR_CODE_MIN + 69, MemoryError, RuntimeError);
ERROR_DEFINE(ERROR_CODE_MAX, RuntimeError, RuntimeError);

View File

@ -16,6 +16,7 @@ typedef struct ErrorType ErrorType;
// Error types
ERROR_DECLARE(AssertError);
ERROR_DECLARE(FormatError);
ERROR_DECLARE(MemoryError);
ERROR_DECLARE(RuntimeError);

View File

@ -128,6 +128,22 @@ my $oTestDef =
'common/memContext' => TESTDEF_COVERAGE_FULL,
},
},
{
&TESTDEF_NAME => 'encode',
&TESTDEF_TOTAL => 1,
&TESTDEF_C => true,
&TESTDEF_COVERAGE =>
{
'common/encode' => TESTDEF_COVERAGE_FULL,
'common/encode/base64' => TESTDEF_COVERAGE_FULL,
},
},
{
&TESTDEF_NAME => 'encode-perl',
&TESTDEF_TOTAL => 1,
&TESTDEF_CLIB => true,
},
{
&TESTDEF_NAME => 'http-client',
&TESTDEF_TOTAL => 2,

View File

@ -0,0 +1,62 @@
####################################################################################################################################
# Test Binary to String Encode/Decode
####################################################################################################################################
package pgBackRestTest::Module::Common::CommonEncodePerlTest;
use parent 'pgBackRestTest::Common::RunTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::LibC qw(:encode);
use pgBackRest::Version;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::RunTest;
####################################################################################################################################
# run
####################################################################################################################################
sub run
{
my $self = shift;
################################################################################################################################
if ($self->begin("encodeToStrBase64() and decodeToBinBase64()"))
{
my $strData = 'string_to_encode';
my $strEncodedData = 'c3RyaW5nX3RvX2VuY29kZQ==';
$self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $strData)}, $strEncodedData, 'encode string');
$self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $strEncodedData)}, $strData, 'decode string');
#---------------------------------------------------------------------------------------------------------------------------
my $tData =
pack('C', 1) . pack('C', 2) . pack('C', 3) . pack('C', 4) . pack('C', 5) . pack('C', 4) . pack('C', 3) . pack('C', 2);
my $tEncodedData = 'AQIDBAUEAwI=';
$self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $tData)}, $tEncodedData, 'encode binary');
$self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $tEncodedData)}, $tData, 'decode binary');
#---------------------------------------------------------------------------------------------------------------------------
$tData .= pack('C', 1);
$tEncodedData = 'AQIDBAUEAwIB';
$self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $tData)}, $tEncodedData, 'encode binary');
$self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $tEncodedData)}, $tData, 'decode binary');
#---------------------------------------------------------------------------------------------------------------------------
$self->testException(sub {encodeToStr(-1, '')}, ERROR_ASSERT, 'invalid encode type -1');
$self->testException(
sub {decodeToBin(ENCODE_TYPE_BASE64, "XX")}, ERROR_FORMAT, 'base64 size 2 is not evenly divisible by 4');
}
}
1;

View File

@ -0,0 +1,105 @@
/***********************************************************************************************************************************
Test Binary to String Encode/Decode
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void testRun()
{
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("base64"))
{
char *source = "string_to_encode\r\n";
unsigned char destination[256];
encodeToStr(encodeBase64, source, 1, destination);
TEST_RESULT_STR(destination, "c3==", "1 character encode");
TEST_RESULT_INT(encodeToStrSize(encodeBase64, 1), strlen(destination), "check size");
encodeToStr(encodeBase64, source, 2, destination);
TEST_RESULT_STR(destination, "c3R=", "2 character encode");
TEST_RESULT_INT(encodeToStrSize(encodeBase64, 2), strlen(destination), "check size");
encodeToStr(encodeBase64, source, 3, destination);
TEST_RESULT_STR(destination, "c3Ry", "3 character encode");
TEST_RESULT_INT(encodeToStrSize(encodeBase64, 3), strlen(destination), "check size");
encodeToStr(encodeBase64, source, strlen(source) - 2, destination);
TEST_RESULT_STR(destination, "c3RyaW5nX3RvX2VuY29kZQ==", "encode full string");
TEST_RESULT_INT(encodeToStrSize(encodeBase64, strlen(source) - 2), strlen(destination), "check size");
encodeToStr(encodeBase64, source, strlen(source), destination);
TEST_RESULT_STR(destination, "c3RyaW5nX3RvX2VuY29kZQ0K", "encode full string with \\r\\n");
TEST_RESULT_INT(encodeToStrSize(encodeBase64, strlen(source)), strlen(destination), "check size");
encodeToStr(encodeBase64, source, strlen(source) + 1, destination);
TEST_RESULT_STR(destination, "c3RyaW5nX3RvX2VuY29kZQ0KAG==", "encode full string with \\r\\n and null");
TEST_RESULT_INT(encodeToStrSize(encodeBase64, strlen(source) + 1), strlen(destination), "check size");
TEST_ERROR(encodeToStr(999, source, strlen(source), destination), AssertError, "invalid encode type 999");
TEST_ERROR(encodeToStrSize(999, strlen(source)), AssertError, "invalid encode type 999");
// -------------------------------------------------------------------------------------------------------------------------
memset(destination, 0xFF, sizeof(destination));
char *decode = "c3RyaW5nX3RvX2VuY29kZQ0KAG==";
decodeToBin(encodeBase64, decode, destination);
TEST_RESULT_STR(destination, source, "full string with \\r\\n and null decode");
TEST_RESULT_INT(destination[strlen(source) + 1], 0xFF, "check for overrun");
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), strlen(source) + 1, "check size");
memset(destination, 0xFF, sizeof(destination));
decode = "c3RyaW5nX3RvX2VuY29kZQ0K";
decodeToBin(encodeBase64, decode, destination);
TEST_RESULT_INT(memcmp(destination, source, strlen(source)), 0, "full string with \\r\\n decode");
TEST_RESULT_INT(destination[strlen(source)], 0xFF, "check for overrun");
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), strlen(source), "check size");
memset(destination, 0xFF, sizeof(destination));
decode = "c3RyaW5nX3RvX2VuY29kZQ==";
decodeToBin(encodeBase64, decode, destination);
TEST_RESULT_INT(memcmp(destination, source, strlen(source) - 2), 0, "full string decode");
TEST_RESULT_INT(destination[strlen(source) - 2], 0xFF, "check for overrun");
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), strlen(source) - 2, "check size");
memset(destination, 0xFF, sizeof(destination));
decode = "c3Ry";
decodeToBin(encodeBase64, decode, destination);
TEST_RESULT_INT(memcmp(destination, source, 3), 0, "3 character decode");
TEST_RESULT_INT(destination[3], 0xFF, "check for overrun");
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), 3, "check size");
memset(destination, 0xFF, sizeof(destination));
decode = "c3R=";
decodeToBin(encodeBase64, decode, destination);
TEST_RESULT_INT(memcmp(destination, source, 2), 0, "2 character decode");
TEST_RESULT_INT(destination[2], 0xFF, "check for overrun");
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), 2, "check size");
memset(destination, 0xFF, sizeof(destination));
decode = "c3==";
decodeToBin(encodeBase64, decode, destination);
TEST_RESULT_INT(memcmp(destination, source, 1), 0, "1 character decode");
TEST_RESULT_INT(destination[1], 0xFF, "check for overrun");
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), 1, "check size");
TEST_ERROR(decodeToBin(-1, decode, destination), AssertError, "invalid encode type -1");
TEST_ERROR(decodeToBinSize(-1, decode), AssertError, "invalid encode type -1");
TEST_ERROR(decodeToBin(encodeBase64, "cc$=", destination), FormatError, "base64 invalid character found at position 2");
// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(decodeToBinValidate(encodeBase64, "c3"), FormatError, "base64 size 2 is not evenly divisible by 4");
TEST_ERROR(
decodeToBinValidate(encodeBase64, "c==="), FormatError, "base64 '=' character may only appear in last two positions");
TEST_ERROR(
decodeToBinValidate(encodeBase64, "cc=c"), FormatError, "base64 last character must be '=' if second to last is");
TEST_ERROR(decodeToBinValidate(9999, "cc=c"), AssertError, "invalid encode type 9999");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(decodeToBinValid(encodeBase64, "CCCCCCCCCCC"), false, "base64 string not valid");
TEST_RESULT_BOOL(decodeToBinValid(encodeBase64, "CCCCCCCCCCCC"), true, "base64 string valid");
TEST_ERROR(decodeToBinValid(-999, "CCCCCCCCCCCC"), AssertError, "invalid encode type -999");
}
}