aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/taler_amount_lib.h2
-rw-r--r--src/include/taler_crypto_lib.h1
-rw-r--r--src/include/taler_json_lib.h2
-rw-r--r--src/util/Makefile.am38
-rw-r--r--src/util/amount.c66
-rw-r--r--src/util/test_amount.c190
-rw-r--r--src/util/test_crypto.c38
-rw-r--r--src/util/test_json.c38
-rw-r--r--src/util/test_wireformats.c (renamed from src/util/test_json_validations.c)0
9 files changed, 338 insertions, 37 deletions
diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h
index 82952f0b2..54eeda844 100644
--- a/src/include/taler_amount_lib.h
+++ b/src/include/taler_amount_lib.h
@@ -100,7 +100,7 @@ struct TALER_Amount
/**
- * Parse denomination description, in the format "T : V : F".
+ * Parse denomination description, in the format "T:V.F".
*
* @param str denomination description
* @param denom denomination to write the result to
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index d7d12354a..3c8aee557 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -489,5 +489,6 @@ TALER_refresh_link_encrypted_decode (const char *buf,
size_t buf_len);
+/* FIXME: should also have _encode API... */
#endif
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index 9410d5088..7e0955688 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 2a5cdefef..804ff85a2 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -28,14 +28,40 @@ libtalerutil_la_LDFLAGS = \
-export-dynamic -no-undefined
TESTS = \
- test-json-validations
+ test_amount \
+ test_crypto \
+ test_json \
+ test_wireformats
-check_PROGRAMS=\
- test-json-validations
+check_PROGRAMS= \
+ test_amount \
+ test_crypto \
+ test_json \
+ test_wireformats
-test_json_validations_SOURCES = \
- test_json_validations.c
-test_json_validations_LDADD = \
+
+test_amount_SOURCES = \
+ test_amount.c
+test_amount_LDADD = \
+ -lgnunetutil \
+ libtalerutil.la
+
+test_crypto_SOURCES = \
+ test_crypto.c
+test_crypto_LDADD = \
+ -lgnunetutil \
+ libtalerutil.la
+
+test_json_SOURCES = \
+ test_json.c
+test_json_LDADD = \
+ -lgnunetutil \
+ -ljansson \
+ libtalerutil.la
+
+test_wireformats_SOURCES = \
+ test_wireformats.c
+test_wireformats_LDADD = \
-lgnunetutil \
-ljansson \
libtalerutil.la
diff --git a/src/util/amount.c b/src/util/amount.c
index fcf12692f..74ffcd36f 100644
--- a/src/util/amount.c
+++ b/src/util/amount.c
@@ -19,12 +19,7 @@
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
* @author Florian Dold
* @author Benedikt Mueller
- *
- * TODO:
- * - the way this library currently deals with underflow/overflow
- * is insufficient; just going for UINT32_MAX on overflow
- * will not do; similar issues for incompatible currencies;
- * we need some more explicit logic to say 'bogus value',
+ * @author Christian Grothoff
*/
#include "platform.h"
#include "taler_util.h"
@@ -91,14 +86,14 @@ TALER_string_to_amount (const char *str,
{
return GNUNET_OK;
}
- if ( (str[i] < '0') || (str[i] > '9') )
+ if ( (value[i] < '0') || (value[i] > '9') )
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Invalid character `%c'\n",
- str[i]);
+ value[i]);
goto fail;
}
- n = str[i] - '0';
+ n = value[i] - '0';
if (denom->value * 10 + n < denom->value)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -113,29 +108,29 @@ TALER_string_to_amount (const char *str,
i++;
/* parse fraction */
- if ('\0' == str[i])
+ if ('\0' == value[i])
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Null after dot");
+ "Null after dot\n");
goto fail;
}
b = TALER_AMOUNT_FRAC_BASE / 10;
- while ('\0' != str[i])
+ while ('\0' != value[i])
{
if (0 == b)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Fractional value too small (only %u digits supported)",
+ "Fractional value too small (only %u digits supported)\n",
(unsigned int) TALER_AMOUNT_FRAC_LEN);
goto fail;
}
- if ( (str[i] < '0') || (str[i] > '9') )
+ if ( (value[i] < '0') || (value[i] > '9') )
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Error after comma");
+ "Error after dot\n");
goto fail;
}
- n = str[i] - '0';
+ n = value[i] - '0';
denom->fraction += n * b;
b /= 10;
i++;
@@ -258,8 +253,8 @@ TALER_amount_cmp_currency (const struct TALER_Amount *a1,
if ( (GNUNET_NO == test_valid (a1)) ||
(GNUNET_NO == test_valid (a2)) )
return GNUNET_SYSERR;
- if (0 == strcmp (a1->currency,
- a2->currency))
+ if (0 == strcasecmp (a1->currency,
+ a2->currency))
return GNUNET_YES;
return GNUNET_NO;
}
@@ -286,8 +281,10 @@ TALER_amount_cmp (const struct TALER_Amount *a1,
TALER_amount_cmp_currency (a1, a2));
n1 = *a1;
n2 = *a2;
- TALER_amount_normalize (&n1);
- TALER_amount_normalize (&n2);
+ GNUNET_assert (GNUNET_SYSERR !=
+ TALER_amount_normalize (&n1));
+ GNUNET_assert (GNUNET_SYSERR !=
+ TALER_amount_normalize (&n2));
if (n1.value == n2.value)
{
if (n1.fraction < n2.fraction)
@@ -329,8 +326,12 @@ TALER_amount_subtract (struct TALER_Amount *diff,
}
n1 = *a1;
n2 = *a2;
- TALER_amount_normalize (&n1);
- TALER_amount_normalize (&n2);
+ if ( (GNUNET_SYSERR == TALER_amount_normalize (&n1)) ||
+ (GNUNET_SYSERR == TALER_amount_normalize (&n2)) )
+ {
+ invalidate (diff);
+ return GNUNET_SYSERR;
+ }
if (n1.fraction < n2.fraction)
{
@@ -377,6 +378,7 @@ TALER_amount_add (struct TALER_Amount *sum,
{
struct TALER_Amount n1;
struct TALER_Amount n2;
+ struct TALER_Amount res;
if (GNUNET_YES !=
TALER_amount_cmp_currency (a1, a2))
@@ -386,27 +388,32 @@ TALER_amount_add (struct TALER_Amount *sum,
}
n1 = *a1;
n2 = *a2;
- TALER_amount_normalize (&n1);
- TALER_amount_normalize (&n2);
+ if ( (GNUNET_SYSERR == TALER_amount_normalize (&n1)) ||
+ (GNUNET_SYSERR == TALER_amount_normalize (&n2)) )
+ {
+ invalidate (sum);
+ return GNUNET_SYSERR;
+ }
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (a1->currency,
- sum));
- sum->value = n1.value + n2.value;
- if (sum->value < n1.value)
+ &res));
+ res.value = n1.value + n2.value;
+ if (res.value < n1.value)
{
/* integer overflow */
invalidate (sum);
return GNUNET_SYSERR;
}
- sum->fraction = n1.fraction + n2.fraction;
+ res.fraction = n1.fraction + n2.fraction;
if (GNUNET_SYSERR ==
- TALER_amount_normalize (sum))
+ TALER_amount_normalize (&res))
{
/* integer overflow via carry from fraction */
invalidate (sum);
return GNUNET_SYSERR;
}
+ *sum = res;
return GNUNET_OK;
}
@@ -438,6 +445,7 @@ TALER_amount_normalize (struct TALER_Amount *amount)
{
/* failed to normalize, adding up fractions caused
main value to overflow! */
+ invalidate (amount);
return GNUNET_SYSERR;
}
return ret;
diff --git a/src/util/test_amount.c b/src/util/test_amount.c
new file mode 100644
index 000000000..4741bcf36
--- /dev/null
+++ b/src/util/test_amount.c
@@ -0,0 +1,190 @@
+/*
+ This file is part of TALER
+ (C) 2015 Christian Grothoff (and other contributing authors)
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file util/test_amount.c
+ * @brief Tests for amount logic
+ * @author Christian Grothoff <christian@grothoff.org>
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_amount_lib.h"
+
+
+int
+main(int argc,
+ const char *const argv[])
+{
+ struct TALER_Amount a1;
+ struct TALER_Amount a2;
+ struct TALER_Amount a3;
+ char *c;
+
+ GNUNET_log_setup ("test-amout",
+ "WARNING",
+ NULL);
+ /* test invalid conversions */
+ GNUNET_log_skip (6, GNUNET_NO);
+ /* non-numeric */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_string_to_amount ("EUR:4a",
+ &a1));
+ /* non-numeric */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_string_to_amount ("EUR:4.4a",
+ &a1));
+ /* non-numeric */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_string_to_amount ("EUR:4.a4",
+ &a1));
+ /* no currency */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_string_to_amount (":4.a4",
+ &a1));
+ /* precision too high */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_string_to_amount ("EUR:4.1234567",
+ &a1));
+ /* value too big */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_string_to_amount ("EUR:1234567890123456789012345678901234567890123456789012345678901234567890",
+ &a1));
+ GNUNET_log_skip (0, GNUNET_YES);
+
+ /* test conversion without fraction */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:4",
+ &a1));
+ GNUNET_assert (0 == strcasecmp ("EUR",
+ a1.currency));
+ GNUNET_assert (4 == a1.value);
+ GNUNET_assert (0 == a1.fraction);
+
+ /* test conversion with leading space and with fraction */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (" eur:4.12",
+ &a2));
+ GNUNET_assert (0 == strcasecmp ("eur",
+ a2.currency));
+ GNUNET_assert (4 == a2.value);
+ GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 100 * 12 == a2.fraction);
+
+ /* test use of local currency */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (" *LOCAL:4444.1000",
+ &a3));
+ GNUNET_assert (0 == strcasecmp ("*LOCAL",
+ a3.currency));
+ GNUNET_assert (4444 == a3.value);
+ GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 10 == a3.fraction);
+
+ /* test CMP with equal and unequal currencies */
+ GNUNET_assert (GNUNET_NO ==
+ TALER_amount_cmp_currency (&a1,
+ &a3));
+ GNUNET_assert (GNUNET_YES ==
+ TALER_amount_cmp_currency (&a1,
+ &a2));
+
+ /* test subtraction failure (currency missmatch) */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_amount_subtract (&a3,
+ &a3,
+ &a2));
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_amount_normalize (&a3));
+
+ /* test subtraction failure (negative result) */
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_amount_subtract (&a3,
+ &a1,
+ &a2));
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_amount_normalize (&a3));
+
+ /* test subtraction success cases */
+ GNUNET_assert (GNUNET_YES ==
+ TALER_amount_subtract (&a3,
+ &a2,
+ &a1));
+ GNUNET_assert (GNUNET_NO ==
+ TALER_amount_subtract (&a3,
+ &a1,
+ &a1));
+ GNUNET_assert (0 == a3.value);
+ GNUNET_assert (0 == a3.fraction);
+ GNUNET_assert (GNUNET_NO ==
+ TALER_amount_normalize (&a3));
+
+ /* test addition success */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_add (&a3,
+ &a3,
+ &a2));
+ GNUNET_assert (GNUNET_NO ==
+ TALER_amount_normalize (&a3));
+
+ /* test normalization */
+ a3.fraction = 2 * TALER_AMOUNT_FRAC_BASE;
+ a3.value = 4;
+ GNUNET_assert (GNUNET_YES ==
+ TALER_amount_normalize (&a3));
+
+ /* test conversion to string */
+ c = TALER_amount_to_string (&a3);
+ GNUNET_assert (0 == strcmp ("EUR:6",
+ c));
+ GNUNET_free (c);
+
+ /* test normalization with fraction overflow */
+ a3.fraction = 2 * TALER_AMOUNT_FRAC_BASE + 1;
+ a3.value = 4;
+ GNUNET_assert (GNUNET_YES ==
+ TALER_amount_normalize (&a3));
+ c = TALER_amount_to_string (&a3);
+ GNUNET_assert (0 == strcmp ("EUR:6.000001",
+ c));
+ GNUNET_free (c);
+
+ /* test normalization with overflow */
+ a3.fraction = 2 * TALER_AMOUNT_FRAC_BASE + 1;
+ a3.value = UINT64_MAX - 1;
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_amount_normalize (&a3));
+ c = TALER_amount_to_string (&a3);
+ GNUNET_assert (NULL == c);
+
+ /* test addition with overflow */
+ a1.fraction = TALER_AMOUNT_FRAC_BASE - 1;
+ a1.value = UINT64_MAX - 5;
+ a2.fraction = 2;
+ a2.value = 5;
+ GNUNET_assert (GNUNET_SYSERR ==
+ TALER_amount_add (&a3, &a1, &a2));
+
+ /* test addition with underflow on fraction */
+ a1.fraction = 1;
+ a1.value = UINT64_MAX;
+ a2.fraction = 2;
+ a2.value = 0;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_subtract (&a3, &a1, &a2));
+ GNUNET_assert (UINT64_MAX - 1 == a3.value);
+ GNUNET_assert (TALER_AMOUNT_FRAC_BASE - 1 == a3.fraction);
+ return 0;
+}
+
+/* end of test_amount.c */
diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c
new file mode 100644
index 000000000..a375bcfbb
--- /dev/null
+++ b/src/util/test_crypto.c
@@ -0,0 +1,38 @@
+/*
+ This file is part of TALER
+ (C) 2015 Christian Grothoff (and other contributing authors)
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file util/test_crypto.c
+ * @brief Tests for Taler-specific crypto logic
+ * @author Christian Grothoff <christian@grothoff.org>
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_crypto_lib.h"
+
+
+int
+main(int argc,
+ const char *const argv[])
+{
+ GNUNET_log_setup ("test-crypto",
+ "WARNING",
+ NULL);
+ /* FIXME: implement test... */
+ return 0;
+}
+
+/* end of test_crypto.c */
diff --git a/src/util/test_json.c b/src/util/test_json.c
new file mode 100644
index 000000000..9eb72fb8c
--- /dev/null
+++ b/src/util/test_json.c
@@ -0,0 +1,38 @@
+/*
+ This file is part of TALER
+ (C) 2015 Christian Grothoff (and other contributing authors)
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file util/test_json.c
+ * @brief Tests for Taler-specific crypto logic
+ * @author Christian Grothoff <christian@grothoff.org>
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_json_lib.h"
+
+
+int
+main(int argc,
+ const char *const argv[])
+{
+ GNUNET_log_setup ("test-json",
+ "WARNING",
+ NULL);
+ /* FIXME: implement test... */
+ return 0;
+}
+
+/* end of test_json.c */
diff --git a/src/util/test_json_validations.c b/src/util/test_wireformats.c
index 26ec4b79f..26ec4b79f 100644
--- a/src/util/test_json_validations.c
+++ b/src/util/test_wireformats.c