PIKApp/libpikawidgets/test-eevl.c

197 lines
5.6 KiB
C

/* LIBPIKA - The PIKA Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* test-eevl.c
* Copyright (C) 2008 Fredrik Alstromer <roe@excu.se>
* Copyright (C) 2008 Martin Nordholts <martinn@svn.gnome.org>
*
* 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 3 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
* Library 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, see
* <https://www.gnu.org/licenses/>.
*/
/* A small regression test case for the evaluator */
#include "config.h"
#include <string.h>
#include <glib-object.h>
#include "libpikamath/pikamath.h"
#include "pikaeevl.h"
typedef struct
{
const gchar *string;
PikaEevlQuantity result;
gboolean should_succeed;
} TestCase;
static gboolean
test_units (const gchar *ident,
PikaEevlQuantity *factor,
gdouble *offset,
gpointer data)
{
gboolean resolved = FALSE;
gboolean default_unit = (ident == NULL);
*offset = 0.0;
if (default_unit ||
(ident && strcmp ("in", ident) == 0))
{
factor->dimension = 1;
factor->value = 1.;
resolved = TRUE;
}
else if (ident && strcmp ("mm", ident) == 0)
{
factor->dimension = 1;
factor->value = 25.4;
resolved = TRUE;
}
return resolved;
}
int
main(void)
{
gint i;
gint failed = 0;
gint succeeded = 0;
TestCase cases[] =
{
/* "Default" test case */
{ "2in + 3in", { 2 + 3, 1}, TRUE },
/* Whitespace variations */
{ "2in+3in", { 2 + 3, 1}, TRUE },
{ " 2in + 3in", { 2 + 3, 1}, TRUE },
{ "2in + 3in ", { 2 + 3, 1}, TRUE },
{ "2 in + 3 in", { 2 + 3, 1}, TRUE },
{ " 2 in + 3 in ", { 2 + 3, 1}, TRUE },
/* Make sure the default unit is applied as it should */
{ "2 + 3in", { 2 + 3, 1 }, TRUE },
{ "3", { 3, 1 }, TRUE },
/* Somewhat complicated input */
{ "(2 + 3)in", { 2 + 3, 1}, TRUE },
// { "2 / 3 in", { 2 / 3., 1}, TRUE },
{ "(2 + 2/3)in", { 2 + 2 / 3., 1}, TRUE },
{ "1/2 + 1/2", { 1, 1}, TRUE },
{ "2 ^ 3 ^ 4", { pow (2, pow (3, 4)), 1}, TRUE },
/* Mixing of units */
{ "2mm + 3in", { 2 / 25.4 + 3, 1}, TRUE },
/* 'odd' behavior */
{ "2 ++ 1", { 3, 1}, TRUE },
{ "2 +- 1", { 1, 1}, TRUE },
{ "2 -- 1", { 3, 1}, TRUE },
/* End of test cases */
{ NULL, { 0, 0 }, TRUE }
};
g_print ("Testing Eevl Eva, the Evaluator\n\n");
for (i = 0; cases[i].string; i++)
{
const gchar *test = cases[i].string;
PikaEevlOptions options = PIKA_EEVL_OPTIONS_INIT;
PikaEevlQuantity should = cases[i].result;
PikaEevlQuantity result = { 0, -1 };
gboolean should_succeed = cases[i].should_succeed;
GError *error = NULL;
const gchar *error_pos = 0;
options.unit_resolver_proc = test_units;
pika_eevl_evaluate (test,
&options,
&result,
&error_pos,
&error);
g_print ("%s = %lg (%d): ", test, result.value, result.dimension);
if (error || error_pos)
{
if (should_succeed)
{
failed++;
g_print ("evaluation failed ");
if (error)
{
g_print ("with: %s, ", error->message);
}
else
{
g_print ("without reason, ");
}
if (error_pos)
{
if (*error_pos) g_print ("'%s'.", error_pos);
else g_print ("at end of input.");
}
else
{
g_print ("but didn't say where.");
}
g_print ("\n");
}
else
{
g_print ("OK (failure test case)\n");
succeeded++;
}
}
else if (!should_succeed)
{
g_print ("evaluation should've failed, but didn't.\n");
failed++;
}
else if (should.value != result.value || should.dimension != result.dimension)
{
g_print ("results don't match, should be: %lg (%d)\n",
should.value, should.dimension);
failed++;
}
else
{
g_print ("OK\n");
succeeded++;
}
}
g_print ("\n");
if (!failed)
g_print ("All OK. ");
else
g_print ("Test failed! ");
g_print ("(%d/%d) %lg%%\n\n", succeeded, succeeded+failed,
100*succeeded/(gdouble)(succeeded+failed));
return failed;
}