/*
* Copyright (c) 2009-2012 Zmanda, Inc. All Rights Reserved.
* Copyright (c) 2013-2016 Carbonite, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* Contact information: Carbonite Inc., 756 N Pastoria Ave
* Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
*/
#include "amanda.h"
#include "amutil.h"
#include "testutils.h"
#include "simpleprng.h"
static gboolean test_encode(void);
static gboolean test_decode(void);
static gboolean test_roundtrip(void);
static gboolean test_roundtrip_rand(void);
typedef struct {char *in; char *out;} enc_vec;
static gboolean
test_encode(void)
{
static const enc_vec test_strs[] = {
{"hi", "hi"},
{"hi!", "hi%21"},
{"%", "%25"},
{"*", "%2a"},
{"\n", "%0a"},
{"\nhi\n", "%0ahi%0a"}
};
static const int num = G_N_ELEMENTS(test_strs);
int i;
gboolean ret;
char *tmp;
ret = TRUE;
for (i = 0; i < num; i++) {
tmp = hexencode_string(test_strs[i].in);
if (!tmp || !g_str_equal(test_strs[i].out, tmp)) {
ret = FALSE;
tu_dbg("encode failure:\n")
tu_dbg("input: \"%s\"\n", test_strs[i].in);
tu_dbg("output: \"%s\"\n", tmp? tmp : "(null)");
tu_dbg("expected: \"%s\"\n", test_strs[i].out);
}
g_free(tmp);
}
return ret;
}
typedef struct {char *in; char *out; gboolean expect_err; } dec_vec;
static gboolean
test_decode(void)
{
static const dec_vec test_strs[] = {
{"hi", "hi", FALSE},
{"hi%21", "hi!", FALSE},
{"%25", "%", FALSE},
{"%2a", "*", FALSE},
{"%2A", "*", FALSE},
{"%0a", "\n", FALSE},
{"%0A", "\n", FALSE},
{"%0ahi%0a", "\nhi\n", FALSE},
{"%", "", TRUE},
{"%2", "", TRUE},
{"h%", "", TRUE},
{"%0h", "", TRUE},
{"%h0", "", TRUE},
{"%00", "", TRUE}
};
static const int num = G_N_ELEMENTS(test_strs);
int i;
gboolean ret;
char *tmp;
GError *err = NULL;
ret = TRUE;
for (i = 0; i < num; i++) {
tmp = hexdecode_string(test_strs[i].in, &err);
if (!tmp || !g_str_equal(test_strs[i].out, tmp) ||
(!!err != test_strs[i].expect_err)) {
ret = FALSE;
tu_dbg("decode failure:\n")
tu_dbg("input: \"%s\"\n", test_strs[i].in);
tu_dbg("output: \"%s\"\n", tmp? tmp : "(null)");
tu_dbg("expected: \"%s\"\n", test_strs[i].out);
tu_dbg("error msg: %s\n", err? err->message : "(none)");
}
g_clear_error(&err);
g_free(tmp);
}
return ret;
}
typedef char* round_vec;
static gboolean
test_roundtrip(void)
{
static const round_vec test_strs[] = {
"hi",
"hi!",
"hi%21",
"%",
"*",
"\n",
"h%"
};
static const int num = G_N_ELEMENTS(test_strs);
int i;
gboolean ret;
char *tmp_enc = NULL, *tmp_dec = NULL;
GError *err = NULL;
ret = TRUE;
for (i = 0; i < num; i++) {
tmp_enc = hexencode_string(test_strs[i]);
tmp_dec = tmp_enc? hexdecode_string(tmp_enc, &err) : NULL;
if (!tmp_enc || !tmp_dec || !g_str_equal(test_strs[i], tmp_dec) || err) {
ret = FALSE;
tu_dbg("roundtrip failure:\n")
tu_dbg("input: \"%s\"\n", test_strs[i]);
tu_dbg("enc output: \"%s\"\n", tmp_enc? tmp_enc : "(null)");
tu_dbg("dec output: \"%s\"\n", tmp_dec? tmp_dec : "(null)");
tu_dbg("error msg: %s\n", err? err->message : "(none)");
}
g_clear_error(&err);
amfree(tmp_enc);
amfree(tmp_dec);
}
return ret;
}
static gboolean
test_roundtrip_rand(void)
{
int i;
gboolean ret;
simpleprng_state_t state;
char *in, *tmp_enc = NULL, *tmp_dec = NULL;
size_t size;
GError *err = NULL;
simpleprng_seed(&state, 0xface);
ret = TRUE;
for (i = 0; i < 100; i++) {
size = simpleprng_rand_byte(&state);
in = g_malloc0(size+1);
simpleprng_fill_buffer(&state, in, size);
tmp_enc = hexencode_string(in);
tmp_dec = tmp_enc? hexdecode_string(tmp_enc, &err) : NULL;
if (!tmp_enc || !tmp_dec || !g_str_equal(in, tmp_dec) || err) {
ret = FALSE;
tu_dbg("roundtrip failure:\n")
tu_dbg("input: \"%s\"\n", in);
tu_dbg("enc output: \"%s\"\n", tmp_enc? tmp_enc : "(null)");
tu_dbg("dec output: \"%s\"\n", tmp_dec? tmp_dec : "(null)");
tu_dbg("error msg: %s\n", err? err->message : "(none)");
}
g_clear_error(&err);
amfree(tmp_enc);
amfree(tmp_dec);
g_free(in);
}
return ret;
}
int
main(int argc, char **argv)
{
static TestUtilsTest tests[] = {
TU_TEST(test_encode, 90),
TU_TEST(test_decode, 90),
TU_TEST(test_roundtrip, 90),
TU_TEST(test_roundtrip_rand, 90),
TU_END()
};
glib_init();
return testutils_run_tests(argc, argv, tests);
}