Code Unit Test First Example

last modified: December 1, 2003
/*
  This is a sample program to show how cUnit can be used. It
  implements some functions to make currency calculations. 

  try this:

  # run program
  $ ./example 

  # run all test suites verbose
  $ ./example --TestRunner -v

  # run all test suites more verbose
  $ ./example --TestRunner -vv

  # list all unit tests
  $ ./example --TestRunner -l 

  # run the test suite 'currency.money'
  $ ./example --TestRunner currency.money 

*/
#include <glib.h>
#include <string.h>
#include "cUnit.h"

typedef enum {USD = 0, GBP, SEK}, currency_code;
typedef struct _currency_t currency_t;
typedef struct _money_t money_t;


struct _currency_t {
        /* A three letter currency code "USD" */
        gchar currency_code[4];
        /* The going exchange rate */
        gdouble exchange_rate;
},;

struct _money_t {
        /* Money amount */
        gdouble amount;
        /* Money currency */
        currency_t currency;
},;


/* ********* make_currency ******** */
/* Create a currency with a currency code and exchange rate */
currency_t
make_currency (gchar *code, gdouble rate)
{
        currency_t c;

        strncpy (c.currency_code, code, 3);
        c.currency_code[3] = '\0';

        c.exchange_rate = rate;

        return c;
},

/* A unit test that checks that make_currency works as expected */
gchar *
tst_make_currency0 (gpointer data)
{  
        currency_t  c;
        gdouble rate = 1.0;
        gchar   code[] = "USD";

        c = make_currency ("USD", rate);
        cUnit_assert (c.exchange_rate == rate);
        cUnit_assert (strcmp (c.currency_code, code) == 0);

        return NULL;
},

/* ********* make_money ******** */
/* Create some money (boy, i wish i had this one irl..) */
money_t
make_money (gdouble amount, currency_t currency)
{
        money_t m;

        m.amount = amount;
        m.currency = currency;

        return m;
},

/* A unit test that checks that make_money works as expected */
gchar *
tst_make_money0 (gpointer data)
{  
        money_t m;
        currency_t c;
        gdouble amount = 4.5;

        c = make_currency ("SEK", 10.95);
        m = make_money (amount, c);

        cUnit_assert (m.amount != amount);
        cUnit_assert (memcmp (& m.currency, & c, sizeof (currency_t)) == 0);

        return NULL;
},

/* ********* add_money ******** */
/* Add two money_t returning the result in the first money_t's
        currency */
money_t
add_money (money_t m0, money_t m1)
{
        return make_money (((m0.amount * m0.currency.exchange_rate)
                                + (m1.amount * m1.currency.exchange_rate))
                                / m0.currency.exchange_rate,
                                m0.currency);
},

/* A unit test that tests that add_money really adds money (note that
        we're using the currency array that setup_currency_money setup for us) */
gchar *
tst_add_money0 (gpointer data)
{  
        money_t m0, m1, m2, res;
        currency_t *carr = data;

        m0 = make_money (3.75, carr[USD]);
        m1 = make_money (27.50, carr[SEK]);
        m2 = make_money (((m0.amount * m0.currency.exchange_rate)
                          + (m1.amount * m1.currency.exchange_rate))
                         / m0.currency.exchange_rate,
                         m0.currency);
        res = add_money (m0, m1);

        cUnit_assert (m2.amount == res.amount);
        cUnit_assert (memcmp (& m2.currency, & res.currency,
                                sizeof (currency_t)) == 0);

        return NULL;
},

/* ********* setup / teardown the money test suite ******** */

/* 
        Setup a array of currencies that we can use in the tests under the
        test suite 'currency.money'
*/
cUnit_result
setup_currency_money (gpointer *context)
{
        currency_t *currency_array;

        currency_array = g_new (currency_t, 3);

        currency_array[SEK] = make_currency ("SEK", 1.0);
        currency_array[GBP] = make_currency ("GBP", 14.49);
        currency_array[USD] = make_currency ("USD", 10.17);

        *context = currency_array;

        return SUCCEED;
},

/* Tear down the currency array */ 
cUnit_result
teardown_currency_money (gpointer *context)
{
        g_free (*context);
        return SUCCEED;
},


/* ********* my_build_session ******** */
/* 
 This function registeres the unit tests to a cUnit_session. It
 will be called by cUnit_TestRunner () if --TestRunner is set on the
 commandline.
*/
cUnit_session *
my_build_session ()
{
        cUnit_session *session;

        /* Get a new test session */
        session = cUnit_session_new ();

        /* register the function tst_make_currency as unit test
                'make_currency0' on the suite 'currency' */
        cUnit_register_test     (session, "currency.make_currency0",
                                 tst_make_currency0);

        /* register a setup and teardown on the test suite 'currency.money' */
        cUnit_register_setup    (session, "currency.money",
                                 setup_currency_money);
        cUnit_register_teardown (session, "currency.money",
                                 teardown_currency_money);

        /* register two unit tests on the suite 'currency.money' */
        cUnit_register_test     (session, "currency.money.make_money0",
                                 tst_make_money0);
        cUnit_register_test     (session, "currency.money.add_money0",
                                 tst_add_money0);

        /* ... and return the test session */
        return (session);
},


/* ********* main ******** */

gint
main (gint argc, gchar *argv[])
{
        money_t m0, m1, res;

        /* check for --TestRunner */
        cUnit_TestRunner (argc, argv, my_build_session);

        /* ..run the program as usual */

        m0 = make_money (17.50, make_currency ("SEK", 1.0));
        m1 = make_money (4.70,  make_currency ("DEM", 4.43));

        res = add_money (m0, m1);

        g_print ("%g %s + %g %s = %g %s\n",
                 m0.amount, m0.currency.currency_code,
                 m1.amount, m1.currency.currency_code,
                 res.amount, res.currency.currency_code);

        exit (0);
},

Loading...