"Fossies" - the Fresh Open Source Software Archive

Member "udunits-2.2.28/lib/testUnits.c" (7 Dec 2020, 82171 Bytes) of package /linux/privat/udunits-2.2.28.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "testUnits.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.2.26_vs_2.2.28.

    1 /*
    2  * Copyright 2020 University Corporation for Atmospheric Research
    3  *
    4  * This file is part of the UDUNITS-2 package.  See the file COPYRIGHT
    5  * in the top-level source-directory of the package for copying and
    6  * redistribution conditions.
    7  */
    8 #include "config.h"
    9 
   10 #include "udunits2.h"
   11 
   12 #include <float.h>
   13 #include <glob.h>
   14 #include <math.h>
   15 #include <stdarg.h>
   16 #include <stdlib.h>
   17 #include <stdio.h>
   18 #include <string.h>
   19 #include <unistd.h>
   20 #include <CUnit/CUnit.h>
   21 #include <CUnit/Basic.h>
   22 
   23 static const char*      xmlPath;
   24 static ut_system*   unitSystem;
   25 static ut_unit*     kilogram;
   26 static ut_unit*     meter;
   27 static ut_unit*     radian;
   28 static ut_unit*     kelvin;
   29 static ut_unit*     second;
   30 static ut_unit*     minute;
   31 static ut_unit*     kilometer;
   32 static ut_unit*     micron;
   33 static ut_unit*     rankine;
   34 static ut_unit*     celsius;
   35 static ut_unit*     fahrenheit;
   36 static ut_unit*     meterPerSecondSquared;
   37 static ut_unit*     meterSquaredPerSecondSquared;
   38 static ut_unit*     joulePerKilogram;
   39 static ut_unit*     watt;
   40 static ut_unit*     wattSquared;
   41 static ut_unit*     cubicMeter;
   42 static ut_unit*     cubicMicron;
   43 static ut_unit*     BZ;
   44 static ut_unit*     dBZ;
   45 static ut_unit*     secondsSinceTheEpoch;
   46 static ut_unit*     minutesSinceTheMillenium;
   47 static ut_unit*     hertz;
   48 static ut_unit*     megahertz;
   49 
   50 static unsigned     asciiName = UT_ASCII | UT_NAMES;
   51 static unsigned     asciiNameDef = UT_ASCII | UT_NAMES | UT_DEFINITION;
   52 static unsigned     asciiSymbolDef = UT_ASCII | UT_DEFINITION;
   53 static unsigned     latin1SymbolDef = UT_LATIN1 | UT_DEFINITION;
   54 static unsigned     utf8SymbolDef = UT_UTF8 | UT_DEFINITION;
   55 
   56 
   57 /*
   58  * Only called once.
   59  */
   60 static int
   61 setup(
   62     void)
   63 {
   64     return ((unitSystem = ut_new_system()) == NULL)
   65         ? -1
   66         : 0;
   67 }
   68 
   69 
   70 /*
   71  * Only called once.
   72  */
   73 static int
   74 teardown(
   75     void)
   76 {
   77     ut_free_system(unitSystem);
   78 
   79     return 0;
   80 }
   81 
   82 
   83 static void
   84 test_unitSystem(void)
   85 {
   86     ut_system*  system = ut_new_system();
   87     ut_unit*    unit;
   88     char    buf[80];
   89 
   90     CU_ASSERT_PTR_NOT_NULL(system);
   91     ut_set_status(UT_SUCCESS);
   92     unit = ut_new_base_unit(system);
   93     CU_ASSERT_PTR_NOT_NULL(unit);
   94     CU_ASSERT_EQUAL(ut_map_unit_to_name(unit, "name", UT_ASCII), UT_SUCCESS);
   95     ut_free(unit);
   96     unit = ut_get_dimensionless_unit_one(system);
   97     CU_ASSERT_PTR_NOT_NULL_FATAL(unit);
   98     CU_ASSERT_EQUAL(ut_format(unit, buf, sizeof(buf)-1, asciiSymbolDef), 1);
   99     CU_ASSERT_STRING_EQUAL(buf, "1");
  100     ut_free(unit);
  101     ut_free_system(system);
  102     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  103 }
  104 
  105 
  106 static void
  107 test_utNewBaseUnit(void)
  108 {
  109     kilogram = ut_new_base_unit(unitSystem);
  110     CU_ASSERT_PTR_NOT_NULL(kilogram);
  111     CU_ASSERT_EQUAL(ut_map_unit_to_name(kilogram, "kilogram", UT_ASCII),
  112     UT_SUCCESS);
  113     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(kilogram, "kg", UT_ASCII), UT_SUCCESS);
  114     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("kg", UT_ASCII, kilogram), UT_SUCCESS);
  115 
  116     meter = ut_new_base_unit(unitSystem);
  117     CU_ASSERT_PTR_NOT_NULL(meter);
  118     CU_ASSERT_EQUAL(ut_map_name_to_unit("meter", UT_ASCII, meter), UT_SUCCESS);
  119     CU_ASSERT_EQUAL(ut_map_unit_to_name(meter, "meter", UT_ASCII), UT_SUCCESS);
  120     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(meter, "m", UT_ASCII), UT_SUCCESS);
  121     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("m", UT_ASCII, meter), UT_SUCCESS);
  122 
  123     kelvin = ut_new_base_unit(unitSystem);
  124     CU_ASSERT_PTR_NOT_NULL(kelvin);
  125     CU_ASSERT_EQUAL(ut_map_unit_to_name(kelvin, "kelvin", UT_ASCII), UT_SUCCESS);
  126     CU_ASSERT_EQUAL(ut_map_name_to_unit("kelvin", UT_ASCII, kelvin), UT_SUCCESS);
  127     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(kelvin, "K", UT_ASCII), UT_SUCCESS);
  128     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("K", UT_ASCII, kelvin), UT_SUCCESS);
  129 
  130     CU_ASSERT_EQUAL(ut_map_unit_to_name(kilogram, "dummy", UT_ASCII), UT_EXISTS);
  131 
  132     second = ut_new_base_unit(unitSystem);
  133     CU_ASSERT_PTR_NOT_NULL(second);
  134 
  135     CU_ASSERT_PTR_NULL(ut_offset_by_time(second,
  136         ut_encode_time(1970, 1, 1, 0, 0, 0)));
  137     CU_ASSERT_EQUAL(ut_get_status(), UT_NO_SECOND);
  138 
  139     CU_ASSERT_EQUAL(ut_set_second(second), UT_SUCCESS);
  140     CU_ASSERT_EQUAL(ut_set_second(NULL), UT_BAD_ARG);
  141     CU_ASSERT_EQUAL(ut_map_unit_to_name(second, "second", UT_ASCII), UT_SUCCESS);
  142     CU_ASSERT_EQUAL(ut_map_name_to_unit("second", UT_ASCII, second), UT_SUCCESS);
  143     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(second, "s", UT_ASCII), UT_SUCCESS);
  144     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("s", UT_ASCII, second), UT_SUCCESS);
  145 
  146     CU_ASSERT_PTR_NULL(ut_new_base_unit(NULL));
  147     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  148 
  149     CU_ASSERT_EQUAL(ut_map_unit_to_name(kilogram, "\xc5ngstr\xf6m", UT_UTF8), UT_BAD_ARG);
  150 
  151     CU_ASSERT_EQUAL(ut_set_second(second), UT_SUCCESS);
  152     CU_ASSERT_EQUAL(ut_set_second(meter), UT_EXISTS);
  153     CU_ASSERT_EQUAL(ut_set_second(NULL), UT_BAD_ARG);
  154 }
  155 
  156 
  157 static void
  158 test_utNewDimensionlessUnit(void)
  159 {
  160     radian = ut_new_dimensionless_unit(unitSystem);
  161     CU_ASSERT_PTR_NOT_NULL(radian);
  162     CU_ASSERT_EQUAL(ut_map_unit_to_name(radian, "radian", UT_ASCII), UT_SUCCESS);
  163     CU_ASSERT_EQUAL(ut_map_name_to_unit("radian", UT_ASCII, radian), UT_SUCCESS);
  164     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(radian, "rad", UT_ASCII), UT_SUCCESS);
  165     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("rad", UT_ASCII, radian), UT_SUCCESS);
  166 
  167     CU_ASSERT_EQUAL(ut_map_unit_to_name(radian, "dummy", UT_ASCII), UT_EXISTS);
  168 
  169     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(radian, "f", UT_ASCII), UT_EXISTS);
  170     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(NULL, "f", UT_ASCII), UT_BAD_ARG);
  171 
  172     CU_ASSERT_EQUAL(ut_map_unit_to_name(radian, "\xc5ngstr\xf6m", UT_UTF8), UT_BAD_ARG);
  173 }
  174 
  175 
  176 static void
  177 test_utGetUnitByName(void)
  178 {
  179     ut_unit*    altMeter = ut_get_unit_by_name(unitSystem, "meter");
  180 
  181     CU_ASSERT_PTR_NOT_NULL(altMeter);
  182     CU_ASSERT_EQUAL(ut_compare(altMeter, meter), 0);
  183     ut_free(altMeter);
  184 
  185     CU_ASSERT_PTR_NULL(ut_get_unit_by_name(unitSystem, NULL));
  186     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  187 
  188     CU_ASSERT_PTR_NULL(ut_get_unit_by_name(unitSystem, "foo"));
  189     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  190 }
  191 
  192 
  193 static void
  194 test_utGetUnitBySymbol(void)
  195 {
  196     ut_unit*    altMeter = ut_get_unit_by_symbol(unitSystem, "m");
  197 
  198     CU_ASSERT_PTR_NOT_NULL(altMeter);
  199     CU_ASSERT_EQUAL(ut_compare(altMeter, meter), 0);
  200     ut_free(altMeter);
  201 
  202     CU_ASSERT_PTR_NULL(ut_get_unit_by_symbol(unitSystem, NULL));
  203     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  204 
  205     CU_ASSERT_PTR_NULL(ut_get_unit_by_symbol(unitSystem, "M"));
  206     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  207 }
  208 
  209 
  210 static void
  211 test_utAddNamePrefix(void)
  212 {
  213     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, "mega", 1e6), UT_SUCCESS);
  214     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, "mega", 1e6), UT_SUCCESS);
  215     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, "MEGA", 1e6), UT_SUCCESS);
  216 
  217     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, "mega", 1e5), UT_EXISTS);
  218     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, "MEGA", 1e5), UT_EXISTS);
  219     CU_ASSERT_EQUAL(ut_add_name_prefix(NULL, "foo", 1), UT_BAD_ARG);
  220     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, "", 2), UT_BAD_ARG);
  221     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, NULL, 3), UT_BAD_ARG);
  222     CU_ASSERT_EQUAL(ut_add_name_prefix(unitSystem, "foo", 0), UT_BAD_ARG);
  223 }
  224 
  225 
  226 static void
  227 test_utAddSymbolPrefix(void)
  228 {
  229     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "M", 1e6), UT_SUCCESS);
  230     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "M", 1e6), UT_SUCCESS);
  231     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "u", 1e-6), UT_SUCCESS);
  232     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "\xb5", 1e-6), UT_SUCCESS);
  233     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "\xc2\xb5", 1e-6),
  234         UT_SUCCESS);    /* "\xc2\xb5" is "mu" character in UTF-8 */
  235     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "k", 1e3), UT_SUCCESS);
  236 
  237     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "M", 1e5), UT_EXISTS);
  238     CU_ASSERT_EQUAL(ut_add_symbol_prefix(NULL, "foo", 1), UT_BAD_ARG);
  239     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "", 2), UT_BAD_ARG);
  240     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, NULL, 3), UT_BAD_ARG);
  241     CU_ASSERT_EQUAL(ut_add_symbol_prefix(unitSystem, "f", 0), UT_BAD_ARG);
  242 }
  243 
  244 
  245 static void
  246 test_utMapNameToUnit(void)
  247 {
  248     ut_unit*    metre;
  249 
  250     CU_ASSERT_PTR_NULL(ut_get_unit_by_name(unitSystem, "metre"));
  251 
  252     CU_ASSERT_EQUAL(ut_map_name_to_unit("metre", UT_ASCII, meter), UT_SUCCESS);
  253     CU_ASSERT_EQUAL(ut_map_name_to_unit("metre", UT_ASCII, meter), UT_SUCCESS);
  254 
  255     CU_ASSERT_EQUAL(ut_map_name_to_unit("metre", UT_ASCII, second), UT_EXISTS);
  256     CU_ASSERT_EQUAL(ut_map_name_to_unit("metre", UT_ASCII, NULL), UT_BAD_ARG);
  257 
  258     metre = ut_get_unit_by_name(unitSystem, "metre");
  259     CU_ASSERT_PTR_NOT_NULL(metre);
  260     CU_ASSERT_EQUAL(ut_compare(metre, meter), 0);
  261     ut_free(metre);
  262 }
  263 
  264 
  265 static void
  266 test_utMapSymbolToUnit(void)
  267 {
  268     ut_unit*    degK;
  269 
  270     /* "\xb0" is the degree symbol in Latin-1 */
  271     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xb0K", UT_LATIN1, kelvin), UT_SUCCESS);
  272     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xb0K", UT_LATIN1, kelvin), UT_SUCCESS);
  273 
  274     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xb0K", UT_LATIN1, second), UT_EXISTS);
  275     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xb0K", UT_LATIN1, NULL), UT_BAD_ARG);
  276 
  277     degK = ut_get_unit_by_symbol(unitSystem, "\xb0K");
  278     CU_ASSERT_PTR_NOT_NULL(degK);
  279     CU_ASSERT_EQUAL(ut_compare(degK, kelvin), 0);
  280     ut_free(degK);
  281 
  282     /* "\xc2\xb0" is the degree symbol in UTF-8 */
  283     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xc2\xb0K", UT_UTF8, kelvin), UT_SUCCESS);
  284     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xc2\xb0K", UT_UTF8, kelvin), UT_SUCCESS);
  285 
  286     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xc2\xb0K", UT_UTF8, second), UT_EXISTS);
  287     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("\xc2\xb0K", UT_UTF8, NULL), UT_BAD_ARG);
  288 
  289     degK = ut_get_unit_by_symbol(unitSystem, "\xc2\xb0K");
  290     CU_ASSERT_PTR_NOT_NULL(degK);
  291     CU_ASSERT_EQUAL(ut_compare(degK, kelvin), 0);
  292     ut_free(degK);
  293 }
  294 
  295 
  296 static void
  297 test_utToString(void)
  298 {
  299     char    buf[80];
  300     int     nchar = ut_format(meter, buf, sizeof(buf)-1, asciiSymbolDef);
  301     int     n;
  302     ut_unit*    unit;
  303     const char* string = "s @ 1-01-01 00:00:00.000000 UTC";
  304 
  305     CU_ASSERT_EQUAL(nchar, 1);
  306     CU_ASSERT_STRING_EQUAL(buf, "m");
  307 
  308     n = ut_format(kilogram, buf, 1, asciiSymbolDef);
  309     CU_ASSERT_EQUAL(n, 2);
  310 
  311     nchar = ut_format(meter, buf, sizeof(buf)-1, asciiName);
  312     CU_ASSERT_STRING_EQUAL(buf, "meter");
  313 
  314     n = ut_format(celsius, buf, sizeof(buf)-1, asciiName);
  315     CU_ASSERT_TRUE(n > 0);
  316     CU_ASSERT_STRING_EQUAL(buf, "degrees_celsius");
  317 
  318     unit = ut_parse(unitSystem, "second since 1-01-01T00:00:00Z", UT_ASCII);
  319     CU_ASSERT_PTR_NOT_NULL(unit);
  320     CU_ASSERT(ut_format(unit, buf, sizeof(buf), asciiSymbolDef) != -1);
  321     CU_ASSERT_STRING_EQUAL(buf, string);
  322     if (strcmp(buf, string))
  323         printf("%d: buf=%s\n", __LINE__, buf);
  324 
  325     n = ut_format(unit, buf, 1, asciiSymbolDef);
  326     CU_ASSERT_EQUAL(n, strlen(string));
  327     if (n != strlen(string))
  328         printf("%d: n=%d\n", __LINE__, n);
  329     ut_free(unit);
  330 }
  331 
  332 
  333 static void
  334 test_utScale(void)
  335 {
  336     ut_unit*    metre;
  337     char    buf[80];
  338     int     nchar;
  339 
  340     kilometer = ut_scale(1000, meter);
  341     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  342     CU_ASSERT_PTR_NOT_NULL(kilometer);
  343     CU_ASSERT_EQUAL(ut_get_system(meter), ut_get_system(kilometer));
  344     CU_ASSERT_EQUAL(ut_compare(meter, kilometer), -1);
  345     CU_ASSERT_EQUAL(ut_compare(kilometer, meter), 1);
  346 
  347     nchar = ut_format(kilometer, buf, sizeof(buf)-1, asciiSymbolDef);
  348     CU_ASSERT_TRUE_FATAL(nchar > 0);
  349     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  350     buf[nchar] = 0;
  351     CU_ASSERT_STRING_EQUAL(buf, "1000 m");
  352 
  353     nchar = ut_format(kilometer, buf, sizeof(buf)-1, asciiNameDef);
  354     CU_ASSERT_TRUE_FATAL(nchar > 0);
  355     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  356     buf[nchar] = 0;
  357     CU_ASSERT_STRING_EQUAL(buf, "1000 meter");
  358 
  359     micron = ut_scale(1e-6, meter);
  360     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  361     CU_ASSERT_PTR_NOT_NULL(micron);
  362     CU_ASSERT_EQUAL(ut_get_system(meter), ut_get_system(micron));
  363     CU_ASSERT_EQUAL(ut_compare(meter, micron), -1);
  364     CU_ASSERT_EQUAL(ut_compare(micron, meter), 1);
  365     CU_ASSERT_EQUAL(ut_compare(kilometer, micron), 1);
  366     CU_ASSERT_EQUAL(ut_compare(micron, kilometer), -1);
  367 
  368     metre = ut_scale(1, meter);
  369     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  370     CU_ASSERT_PTR_NOT_NULL(metre);
  371     CU_ASSERT_EQUAL(ut_get_system(meter), ut_get_system(metre));
  372     CU_ASSERT_EQUAL(ut_compare(meter, metre), 0);
  373     ut_free(metre);
  374 
  375     minute = ut_scale(60, second);
  376     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  377     CU_ASSERT_PTR_NOT_NULL(minute);
  378     nchar = ut_format(minute, buf, sizeof(buf)-1, asciiSymbolDef);
  379     CU_ASSERT_TRUE_FATAL(nchar > 0);
  380     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  381     buf[nchar] = 0;
  382     CU_ASSERT_STRING_EQUAL(buf, "60 s");
  383 
  384     nchar = ut_format(minute, buf, sizeof(buf)-1, asciiNameDef);
  385     CU_ASSERT_TRUE_FATAL(nchar > 0);
  386     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  387     buf[nchar] = 0;
  388     CU_ASSERT_STRING_EQUAL(buf, "60 second");
  389 
  390     metre = ut_scale(1/1000., kilometer);
  391     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  392     CU_ASSERT_PTR_NOT_NULL(metre);
  393     CU_ASSERT_EQUAL(ut_get_system(meter), ut_get_system(metre));
  394     ut_free(metre);
  395 
  396     CU_ASSERT_PTR_NULL(ut_scale(0, meter));
  397     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  398 
  399     CU_ASSERT_PTR_NULL(ut_scale(0, NULL));
  400     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  401 
  402     rankine = ut_scale(1/1.8, kelvin);
  403     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  404     CU_ASSERT_PTR_NOT_NULL(rankine);
  405 }
  406 
  407 
  408 static void
  409 test_utOffset(void)
  410 {
  411     ut_unit*    dupKelvin;
  412     char    buf[80];
  413     int     nchar;
  414 
  415     celsius = ut_offset(kelvin, 273.15);
  416     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  417     CU_ASSERT_PTR_NOT_NULL(celsius);
  418     CU_ASSERT_EQUAL(ut_get_system(kelvin), ut_get_system(celsius));
  419     CU_ASSERT_EQUAL(ut_compare(kelvin, celsius), -1);
  420     CU_ASSERT_EQUAL(ut_compare(celsius, kelvin), 1);
  421 
  422     fahrenheit = ut_offset(rankine, 459.67);
  423     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  424     CU_ASSERT_PTR_NOT_NULL(fahrenheit);
  425     CU_ASSERT_EQUAL(ut_get_system(rankine), ut_get_system(fahrenheit));
  426     CU_ASSERT_EQUAL(ut_compare(rankine, fahrenheit), -1);
  427     CU_ASSERT_EQUAL(ut_compare(fahrenheit, rankine), 1);
  428     CU_ASSERT_EQUAL(ut_compare(celsius, fahrenheit), -1);
  429     CU_ASSERT_EQUAL(ut_compare(fahrenheit, celsius), 1);
  430     CU_ASSERT_EQUAL(ut_map_name_to_unit("degrees_fahrenheit", UT_ASCII, fahrenheit),
  431     UT_SUCCESS);
  432 
  433     nchar = ut_format(celsius, buf, sizeof(buf)-1, asciiSymbolDef);
  434     CU_ASSERT_TRUE_FATAL(nchar > 0);
  435     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  436     buf[nchar] = 0;
  437     CU_ASSERT_STRING_EQUAL(buf, "K @ 273.15");
  438 
  439     nchar = ut_format(celsius, buf, sizeof(buf)-1, asciiNameDef);
  440     CU_ASSERT_TRUE_FATAL(nchar > 0);
  441     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  442     buf[nchar] = 0;
  443     CU_ASSERT_STRING_EQUAL(buf, "kelvin from 273.15");
  444 
  445     dupKelvin = ut_offset(kelvin, 0);
  446     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  447     CU_ASSERT_PTR_NOT_NULL(dupKelvin);
  448     CU_ASSERT_EQUAL(ut_get_system(kelvin), ut_get_system(dupKelvin));
  449     CU_ASSERT_EQUAL(ut_compare(kelvin, dupKelvin), 0);
  450     ut_free(dupKelvin);
  451 
  452     dupKelvin = ut_offset(celsius, -273.15);
  453     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  454     CU_ASSERT_PTR_NOT_NULL(dupKelvin);
  455     CU_ASSERT_EQUAL(ut_get_system(kelvin), ut_get_system(dupKelvin));
  456     ut_free(dupKelvin);
  457 
  458     (void)ut_offset(NULL, 5);
  459     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  460 }
  461 
  462 
  463 static void
  464 test_utMapUnitToName(void)
  465 {
  466     ut_unit*    metre;
  467 
  468     CU_ASSERT_EQUAL(ut_map_unit_to_name(meter, "metre", UT_ASCII), UT_EXISTS);
  469 
  470     CU_ASSERT_EQUAL(ut_map_name_to_unit("metre", UT_ASCII, second), UT_EXISTS);
  471     CU_ASSERT_EQUAL(ut_map_name_to_unit("metre", UT_ASCII, NULL), UT_BAD_ARG);
  472 
  473     metre = ut_get_unit_by_name(unitSystem, "metre");
  474     CU_ASSERT_PTR_NOT_NULL(metre);
  475     CU_ASSERT_EQUAL(ut_compare(metre, meter), 0);
  476 
  477     CU_ASSERT_EQUAL(ut_map_unit_to_name(celsius, "degrees_celsius", UT_ASCII),
  478     UT_SUCCESS);
  479 
  480     ut_free(metre);
  481 }
  482 
  483 
  484 static void
  485 test_utGetName(void)
  486 {
  487     CU_ASSERT_STRING_EQUAL(ut_get_name(meter, UT_ASCII), "meter");
  488     CU_ASSERT_STRING_EQUAL(ut_get_name(celsius, UT_ASCII), "degrees_celsius");
  489     CU_ASSERT_STRING_EQUAL(ut_get_name(kilogram, UT_ASCII), "kilogram");
  490     CU_ASSERT_STRING_EQUAL(ut_get_name(kelvin, UT_ASCII), "kelvin");
  491     CU_ASSERT_STRING_EQUAL(ut_get_name(second, UT_ASCII), "second");
  492     CU_ASSERT_STRING_EQUAL(ut_get_name(radian, UT_ASCII), "radian");
  493 }
  494 
  495 
  496 static void
  497 test_utGetSymbol(void)
  498 {
  499     CU_ASSERT_STRING_EQUAL(ut_get_symbol(kilogram, UT_ASCII), "kg");
  500     CU_ASSERT_STRING_EQUAL(ut_get_symbol(meter, UT_ASCII), "m");
  501     CU_ASSERT_STRING_EQUAL(ut_get_symbol(kelvin, UT_ASCII), "K");
  502     CU_ASSERT_STRING_EQUAL(ut_get_symbol(second, UT_ASCII), "s");
  503     CU_ASSERT_STRING_EQUAL(ut_get_symbol(radian, UT_ASCII), "rad");
  504     CU_ASSERT_STRING_EQUAL(ut_get_symbol(hertz, UT_ASCII), "Hz");
  505 }
  506 
  507 
  508 static void
  509 test_utMultiply(void)
  510 {
  511     ut_unit*    squareMeter;
  512     ut_unit*    meterSecond;
  513     ut_unit*    meterCelsius;
  514     ut_unit*    meterRadian;
  515     ut_unit*    kilometerMinute;
  516     ut_unit*    unit;
  517     char    buf[80];
  518     int     nchar;
  519 
  520     squareMeter = ut_multiply(meter, meter);
  521     CU_ASSERT_PTR_NOT_NULL(squareMeter);
  522     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  523     nchar = ut_format(squareMeter, buf, sizeof(buf)-1, asciiSymbolDef);
  524     CU_ASSERT_TRUE_FATAL(nchar > 0);
  525     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  526     buf[nchar] = 0;
  527     CU_ASSERT_STRING_EQUAL(buf, "m2");
  528 
  529     nchar = ut_format(squareMeter, buf, sizeof(buf)-1, asciiNameDef);
  530     CU_ASSERT_TRUE_FATAL(nchar > 0);
  531     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  532     buf[nchar] = 0;
  533     CU_ASSERT_STRING_EQUAL(buf, "meter^2");
  534 
  535     meterSecond = ut_multiply(meter, second);
  536     CU_ASSERT_PTR_NOT_NULL(meterSecond);
  537     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  538     nchar = ut_format(meterSecond, buf, sizeof(buf)-1, asciiSymbolDef);
  539     CU_ASSERT_TRUE_FATAL(nchar > 0);
  540     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  541     buf[nchar] = 0;
  542     CU_ASSERT_STRING_EQUAL(buf, "m.s");
  543 
  544     nchar = ut_format(meterSecond, buf, sizeof(buf)-1, asciiNameDef);
  545     CU_ASSERT_TRUE_FATAL(nchar > 0);
  546     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  547     buf[nchar] = 0;
  548     CU_ASSERT_STRING_EQUAL(buf, "meter-second");
  549 
  550     meterCelsius = ut_multiply(meter, celsius);
  551     CU_ASSERT_PTR_NOT_NULL(meterCelsius);
  552     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  553     nchar = ut_format(meterCelsius, buf, sizeof(buf)-1, asciiSymbolDef);
  554     CU_ASSERT_TRUE_FATAL(nchar > 0);
  555     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  556     buf[nchar] = 0;
  557     CU_ASSERT_STRING_EQUAL(buf, "m.K");
  558 
  559     meterRadian = ut_multiply(meter, radian);
  560     CU_ASSERT_PTR_NOT_NULL(meterRadian);
  561     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  562     nchar = ut_format(meterRadian, buf, sizeof(buf)-1, asciiSymbolDef);
  563     CU_ASSERT_TRUE_FATAL(nchar > 0);
  564     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  565     buf[nchar] = 0;
  566     CU_ASSERT_STRING_EQUAL(buf, "m.rad");
  567 
  568     kilometerMinute = ut_multiply(kilometer, minute);
  569     CU_ASSERT_PTR_NOT_NULL(kilometerMinute);
  570     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  571     nchar = ut_format(kilometerMinute, buf, sizeof(buf)-1, asciiSymbolDef);
  572     CU_ASSERT_TRUE_FATAL(nchar > 0);
  573     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  574     buf[nchar] = 0;
  575     CU_ASSERT_STRING_EQUAL(buf, "60000 m.s");
  576 
  577     nchar = ut_format(kilometerMinute, buf, sizeof(buf)-1, asciiNameDef);
  578     CU_ASSERT_TRUE_FATAL(nchar > 0);
  579     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  580     buf[nchar] = 0;
  581     CU_ASSERT_STRING_EQUAL(buf, "60000 meter-second");
  582 
  583     unit = ut_multiply(secondsSinceTheEpoch, meter);
  584     CU_ASSERT_PTR_NOT_NULL(unit);
  585     ut_free(unit);
  586 
  587     ut_free(squareMeter);
  588     ut_free(meterSecond);
  589     ut_free(meterCelsius);
  590     ut_free(meterRadian);
  591     ut_free(kilometerMinute);
  592 
  593     CU_ASSERT_PTR_NULL(ut_multiply(NULL, meter));
  594     CU_ASSERT_PTR_NULL(ut_multiply(meter, NULL));
  595 }
  596 
  597 
  598 static void
  599 test_utInvert(void)
  600 {
  601     ut_unit*    inverseMeter;
  602     ut_unit*    inverseMinute;
  603     ut_unit*    inverseCelsius;
  604     ut_unit*    inverseRadian;
  605     ut_unit*    inverseMeterSecond;
  606     ut_unit*    unit;
  607     char    buf[80];
  608     int     nchar;
  609 
  610     inverseMeter = ut_invert(meter);
  611     CU_ASSERT_PTR_NOT_NULL(inverseMeter);
  612     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  613     nchar = ut_format(inverseMeter, buf, sizeof(buf)-1, asciiSymbolDef);
  614     CU_ASSERT_TRUE_FATAL(nchar > 0);
  615     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  616     buf[nchar] = 0;
  617     CU_ASSERT_STRING_EQUAL(buf, "m-1");
  618 
  619     inverseMinute = ut_invert(minute);
  620     CU_ASSERT_PTR_NOT_NULL(inverseMinute);
  621     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  622     nchar = ut_format(inverseMinute, buf, sizeof(buf)-1, asciiSymbolDef);
  623     CU_ASSERT_TRUE_FATAL(nchar > 0);
  624     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  625     buf[nchar] = 0;
  626     CU_ASSERT_STRING_EQUAL(buf, "0.0166666666666667 s-1");
  627 
  628     inverseRadian = ut_invert(radian);
  629     CU_ASSERT_PTR_NOT_NULL(inverseRadian);
  630     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  631     nchar = ut_format(inverseRadian, buf, sizeof(buf)-1, asciiSymbolDef);
  632     CU_ASSERT_TRUE_FATAL(nchar > 0);
  633     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  634     buf[nchar] = 0;
  635     CU_ASSERT_STRING_EQUAL(buf, "rad-1");
  636 
  637     inverseCelsius = ut_invert(celsius);
  638     CU_ASSERT_PTR_NOT_NULL(inverseCelsius);
  639     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  640     nchar = ut_format(inverseCelsius, buf, sizeof(buf)-1, asciiSymbolDef);
  641     CU_ASSERT_TRUE_FATAL(nchar > 0);
  642     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  643     buf[nchar] = 0;
  644     CU_ASSERT_STRING_EQUAL(buf, "K-1");
  645 
  646     unit = ut_multiply(meter, second);
  647     inverseMeterSecond = ut_invert(unit);
  648     ut_free(unit);
  649     CU_ASSERT_PTR_NOT_NULL(inverseMeterSecond);
  650     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  651     nchar = ut_format(inverseMeterSecond, buf, sizeof(buf)-1, asciiSymbolDef);
  652     CU_ASSERT_TRUE_FATAL(nchar > 0);
  653     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  654     buf[nchar] = 0;
  655     CU_ASSERT_STRING_EQUAL(buf, "m-1.s-1");
  656 
  657     ut_free(inverseMeter);
  658     ut_free(inverseMinute);
  659     ut_free(inverseCelsius);
  660     ut_free(inverseRadian);
  661     ut_free(inverseMeterSecond);
  662 
  663     hertz = ut_invert(second);
  664     CU_ASSERT_PTR_NOT_NULL(hertz);
  665     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  666 
  667     CU_ASSERT_EQUAL(ut_map_unit_to_name(hertz, "hertz", UT_ASCII), UT_SUCCESS);
  668     CU_ASSERT_EQUAL(ut_map_name_to_unit("hertz", UT_ASCII, hertz), UT_SUCCESS);
  669     CU_ASSERT_EQUAL(ut_map_unit_to_symbol(hertz, "Hz", UT_ASCII), UT_SUCCESS);
  670     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("Hz", UT_ASCII, hertz), UT_SUCCESS);
  671 
  672     unit = ut_invert(second);
  673     megahertz = ut_scale(1e6, unit);
  674     ut_free(unit);
  675     CU_ASSERT_PTR_NOT_NULL(megahertz);
  676     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  677 }
  678 
  679 
  680 static void
  681 test_utDivide(void)
  682 {
  683     ut_unit*    meterPerSecond;
  684     ut_unit*    kilometerPerMinute;
  685     ut_unit*    celsiusPerMeter;
  686     ut_unit*    meterPerCelsius;
  687     ut_unit*    unit;
  688     ut_unit*    unit2;
  689     ut_unit*    unit3;
  690     char    buf[80];
  691     int     nchar;
  692 
  693     meterPerSecond = ut_divide(meter, second);
  694     CU_ASSERT_PTR_NOT_NULL(meterPerSecond);
  695     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  696     nchar = ut_format(meterPerSecond, buf, sizeof(buf)-1, asciiSymbolDef);
  697     CU_ASSERT_TRUE_FATAL(nchar > 0);
  698     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  699     buf[nchar] = 0;
  700     CU_ASSERT_STRING_EQUAL(buf, "m.s-1");
  701 
  702     kilometerPerMinute = ut_divide(kilometer, minute);
  703     CU_ASSERT_PTR_NOT_NULL(kilometerPerMinute);
  704     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  705     nchar = ut_format(kilometerPerMinute, buf, sizeof(buf)-1, asciiSymbolDef);
  706     CU_ASSERT_TRUE_FATAL(nchar > 0);
  707     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  708     buf[nchar] = 0;
  709     CU_ASSERT_STRING_EQUAL(buf, "16.6666666666667 m.s-1");
  710 
  711     celsiusPerMeter = ut_divide(celsius, meter);
  712     CU_ASSERT_PTR_NOT_NULL(celsiusPerMeter);
  713     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  714     nchar = ut_format(celsiusPerMeter, buf, sizeof(buf)-1, asciiSymbolDef);
  715     CU_ASSERT_TRUE_FATAL(nchar > 0);
  716     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  717     buf[nchar] = 0;
  718     CU_ASSERT_STRING_EQUAL(buf, "m-1.K");
  719 
  720     meterPerCelsius = ut_divide(meter, celsius);
  721     CU_ASSERT_PTR_NOT_NULL(meterPerCelsius);
  722     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  723     nchar = ut_format(meterPerCelsius, buf, sizeof(buf)-1, asciiSymbolDef);
  724     CU_ASSERT_TRUE_FATAL(nchar > 0);
  725     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  726     buf[nchar] = 0;
  727     CU_ASSERT_STRING_EQUAL(buf, "m.K-1");
  728 
  729     unit = ut_raise(second, 2);
  730     meterPerSecondSquared = ut_divide(meter, unit);
  731     ut_free(unit);
  732     CU_ASSERT_PTR_NOT_NULL(meterPerSecondSquared);
  733     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  734     nchar = ut_format(meterPerSecondSquared, buf, sizeof(buf)-1,
  735     asciiSymbolDef);
  736     CU_ASSERT_TRUE_FATAL(nchar > 0);
  737     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  738     buf[nchar] = 0;
  739     CU_ASSERT_STRING_EQUAL(buf, "m.s-2");
  740 
  741     unit = ut_divide(meter, second);
  742     meterSquaredPerSecondSquared = ut_raise(unit, 2);
  743     ut_free(unit);
  744     CU_ASSERT_PTR_NOT_NULL(meterSquaredPerSecondSquared);
  745     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  746     nchar = ut_format(meterSquaredPerSecondSquared, buf, sizeof(buf)-1,
  747     asciiSymbolDef);
  748     CU_ASSERT_TRUE_FATAL(nchar > 0);
  749     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  750     buf[nchar] = 0;
  751     CU_ASSERT_STRING_EQUAL(buf, "m2.s-2");
  752 
  753     unit = ut_divide(meter, second);
  754     unit2 = ut_raise(unit, 2);
  755     ut_free(unit);
  756     unit3 = ut_multiply(kilogram, unit2);
  757     ut_free(unit2);
  758     joulePerKilogram = ut_divide(unit3, kilogram);
  759     ut_free(unit3);
  760     CU_ASSERT_PTR_NOT_NULL(joulePerKilogram);
  761     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  762     nchar = ut_format(joulePerKilogram, buf, sizeof(buf)-1, asciiSymbolDef);
  763     CU_ASSERT_TRUE_FATAL(nchar > 0);
  764     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  765     buf[nchar] = 0;
  766     CU_ASSERT_STRING_EQUAL(buf, "m2.s-2");
  767 
  768     unit = ut_divide(meter, second);
  769     unit2 = ut_raise(unit, 2);
  770     ut_free(unit);
  771     unit3 = ut_multiply(kilogram, unit2);
  772     ut_free(unit2);
  773     watt = ut_divide(unit3, second);
  774     ut_free(unit3);
  775     CU_ASSERT_PTR_NOT_NULL(watt);
  776     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  777     nchar = ut_format(watt, buf, sizeof(buf)-1, asciiSymbolDef);
  778     CU_ASSERT_TRUE_FATAL(nchar > 0);
  779     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  780     buf[nchar] = 0;
  781     CU_ASSERT_STRING_EQUAL(buf, "kg.m2.s-3");
  782 
  783     ut_free(meterPerSecond);
  784     ut_free(kilometerPerMinute);
  785     ut_free(celsiusPerMeter);
  786     ut_free(meterPerCelsius);
  787 
  788     CU_ASSERT_PTR_NULL(ut_divide(NULL, meter));
  789     CU_ASSERT_PTR_NULL(ut_divide(meter, NULL));
  790 }
  791 
  792 
  793 static void
  794 test_utRaise(void)
  795 {
  796     ut_unit*    perCubicMeter;
  797     ut_unit*    celsiusCubed;
  798     ut_unit*    minutesPerKilometer;
  799     ut_unit*    kilometersSquaredPerMinuteSquared;
  800     ut_unit*    unit;
  801     char    buf[80];
  802     int     nchar;
  803 
  804     wattSquared = ut_raise(watt, 2);
  805     CU_ASSERT_PTR_NOT_NULL(wattSquared);
  806     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  807     nchar = ut_format(wattSquared, buf, sizeof(buf)-1, asciiSymbolDef);
  808     CU_ASSERT_TRUE_FATAL(nchar > 0);
  809     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  810     buf[nchar] = 0;
  811     CU_ASSERT_STRING_EQUAL(buf, "kg2.m4.s-6");
  812 
  813     perCubicMeter = ut_raise(meter, -3);
  814     CU_ASSERT_PTR_NOT_NULL(perCubicMeter);
  815     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  816     nchar = ut_format(perCubicMeter, buf, sizeof(buf)-1, asciiSymbolDef);
  817     CU_ASSERT_TRUE_FATAL(nchar > 0);
  818     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  819     buf[nchar] = 0;
  820     CU_ASSERT_STRING_EQUAL(buf, "m-3");
  821 
  822     celsiusCubed = ut_raise(celsius, 3);
  823     CU_ASSERT_PTR_NOT_NULL(celsiusCubed);
  824     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  825     nchar = ut_format(celsiusCubed, buf, sizeof(buf)-1, asciiSymbolDef);
  826     CU_ASSERT_TRUE_FATAL(nchar > 0);
  827     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  828     buf[nchar] = 0;
  829     CU_ASSERT_STRING_EQUAL(buf, "K3");
  830 
  831     minutesPerKilometer = ut_divide(minute, kilometer);
  832     kilometersSquaredPerMinuteSquared = ut_raise(minutesPerKilometer, -2);
  833     ut_free(minutesPerKilometer);
  834     CU_ASSERT_PTR_NOT_NULL(kilometersSquaredPerMinuteSquared);
  835     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  836     nchar = ut_format(kilometersSquaredPerMinuteSquared, buf,
  837     sizeof(buf)-1, asciiSymbolDef);
  838     CU_ASSERT_TRUE_FATAL(nchar > 0);
  839     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  840     buf[nchar] = 0;
  841     CU_ASSERT_STRING_EQUAL(buf, "277.777777777778 m2.s-2");
  842 
  843     ut_free(perCubicMeter);
  844     ut_free(celsiusCubed);
  845     ut_free(kilometersSquaredPerMinuteSquared);
  846 
  847     unit = ut_raise(meter, 0);
  848     CU_ASSERT_PTR_NOT_NULL(unit);
  849     CU_ASSERT_EQUAL(ut_compare(unit, ut_get_dimensionless_unit_one(unitSystem)), 0);
  850     ut_free(unit);
  851 
  852     unit = ut_raise(meter, 1);
  853     CU_ASSERT_PTR_NOT_NULL(unit);
  854     CU_ASSERT_EQUAL(ut_compare(unit, meter), 0);
  855     ut_free(unit);
  856 
  857     unit = ut_raise(secondsSinceTheEpoch, 2);
  858     CU_ASSERT_PTR_NOT_NULL(unit);
  859     ut_free(unit);
  860 
  861     CU_ASSERT_PTR_NULL(ut_raise(dBZ, 2));
  862     CU_ASSERT_PTR_NULL(ut_raise(NULL, 2));
  863 }
  864 
  865 
  866 static void
  867 test_utRoot(void)
  868 {
  869     ut_unit*    unit;
  870     ut_unit*    unit2;
  871 
  872     CU_ASSERT_PTR_NULL(ut_root(watt, -1));
  873     CU_ASSERT_PTR_NULL(ut_root(watt, 0));
  874     unit = ut_root(watt, 1);
  875     CU_ASSERT_EQUAL(ut_compare(watt, unit), 0);
  876     ut_free(unit);
  877 
  878     unit = ut_get_dimensionless_unit_one(unitSystem);
  879     CU_ASSERT_EQUAL(ut_compare(unit, ut_root(unit, 1)), 0);
  880     ut_free(unit);
  881     unit = ut_root(watt, 1);
  882     CU_ASSERT_EQUAL(ut_compare(watt, unit), 0);
  883     ut_free(unit);
  884 
  885     unit = ut_raise(watt, 2);
  886     unit2 = ut_root(unit, 2);
  887     ut_free(unit);
  888     CU_ASSERT_EQUAL(ut_compare(watt, unit2), 0);
  889     ut_free(unit2);
  890 
  891     unit = ut_raise(celsius, 2);
  892     unit2 = ut_root(unit, 2);
  893     ut_free(unit);
  894     CU_ASSERT_EQUAL(ut_compare(kelvin, unit2), 0);
  895     ut_free(unit2);
  896 
  897     unit = ut_raise(secondsSinceTheEpoch, 2);
  898     unit2 = ut_root(unit, 2);
  899     ut_free(unit);
  900     CU_ASSERT_EQUAL(ut_compare(second, unit2), 0);
  901     ut_free(unit2);
  902 
  903     CU_ASSERT_PTR_NULL(ut_root(BZ, 2));
  904 }
  905 
  906 
  907 static void
  908 test_utLog(void)
  909 {
  910     ut_unit*    milliwatt = ut_scale(0.001, watt);
  911     ut_unit*    bel_1_mW = ut_log(10, milliwatt);
  912     ut_unit*    decibel_1_mW;
  913     ut_unit*    unit;
  914     char    buf[80];
  915     int     nchar;
  916 
  917     CU_ASSERT_PTR_NOT_NULL(bel_1_mW);
  918     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  919     nchar = ut_format(bel_1_mW, buf, sizeof(buf)-1, asciiSymbolDef);
  920     CU_ASSERT_TRUE_FATAL(nchar > 0);
  921     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  922     buf[nchar] = 0;
  923     CU_ASSERT_STRING_EQUAL(buf, "lg(re 0.001 kg.m2.s-3)");
  924 
  925     decibel_1_mW = ut_scale(0.1, bel_1_mW);
  926     CU_ASSERT_PTR_NOT_NULL(decibel_1_mW);
  927     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  928     nchar = ut_format(decibel_1_mW, buf, sizeof(buf)-1, asciiSymbolDef);
  929     CU_ASSERT_TRUE_FATAL(nchar > 0);
  930     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  931     buf[nchar] = 0;
  932     CU_ASSERT_STRING_EQUAL(buf, "0.1 lg(re 0.001 kg.m2.s-3)");
  933 
  934     unit = ut_log(-10, milliwatt);
  935     CU_ASSERT_PTR_NULL(unit);
  936     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  937 
  938     cubicMeter = ut_raise(meter, 3);
  939     unit = ut_scale(1e-6, meter);
  940     cubicMicron = ut_raise(unit, 3);
  941     ut_free(unit);
  942     CU_ASSERT_PTR_NOT_NULL(cubicMicron);
  943 
  944     BZ = ut_log(10, cubicMicron);
  945     CU_ASSERT_PTR_NOT_NULL(BZ);
  946     CU_ASSERT_EQUAL(ut_is_dimensionless(BZ), 1);
  947 
  948     CU_ASSERT_PTR_NULL(ut_raise(BZ, 2));
  949     CU_ASSERT_EQUAL(ut_get_status(), UT_MEANINGLESS);
  950 
  951     dBZ = ut_scale(0.1, BZ);
  952     CU_ASSERT_PTR_NOT_NULL(dBZ);
  953     CU_ASSERT_EQUAL(ut_get_status(), UT_SUCCESS);
  954     nchar = ut_format(dBZ, buf, sizeof(buf)-1, asciiSymbolDef);
  955     CU_ASSERT_TRUE_FATAL(nchar > 0);
  956     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
  957     buf[nchar] = 0;
  958     CU_ASSERT_TRUE(strcmp(buf, "0.1 lg(re 1e-18 m3)") == 0 ||
  959             strcmp(buf, "0.1 lg(re 1e-018 m3)") == 0);
  960     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("dBZ", UT_ASCII, dBZ), UT_SUCCESS);
  961     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("dBZ", UT_ASCII, dBZ), UT_SUCCESS);
  962     CU_ASSERT_EQUAL(ut_map_symbol_to_unit("dBZ", UT_ASCII, meter), UT_EXISTS);
  963     {
  964     ut_unit*    unit = ut_get_unit_by_symbol(unitSystem, "dBZ");
  965 
  966     CU_ASSERT_PTR_NOT_NULL(unit);
  967     CU_ASSERT_EQUAL(ut_compare(unit, dBZ), 0);
  968 
  969     CU_ASSERT_PTR_NULL(ut_get_unit_by_symbol(unitSystem, "DBZ"));
  970     ut_free(unit);
  971     }
  972 
  973     ut_free(milliwatt);
  974     ut_free(bel_1_mW);
  975     ut_free(decibel_1_mW);
  976 
  977     CU_ASSERT_PTR_NULL(ut_log(2, NULL));
  978     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  979     CU_ASSERT_PTR_NULL(ut_log(1, meter));
  980     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
  981 
  982     CU_ASSERT_PTR_NULL(ut_multiply(dBZ, meter));
  983     unit = ut_multiply(dBZ, radian);
  984     CU_ASSERT_PTR_NOT_NULL(unit);
  985     CU_ASSERT_EQUAL(ut_compare(unit, dBZ), 0);
  986     ut_free(unit);
  987     CU_ASSERT_PTR_NULL(ut_multiply(dBZ, dBZ));
  988 }
  989 
  990 
  991 static int
  992 areCloseFloats(
  993     float   x,
  994     float   y)
  995 {
  996     int     areClose;
  997 
  998     if (x == 0 || y == 0) {
  999     areClose = fabs(x - y) < 1000*FLT_EPSILON;
 1000     }
 1001     else {
 1002     areClose = fabs(1.0 - x / y) < 1000*FLT_EPSILON;
 1003     }
 1004 
 1005     return areClose;
 1006 }
 1007 
 1008 
 1009 static int
 1010 areCloseDoubles(
 1011     double  x,
 1012     double  y)
 1013 {
 1014     int     areClose;
 1015 
 1016     if (x == 0 || y == 0) {
 1017     areClose = fabs(x - y) < 1000*DBL_EPSILON;
 1018     }
 1019     else {
 1020     areClose = fabs(1.0 - x / y) < 1000*DBL_EPSILON;
 1021     }
 1022 
 1023     return areClose;
 1024 }
 1025 
 1026 
 1027 static void
 1028 test_utGetDimensionlessUnitOne(void)
 1029 {
 1030     CU_ASSERT_PTR_NOT_NULL(ut_get_dimensionless_unit_one(unitSystem));
 1031     CU_ASSERT_PTR_NULL(ut_get_dimensionless_unit_one(NULL));
 1032 }
 1033 
 1034 
 1035 static void
 1036 test_utGetSystem(void)
 1037 {
 1038     CU_ASSERT_PTR_NOT_NULL(ut_get_system(meter));
 1039     CU_ASSERT_PTR_NULL(ut_get_system(NULL));
 1040 }
 1041 
 1042 
 1043 static void
 1044 test_utSameSystem(void)
 1045 {
 1046     ut_system*  system;
 1047 
 1048     CU_ASSERT_EQUAL(ut_same_system(meter, kilogram), 1);
 1049 
 1050     CU_ASSERT_EQUAL(ut_same_system(NULL, kilogram), 0);
 1051     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1052     CU_ASSERT_EQUAL(ut_same_system(kilogram, NULL), 0);
 1053     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1054 
 1055     system = ut_new_system();
 1056     CU_ASSERT_PTR_NOT_NULL(system);
 1057 
 1058     CU_ASSERT_EQUAL(ut_same_system(meter, ut_get_dimensionless_unit_one(system)), 0);
 1059 
 1060     ut_free_system(system);
 1061 }
 1062 
 1063 
 1064 static void
 1065 test_utIsDimensionless(void)
 1066 {
 1067     ut_unit*    unit;
 1068 
 1069     CU_ASSERT_EQUAL(ut_is_dimensionless(meter), 0);
 1070     CU_ASSERT_EQUAL(ut_is_dimensionless(radian), 1);
 1071     CU_ASSERT_EQUAL(ut_is_dimensionless(secondsSinceTheEpoch), 0);
 1072     CU_ASSERT_EQUAL(ut_is_dimensionless(NULL), 0);
 1073     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1074 
 1075     unit = ut_raise(radian, 2);
 1076     CU_ASSERT_EQUAL(ut_is_dimensionless(unit), 1);
 1077     ut_free(unit);
 1078 }
 1079 
 1080 
 1081 static void
 1082 test_utClone(void)
 1083 {
 1084     ut_unit*    unit;
 1085 
 1086     unit = ut_clone(secondsSinceTheEpoch);
 1087     CU_ASSERT_PTR_NOT_NULL(unit);
 1088     CU_ASSERT_EQUAL(ut_are_convertible(unit, secondsSinceTheEpoch), 1);
 1089     ut_free(unit);
 1090 
 1091     CU_ASSERT_PTR_NULL(ut_clone(NULL));
 1092     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1093 }
 1094 
 1095 
 1096 static void
 1097 test_utAreConvertible(void)
 1098 {
 1099     ut_unit*    unit;
 1100 
 1101     CU_ASSERT_EQUAL(ut_are_convertible(meter, meter), 1);
 1102     CU_ASSERT_EQUAL(ut_are_convertible(radian, radian), 1);
 1103     CU_ASSERT_EQUAL(ut_are_convertible(radian, meter), 0);
 1104     CU_ASSERT_EQUAL(ut_are_convertible(cubicMicron, cubicMicron), 1);
 1105     CU_ASSERT_EQUAL(ut_are_convertible(cubicMicron, cubicMeter), 1);
 1106     CU_ASSERT_EQUAL(ut_are_convertible(watt, watt), 1);
 1107     CU_ASSERT_EQUAL(ut_are_convertible(watt, cubicMicron), 0);
 1108     CU_ASSERT_EQUAL(ut_are_convertible(cubicMicron, watt), 0);
 1109     CU_ASSERT_EQUAL(ut_are_convertible(secondsSinceTheEpoch,
 1110     secondsSinceTheEpoch), 1);
 1111     CU_ASSERT_EQUAL(ut_are_convertible(secondsSinceTheEpoch, second), 0);
 1112     CU_ASSERT_EQUAL(ut_are_convertible(joulePerKilogram,
 1113     meterSquaredPerSecondSquared), 1);
 1114     CU_ASSERT_EQUAL(ut_are_convertible(joulePerKilogram,
 1115     meterPerSecondSquared), 0);
 1116 
 1117     unit = ut_raise(radian, 2);
 1118     CU_ASSERT_EQUAL(ut_are_convertible(radian, unit), 1);
 1119     ut_free(unit);
 1120 
 1121     CU_ASSERT_EQUAL(ut_are_convertible(NULL, meter), 0);
 1122     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1123 }
 1124 
 1125 
 1126 static void
 1127 test_utGetConverter(void)
 1128 {
 1129     cv_converter*   converter = ut_get_converter(meter, meter);
 1130     double      doubles[2];
 1131     float       floats[2];
 1132 
 1133     CU_ASSERT_PTR_NOT_NULL(converter);
 1134     CU_ASSERT_EQUAL(cv_convert_double(converter, 1.0), 1.0);
 1135     floats[0] = 1; floats[1] = 2;
 1136     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1137     CU_ASSERT_EQUAL(floats[0], 1);
 1138     CU_ASSERT_EQUAL(floats[1], 2);
 1139     doubles[0] = 1; doubles[1] = 2;
 1140     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1141     CU_ASSERT_EQUAL(doubles[0], 1);
 1142     CU_ASSERT_EQUAL(doubles[1], 2);
 1143     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1144     CU_ASSERT_EQUAL(floats[1], 1);
 1145     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1146     doubles+1);
 1147     CU_ASSERT_EQUAL(doubles[1], 1);
 1148     floats[0] = 1; floats[1] = 2;
 1149     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1150     CU_ASSERT_EQUAL(floats[0], 2);
 1151     doubles[0] = 1; doubles[1] = 2;
 1152     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1153     doubles);
 1154     CU_ASSERT_EQUAL(doubles[0], 2);
 1155     cv_free(converter);
 1156 
 1157     converter = ut_get_converter(radian, radian);
 1158     CU_ASSERT_PTR_NOT_NULL(converter);
 1159     CU_ASSERT_EQUAL(cv_convert_double(converter, 1.0), 1.0);
 1160     cv_free(converter);
 1161 
 1162     converter = ut_get_converter(meter, radian);
 1163     CU_ASSERT_PTR_NULL(converter);
 1164     converter = ut_get_converter(meter, kelvin);
 1165     CU_ASSERT_PTR_NULL(converter);
 1166     converter = ut_get_converter(meter, celsius);
 1167     CU_ASSERT_PTR_NULL(converter);
 1168     converter = ut_get_converter(meter, fahrenheit);
 1169     CU_ASSERT_PTR_NULL(converter);
 1170     converter = ut_get_converter(meter, dBZ);
 1171     CU_ASSERT_PTR_NULL(converter);
 1172     converter = ut_get_converter(dBZ, radian);
 1173     CU_ASSERT_PTR_NULL(converter);
 1174 
 1175     converter = ut_get_converter(kilometer, kilometer);
 1176     CU_ASSERT_PTR_NOT_NULL(converter);
 1177     CU_ASSERT_EQUAL(cv_convert_double(converter, 1.0), 1.0);
 1178     cv_free(converter);
 1179 
 1180     converter = ut_get_converter(meter, kilometer);
 1181     CU_ASSERT_PTR_NOT_NULL(converter);
 1182     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1000.0), 1.0));
 1183     floats[0] = 0; floats[1] = 1000;
 1184     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1185     CU_ASSERT_EQUAL(floats[0], 0);
 1186     CU_ASSERT_EQUAL(floats[1], 1);
 1187     doubles[0] = 0; doubles[1] = 1000;
 1188     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1189     CU_ASSERT_EQUAL(doubles[0], 0);
 1190     CU_ASSERT_EQUAL(doubles[1], 1);
 1191     floats[0] = 0; floats[1] = 1000;
 1192     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1193     CU_ASSERT_EQUAL(floats[1], 0);
 1194     doubles[0] = 0; doubles[1] = 1000;
 1195     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1196     doubles+1);
 1197     CU_ASSERT_EQUAL(doubles[1], 0);
 1198     floats[0] = 0; floats[1] = 1000;
 1199     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1200     CU_ASSERT_EQUAL(floats[0], 1);
 1201     doubles[0] = 0; doubles[1] = 1000;
 1202     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1203     doubles);
 1204     CU_ASSERT_EQUAL(doubles[0], 1);
 1205     cv_free(converter);
 1206 
 1207     converter = ut_get_converter(kilometer, meter);
 1208     CU_ASSERT_PTR_NOT_NULL(converter);
 1209     CU_ASSERT_EQUAL(cv_convert_double(converter, 1.0), 1000.0);
 1210     floats[0] = 0; floats[1] = 1;
 1211     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1212     CU_ASSERT_EQUAL(floats[0], 0);
 1213     CU_ASSERT_EQUAL(floats[1], 1000);
 1214     doubles[0] = 0; doubles[1] = 1;
 1215     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1216     CU_ASSERT_EQUAL(doubles[0], 0);
 1217     CU_ASSERT_EQUAL(doubles[1], 1000);
 1218     floats[0] = 0; floats[1] = 1;
 1219     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1220     CU_ASSERT_EQUAL(floats[1], 0);
 1221     doubles[0] = 0; doubles[1] = 1;
 1222     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1223     doubles+1);
 1224     CU_ASSERT_EQUAL(doubles[1], 0);
 1225     floats[0] = 0; floats[1] = 1;
 1226     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1227     CU_ASSERT_EQUAL(floats[0], 1000);
 1228     doubles[0] = 0; doubles[1] = 1;
 1229     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1230     doubles);
 1231     CU_ASSERT_EQUAL(doubles[0], 1000);
 1232     cv_free(converter);
 1233 
 1234     converter = ut_get_converter(kelvin, celsius);
 1235     CU_ASSERT_PTR_NOT_NULL(converter);
 1236     CU_ASSERT_EQUAL(cv_convert_double(converter, 273.15), 0.0);
 1237     floats[0] = 0; floats[1] = 273.15;
 1238     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1239     CU_ASSERT_TRUE(areCloseFloats(floats[0], -273.15));
 1240     CU_ASSERT_TRUE(areCloseFloats(floats[1], 0));
 1241     doubles[0] = 0; doubles[1] = 273.15;
 1242     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1243     CU_ASSERT_EQUAL(doubles[0], -273.15);
 1244     CU_ASSERT_EQUAL(doubles[1], 0);
 1245     floats[0] = 0; floats[1] = 273.15;
 1246     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1247     CU_ASSERT_TRUE(areCloseFloats(floats[1], -273.15));
 1248     doubles[0] = 0; doubles[1] = 273.15;
 1249     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1250     doubles+1);
 1251     CU_ASSERT_EQUAL(doubles[1], -273.15);
 1252     floats[0] = 0; floats[1] = 273.15;
 1253     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1254     CU_ASSERT_TRUE(areCloseFloats(floats[0], 0));
 1255     doubles[0] = 0; doubles[1] = 273.15;
 1256     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1257     doubles);
 1258     CU_ASSERT_EQUAL(doubles[0], 0);
 1259     cv_free(converter);
 1260 
 1261     converter = ut_get_converter(celsius, kelvin);
 1262     CU_ASSERT_PTR_NOT_NULL(converter);
 1263     CU_ASSERT_EQUAL(cv_convert_double(converter, 0.0), 273.15);
 1264     floats[0] = 0; floats[1] = -273.15;
 1265     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1266     CU_ASSERT_TRUE(areCloseFloats(floats[0], 273.15));
 1267     CU_ASSERT_TRUE(areCloseFloats(floats[1], 0));
 1268     doubles[0] = 0; doubles[1] = -273.15;
 1269     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1270     CU_ASSERT_EQUAL(doubles[0], 273.15);
 1271     CU_ASSERT_EQUAL(doubles[1], 0);
 1272     floats[0] = 0; floats[1] = -273.15;
 1273     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1274     CU_ASSERT_TRUE(areCloseFloats(floats[1], 273.15));
 1275     doubles[0] = 0; doubles[1] = -273.15;
 1276     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1277     doubles+1);
 1278     CU_ASSERT_EQUAL(doubles[1], 273.15);
 1279     floats[0] = 0; floats[1] = -273.15;
 1280     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1281     CU_ASSERT_TRUE(areCloseFloats(floats[0], 0));
 1282     doubles[0] = 0; doubles[1] = -273.15;
 1283     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1284     doubles);
 1285     CU_ASSERT_EQUAL(doubles[0], 0);
 1286     cv_free(converter);
 1287 
 1288     converter = ut_get_converter(celsius, fahrenheit);
 1289     CU_ASSERT_PTR_NOT_NULL(converter);
 1290     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 0.0), 32));
 1291     floats[0] = 0; floats[1] = 100;
 1292     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1293     CU_ASSERT_TRUE(areCloseFloats(floats[0], 32));
 1294     CU_ASSERT_TRUE(areCloseFloats(floats[1], 212));
 1295     doubles[0] = 0; doubles[1] = 100;
 1296     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1297     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 32));
 1298     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 212));
 1299     floats[0] = 0; floats[1] = 100;
 1300     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1301     CU_ASSERT_TRUE(areCloseFloats(floats[1], 32));
 1302     doubles[0] = 0; doubles[1] = 100;
 1303     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1304     doubles+1);
 1305     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 32));
 1306     floats[0] = 0; floats[1] = 100;
 1307     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1308     CU_ASSERT_TRUE(areCloseFloats(floats[0], 212));
 1309     doubles[0] = 0; doubles[1] = 100;
 1310     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1311     doubles);
 1312     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 212));
 1313     cv_free(converter);
 1314 
 1315     converter = ut_get_converter(fahrenheit, celsius);
 1316     CU_ASSERT_PTR_NOT_NULL(converter);
 1317     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 32.0), 0.0));
 1318     floats[0] = 32; floats[1] = 212;
 1319     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1320     CU_ASSERT_TRUE(areCloseFloats(floats[0], 0));
 1321     CU_ASSERT_TRUE(areCloseFloats(floats[1], 100));
 1322     doubles[0] = 32; doubles[1] = 212;
 1323     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1324     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 0));
 1325     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 100));
 1326     floats[0] = 32; floats[1] = 212;
 1327     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1328     CU_ASSERT_TRUE(areCloseFloats(floats[1], 0));
 1329     doubles[0] = 32; doubles[1] = 212;
 1330     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1331     doubles+1);
 1332     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 0));
 1333     floats[0] = 32; floats[1] = 212;
 1334     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1335     CU_ASSERT_TRUE(areCloseFloats(floats[0], 100));
 1336     doubles[0] = 32; doubles[1] = 212;
 1337     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1338     doubles);
 1339     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 100));
 1340     cv_free(converter);
 1341 
 1342     converter = ut_get_converter(cubicMeter, dBZ);
 1343     CU_ASSERT_PTR_NOT_NULL(converter);
 1344     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1e-18), 0.0));
 1345     cv_free(converter);
 1346 
 1347     converter = ut_get_converter(cubicMicron, dBZ);
 1348     CU_ASSERT_PTR_NOT_NULL(converter);
 1349     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1000), 30.0));
 1350     floats[0] = 10; floats[1] = 1000;
 1351     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1352     CU_ASSERT_TRUE(areCloseFloats(floats[0], 10));
 1353     CU_ASSERT_TRUE(areCloseFloats(floats[1], 30));
 1354     doubles[0] = 10; doubles[1] = 1000;
 1355     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1356     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 10));
 1357     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 30));
 1358     floats[0] = 10; floats[1] = 1000;
 1359     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1360     CU_ASSERT_TRUE(areCloseFloats(floats[1], 10));
 1361     doubles[0] = 10; doubles[1] = 1000;
 1362     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1363     doubles+1);
 1364     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 10));
 1365     floats[0] = 10; floats[1] = 1000;
 1366     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1367     CU_ASSERT_TRUE(areCloseFloats(floats[0], 30));
 1368     doubles[0] = 10; doubles[1] = 1000;
 1369     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1370     doubles);
 1371     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 30));
 1372     cv_free(converter);
 1373 
 1374     converter = ut_get_converter(dBZ, cubicMicron);
 1375     CU_ASSERT_PTR_NOT_NULL(converter);
 1376     CU_ASSERT_TRUE(areCloseFloats(cv_convert_float(converter, 10), 10.0));
 1377     CU_ASSERT_TRUE(areCloseFloats(cv_convert_float(converter, 30), 1000.0));
 1378     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 10), 10.0));
 1379     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 30), 1000.0));
 1380     floats[0] = 10; floats[1] = 30;
 1381     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1382     CU_ASSERT_TRUE(areCloseFloats(floats[0], 10));
 1383     CU_ASSERT_TRUE(areCloseFloats(floats[1], 1000));
 1384     doubles[0] = 10; doubles[1] = 30;
 1385     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1386     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 10));
 1387     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 1000));
 1388     floats[0] = 10; floats[1] = 30;
 1389     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1390     CU_ASSERT_TRUE(areCloseFloats(floats[1], 10));
 1391     doubles[0] = 10; doubles[1] = 30;
 1392     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1393     doubles+1);
 1394     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 10));
 1395     floats[0] = 10; floats[1] = 30;
 1396     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1397     CU_ASSERT_TRUE(areCloseFloats(floats[0], 1000));
 1398     doubles[0] = 10; doubles[1] = 30;
 1399     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1400     doubles);
 1401     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 1000));
 1402     cv_free(converter);
 1403 
 1404     converter = ut_get_converter(second, hertz);
 1405     CU_ASSERT_PTR_NOT_NULL(converter);
 1406     CU_ASSERT_TRUE(areCloseFloats(cv_convert_float(converter, 1.0), 1.0));
 1407     CU_ASSERT_TRUE(areCloseFloats(cv_convert_float(converter, 5.0), 1/5.0));
 1408     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1.0), 1.0));
 1409     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 5.0), 1/5.0));
 1410     floats[0] = 1; floats[1] = 5;
 1411     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1412     CU_ASSERT_TRUE(areCloseFloats(floats[0], 1.0));
 1413     CU_ASSERT_TRUE(areCloseFloats(floats[1], 1.0/5));
 1414     doubles[0] = 1; doubles[1] = 5;
 1415     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1416     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 1));
 1417     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 1.0/5));
 1418     cv_free(converter);
 1419 
 1420     converter = ut_get_converter(second, megahertz);
 1421     CU_ASSERT_PTR_NOT_NULL(converter);
 1422     CU_ASSERT_TRUE(areCloseFloats(cv_convert_float(converter, 1), 1e-6));
 1423     CU_ASSERT_TRUE(areCloseFloats(cv_convert_float(converter, 1e-6), 1.0));
 1424     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1), 1e-6));
 1425     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1e-6), 1.0));
 1426     floats[0] = 1; floats[1] = 1e-6;
 1427     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1428     CU_ASSERT_TRUE(areCloseFloats(floats[0], 1e-6));
 1429     CU_ASSERT_TRUE(areCloseFloats(floats[1], 1));
 1430     doubles[0] = 1; doubles[1] = 1e-6;
 1431     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1432     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 1e-6));
 1433     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 1));
 1434     cv_free(converter);
 1435 
 1436     converter = ut_get_converter(secondsSinceTheEpoch, minutesSinceTheMillenium);
 1437     CU_ASSERT_PTR_NOT_NULL(converter);
 1438     cv_free(converter);
 1439 
 1440     CU_ASSERT_PTR_NULL(ut_get_converter(NULL, meter));
 1441     CU_ASSERT_PTR_NULL(ut_get_converter(meter, NULL));
 1442 }
 1443 
 1444 
 1445 static void
 1446 test_utOffsetByTime(void)
 1447 {
 1448     char        buf[80];
 1449     int         nchar;
 1450     cv_converter*   converter;
 1451     ut_unit*        day;
 1452     ut_unit*        daysSinceTheEpoch;
 1453     double      doubles[2];
 1454     float       floats[2];
 1455 
 1456     secondsSinceTheEpoch =
 1457         ut_offset_by_time(second, ut_encode_time(1970, 1, 1, 0, 0, 0));
 1458     CU_ASSERT_PTR_NOT_NULL(secondsSinceTheEpoch);
 1459     nchar = ut_format(secondsSinceTheEpoch, buf, sizeof(buf)-1, asciiSymbolDef);
 1460     CU_ASSERT_TRUE_FATAL(nchar > 0);
 1461     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
 1462     buf[nchar] = 0;
 1463     CU_ASSERT_STRING_EQUAL(buf, "s @ 19700101T000000.0000000 UTC");
 1464     if (strcmp(buf, "s @ 19700101T000000.0000000 UTC"))
 1465         fprintf(stderr, "buf=%s\n", buf);
 1466 
 1467     minutesSinceTheMillenium =
 1468         ut_offset_by_time(minute, ut_encode_time(2001, 1, 1, 0, 0, 0));
 1469     CU_ASSERT_PTR_NOT_NULL(minutesSinceTheMillenium);
 1470 
 1471     nchar = ut_format(secondsSinceTheEpoch, buf, sizeof(buf)-1, asciiNameDef);
 1472     CU_ASSERT_TRUE_FATAL(nchar > 0);
 1473     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
 1474     buf[nchar] = 0;
 1475     CU_ASSERT_STRING_EQUAL(buf, "second since 1970-01-01 00:00:00.0000000 UTC");
 1476 
 1477     converter = ut_get_converter(secondsSinceTheEpoch, secondsSinceTheEpoch);
 1478     CU_ASSERT_PTR_NOT_NULL(converter);
 1479     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1000), 1000));
 1480     floats[0] = 0; floats[1] = 1000;
 1481     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1482     CU_ASSERT_TRUE(areCloseFloats(floats[0], 0));
 1483     CU_ASSERT_TRUE(areCloseFloats(floats[1], 1000));
 1484     doubles[0] = 0; doubles[1] = 1000;
 1485     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1486     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 0));
 1487     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 1000));
 1488     floats[0] = 0; floats[1] = 1000;
 1489     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1490     CU_ASSERT_TRUE(areCloseFloats(floats[1], 0));
 1491     doubles[0] = 0; doubles[1] = 1000;
 1492     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1493     doubles+1);
 1494     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 0));
 1495     floats[0] = 0; floats[1] = 1000;
 1496     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1497     CU_ASSERT_TRUE(areCloseFloats(floats[0], 1000));
 1498     doubles[0] = 0; doubles[1] = 1000;
 1499     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1500     doubles);
 1501     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 1000));
 1502     cv_free(converter);
 1503 
 1504     day = ut_scale(86400, second);
 1505     CU_ASSERT_PTR_NOT_NULL_FATAL(day);
 1506     daysSinceTheEpoch = ut_offset_by_time(day, ut_encode_time(1970, 1, 1, 0, 0, 0));
 1507     ut_free(day);
 1508     CU_ASSERT_PTR_NOT_NULL_FATAL(daysSinceTheEpoch);
 1509     nchar = ut_format(daysSinceTheEpoch, buf, sizeof(buf)-1, asciiSymbolDef);
 1510     CU_ASSERT_TRUE_FATAL(nchar > 0);
 1511     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
 1512     buf[nchar] = 0;
 1513     CU_ASSERT_STRING_EQUAL(buf, "(86400 s) @ 19700101T000000.0000000 UTC");
 1514 
 1515     converter = ut_get_converter(secondsSinceTheEpoch, daysSinceTheEpoch);
 1516     CU_ASSERT_PTR_NOT_NULL(converter);
 1517     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 86400), 1));
 1518     floats[0] = 0; floats[1] = 86400;
 1519     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1520     CU_ASSERT_TRUE(areCloseFloats(floats[0], 0));
 1521     CU_ASSERT_TRUE(areCloseFloats(floats[1], 1));
 1522     doubles[0] = 0; doubles[1] = 86400;
 1523     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1524     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 0));
 1525     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 1));
 1526     floats[0] = 0; floats[1] = 86400;
 1527     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1528     CU_ASSERT_TRUE(areCloseFloats(floats[1], 0));
 1529     doubles[0] = 0; doubles[1] = 86400;
 1530     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1531     doubles+1);
 1532     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 0));
 1533     floats[0] = 0; floats[1] = 86400;
 1534     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1535     CU_ASSERT_TRUE(areCloseFloats(floats[0], 1));
 1536     doubles[0] = 0; doubles[1] = 86400;
 1537     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1538     doubles);
 1539     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 1));
 1540     cv_free(converter);
 1541 
 1542     converter = ut_get_converter(daysSinceTheEpoch, secondsSinceTheEpoch);
 1543     CU_ASSERT_PTR_NOT_NULL(converter);
 1544     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1), 86400));
 1545     floats[0] = 0; floats[1] = 1;
 1546     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 2, floats), floats);
 1547     CU_ASSERT_TRUE(areCloseFloats(floats[0], 0));
 1548     CU_ASSERT_TRUE(areCloseFloats(floats[1], 86400));
 1549     doubles[0] = 0; doubles[1] = 1;
 1550     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 2, doubles), doubles);
 1551     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 0));
 1552     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 86400));
 1553     floats[0] = 0; floats[1] = 1;
 1554     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats, 1, floats+1), floats+1);
 1555     CU_ASSERT_TRUE(areCloseFloats(floats[1], 0));
 1556     doubles[0] = 0; doubles[1] = 1;
 1557     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles, 1, doubles+1),
 1558     doubles+1);
 1559     CU_ASSERT_TRUE(areCloseDoubles(doubles[1], 0));
 1560     floats[0] = 0; floats[1] = 1;
 1561     CU_ASSERT_EQUAL(cv_convert_floats(converter, floats+1, 1, floats), floats);
 1562     CU_ASSERT_TRUE(areCloseFloats(floats[0], 86400));
 1563     doubles[0] = 0; doubles[1] = 1;
 1564     CU_ASSERT_EQUAL(cv_convert_doubles(converter, doubles+1, 1, doubles),
 1565     doubles);
 1566     CU_ASSERT_TRUE(areCloseDoubles(doubles[0], 86400));
 1567     cv_free(converter);
 1568 
 1569     ut_free(daysSinceTheEpoch);
 1570 
 1571     {
 1572         /*
 1573          * "Naked hour" test
 1574          */
 1575         ut_unit* unit = ut_parse(unitSystem,
 1576                 "second since 1970-01-01 0", UT_ASCII);
 1577         CU_ASSERT_PTR_NOT_NULL(unit);
 1578         if (unit) {
 1579             converter = ut_get_converter(unit, secondsSinceTheEpoch);
 1580             CU_ASSERT_PTR_NOT_NULL(converter);
 1581             if (converter) {
 1582                 CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 0), 0));
 1583                 cv_free(converter);
 1584             }
 1585             ut_free(unit);
 1586         }
 1587 
 1588         unit = ut_parse(unitSystem,
 1589                 "second since 1970-01-01 0+1", UT_ASCII);
 1590         CU_ASSERT_PTR_NOT_NULL(unit);
 1591         if (unit) {
 1592             converter = ut_get_converter(unit, secondsSinceTheEpoch);
 1593             CU_ASSERT_PTR_NOT_NULL(converter);
 1594             if (converter) {
 1595                 CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 0), -3600));
 1596                 cv_free(converter);
 1597             }
 1598             ut_free(unit);
 1599         }
 1600 
 1601         unit = ut_parse(unitSystem,
 1602                 "second since 1970-01-01 0 -1", UT_ASCII);
 1603         CU_ASSERT_PTR_NOT_NULL(unit);
 1604         if (unit) {
 1605             converter = ut_get_converter(unit, secondsSinceTheEpoch);
 1606             CU_ASSERT_PTR_NOT_NULL(converter);
 1607             if (converter) {
 1608                 CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 0), 3600));
 1609                 cv_free(converter);
 1610             }
 1611             ut_free(unit);
 1612         }
 1613     }
 1614 
 1615     CU_ASSERT_PTR_NULL(ut_offset_by_time(NULL, ut_encode_time(0, 0, 0, 0, 0, 0)));
 1616     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1617 }
 1618 
 1619 
 1620 static void
 1621 test_ut_decode_time(void)
 1622 {
 1623     double      timeval = ut_encode_time(2001, 1, 1, 0, 0, 0);
 1624     int         year1, month1, day1, hour1, minute1;
 1625     int         year2, month2, day2, hour2, minute2;
 1626     double      second1, resolution1;
 1627     double      second2, resolution2;
 1628     ut_unit*    unit;
 1629 
 1630     ut_decode_time(timeval, &year1, &month1, &day1, &hour1, &minute1,
 1631         &second1, &resolution1);
 1632     unit = ut_parse(unitSystem, "second since 2010-01-11T09:08:10Z", UT_ASCII);
 1633     CU_ASSERT_PTR_NOT_NULL(unit);
 1634     ut_free(unit);
 1635     ut_decode_time(timeval, &year2, &month2, &day2, &hour2, &minute2,
 1636         &second2, &resolution2);
 1637     CU_ASSERT_EQUAL(year1, year2);
 1638     CU_ASSERT_EQUAL(month1, month2);
 1639     CU_ASSERT_EQUAL(day1, day2);
 1640     CU_ASSERT_EQUAL(hour1, hour2);
 1641     CU_ASSERT_EQUAL(minute1, minute2);
 1642     CU_ASSERT_EQUAL(second1, second2);
 1643     CU_ASSERT_EQUAL(resolution1, resolution2);
 1644 
 1645     /*
 1646      * User reported getting 60 seconds back from ut_decode_time() for a time
 1647      * value of -3240.0.
 1648      */
 1649     //timeval = ut_encode_time(2000, 12, 31, 23, 5, 60);
 1650     timeval = -3240.0;
 1651     ut_decode_time(timeval, &year2, &month2, &day2, &hour2, &minute2,
 1652         &second2, &resolution2);
 1653     CU_ASSERT_EQUAL(year2, 2000);
 1654     CU_ASSERT_EQUAL(month2, 12);
 1655     CU_ASSERT_EQUAL(day2, 31);
 1656     CU_ASSERT_EQUAL(hour2, 23);
 1657     CU_ASSERT_EQUAL(minute2, 6);
 1658     CU_ASSERT_EQUAL(second2, 0);
 1659 }
 1660 
 1661 
 1662 static void
 1663 test_utSetEncoding(void)
 1664 {
 1665     char        buf[80];
 1666     int         nchar;
 1667 
 1668     nchar = ut_format(watt, buf, sizeof(buf)-1, asciiSymbolDef);
 1669     CU_ASSERT_TRUE_FATAL(nchar > 0);
 1670     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
 1671     buf[nchar] = 0;
 1672     CU_ASSERT_STRING_EQUAL(buf, "kg.m2.s-3");
 1673 
 1674     nchar = ut_format(watt, buf, sizeof(buf)-1, latin1SymbolDef);
 1675     CU_ASSERT_TRUE_FATAL(nchar > 0);
 1676     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
 1677     buf[nchar] = 0;
 1678     CU_ASSERT_STRING_EQUAL(buf, "m\xb2\xb7kg/s\xb3");
 1679 
 1680     nchar = ut_format(watt, buf, sizeof(buf)-1, utf8SymbolDef);
 1681     CU_ASSERT_TRUE_FATAL(nchar > 0);
 1682     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
 1683     buf[nchar] = 0;
 1684     CU_ASSERT_STRING_EQUAL(buf,
 1685     "kg\xc2\xb7m\xc2\xb2\xc2\xb7s\xe2\x81\xbb\xc2\xb3");
 1686 
 1687     nchar = ut_format(wattSquared, buf, sizeof(buf)-1, utf8SymbolDef);
 1688     CU_ASSERT_TRUE_FATAL(nchar > 0);
 1689     CU_ASSERT_TRUE_FATAL(nchar < sizeof(buf));
 1690     buf[nchar] = 0;
 1691     CU_ASSERT_STRING_EQUAL(buf,
 1692     "kg\xc2\xb2\xc2\xb7m\xe2\x81\xb4\xc2\xb7s\xe2\x81\xbb\xe2\x81\xb6");
 1693         /* kg2.m4.s-6 */
 1694 }
 1695 
 1696 
 1697 static void
 1698 test_utCompare(void)
 1699 {
 1700     CU_ASSERT_NOT_EQUAL(ut_compare(kilogram, meter), 0);
 1701     CU_ASSERT_NOT_EQUAL(ut_compare(meter, radian), 0);
 1702     CU_ASSERT_NOT_EQUAL(ut_compare(radian, kelvin), 0);
 1703     CU_ASSERT_NOT_EQUAL(ut_compare(kelvin, second), 0);
 1704     CU_ASSERT_NOT_EQUAL(ut_compare(second, minute), 0);
 1705     CU_ASSERT_NOT_EQUAL(ut_compare(minute, kilometer), 0);
 1706     CU_ASSERT_NOT_EQUAL(ut_compare(kilometer, rankine), 0);
 1707     CU_ASSERT_NOT_EQUAL(ut_compare(rankine, celsius), 0);
 1708     CU_ASSERT_NOT_EQUAL(ut_compare(celsius, fahrenheit), 0);
 1709     CU_ASSERT_NOT_EQUAL(ut_compare(fahrenheit, watt), 0);
 1710     CU_ASSERT_NOT_EQUAL(ut_compare(watt, cubicMicron), 0);
 1711     CU_ASSERT_NOT_EQUAL(ut_compare(BZ, cubicMicron), 0);
 1712     CU_ASSERT_NOT_EQUAL(ut_compare(cubicMicron, dBZ), 0);
 1713     CU_ASSERT_NOT_EQUAL(ut_compare(dBZ, secondsSinceTheEpoch), 0);
 1714     CU_ASSERT_NOT_EQUAL(ut_compare(secondsSinceTheEpoch, hertz), 0);
 1715     CU_ASSERT_NOT_EQUAL(ut_compare(hertz, megahertz), 0);
 1716     CU_ASSERT_NOT_EQUAL(ut_compare(megahertz, kilogram), 0);
 1717     CU_ASSERT_NOT_EQUAL(ut_compare(dBZ, meter), 0);
 1718 
 1719     CU_ASSERT_EQUAL(ut_compare(NULL, meter), -1);
 1720     CU_ASSERT_EQUAL(ut_compare(NULL, NULL), 0);
 1721     CU_ASSERT_EQUAL(ut_compare(meter, NULL), 1);
 1722 }
 1723 
 1724 
 1725 static void
 1726 test_parsing(void)
 1727 {
 1728     ut_unit*    unit;
 1729     char*   spec;
 1730 
 1731     spec = "34 quatloos";
 1732     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1733     CU_ASSERT_PTR_NULL(unit);
 1734     CU_ASSERT_EQUAL(ut_get_status(), UT_UNKNOWN);
 1735 
 1736     spec = "$&/^";
 1737     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1738     CU_ASSERT_PTR_NULL(unit);
 1739     CU_ASSERT_EQUAL(ut_get_status(), UT_UNKNOWN);
 1740 
 1741     unit = ut_parse(unitSystem, NULL, UT_ASCII);
 1742     CU_ASSERT_PTR_NULL(unit);
 1743     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1744 
 1745     unit = ut_parse(NULL, "kg", UT_ASCII);
 1746     CU_ASSERT_PTR_NULL(unit);
 1747     CU_ASSERT_EQUAL(ut_get_status(), UT_BAD_ARG);
 1748 
 1749     spec = "m";
 1750     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1751     CU_ASSERT_PTR_NOT_NULL(unit);
 1752     CU_ASSERT_EQUAL(ut_compare(unit, meter), 0);
 1753     ut_free(unit);
 1754 
 1755     spec = "kg.m";
 1756     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1757     CU_ASSERT_PTR_NOT_NULL(unit);
 1758     ut_free(unit);
 1759 
 1760     spec = "kg m";
 1761     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1762     CU_ASSERT_PTR_NOT_NULL(unit);
 1763     ut_free(unit);
 1764 
 1765     spec = "1/s";
 1766     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1767     CU_ASSERT_PTR_NOT_NULL(unit);
 1768     CU_ASSERT_EQUAL(ut_compare(unit, hertz), 0);
 1769     ut_free(unit);
 1770 
 1771     spec = "kg.m2.s-3";
 1772     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1773     CU_ASSERT_PTR_NOT_NULL(unit);
 1774     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1775     ut_free(unit);
 1776 
 1777     spec = "kg.m2/s3";
 1778     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1779     CU_ASSERT_PTR_NOT_NULL(unit);
 1780     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1781     ut_free(unit);
 1782 
 1783     spec = "s-3.m2.kg";
 1784     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1785     CU_ASSERT_PTR_NOT_NULL(unit);
 1786     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1787     ut_free(unit);
 1788 
 1789     spec = "(kg.m2/s3)";
 1790     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1791     CU_ASSERT_PTR_NOT_NULL(unit);
 1792     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1793     ut_free(unit);
 1794 
 1795     spec = "(kg.m2/s3)^1";
 1796     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1797     CU_ASSERT_PTR_NOT_NULL(unit);
 1798     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1799     ut_free(unit);
 1800 
 1801     spec = "kg.(m/s)^2.s-1";
 1802     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1803     CU_ASSERT_PTR_NOT_NULL(unit);
 1804     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1805     ut_free(unit);
 1806 
 1807     spec = "1000 m";
 1808     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1809     CU_ASSERT_PTR_NOT_NULL(unit);
 1810     CU_ASSERT_EQUAL(ut_compare(unit, kilometer), 0);
 1811     ut_free(unit);
 1812 
 1813     spec = "(1000)(m)";
 1814     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1815     CU_ASSERT_PTR_NOT_NULL(unit);
 1816     CU_ASSERT_EQUAL(ut_compare(unit, kilometer), 0);
 1817     ut_free(unit);
 1818 
 1819     spec = "1/2";
 1820     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1821     CU_ASSERT_PTR_NOT_NULL(unit);
 1822     CU_ASSERT_EQUAL(ut_are_convertible(unit,
 1823             ut_get_dimensionless_unit_one(unitSystem)), 1);
 1824     ut_free(unit);
 1825 
 1826     spec = "1/(2)";
 1827     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1828     CU_ASSERT_PTR_NOT_NULL(unit);
 1829     CU_ASSERT_EQUAL(ut_are_convertible(unit,
 1830             ut_get_dimensionless_unit_one(unitSystem)), 1);
 1831     ut_free(unit);
 1832 
 1833     spec = "1/m";
 1834     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1835     CU_ASSERT_PTR_NOT_NULL(unit);
 1836     CU_ASSERT_EQUAL(ut_are_convertible(unit, meter), 1);
 1837     ut_free(unit);
 1838 
 1839     spec = "1/(2 m)";
 1840     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1841     CU_ASSERT_PTR_NOT_NULL(unit);
 1842     CU_ASSERT_EQUAL(ut_are_convertible(unit, meter), 1);
 1843     ut_free(unit);
 1844 
 1845     spec = "(K/1.8) @ 459.67";
 1846     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1847     CU_ASSERT_EQUAL(ut_are_convertible(unit, fahrenheit), 1);
 1848     ut_free(unit);
 1849 
 1850     spec = "METER";
 1851     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1852     CU_ASSERT_PTR_NOT_NULL(unit);
 1853     CU_ASSERT_EQUAL(ut_compare(unit, meter), 0);
 1854     ut_free(unit);
 1855 
 1856     spec = "s @ 19700101T000000";
 1857     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1858     CU_ASSERT_PTR_NOT_NULL(unit);
 1859     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1860     ut_free(unit);
 1861 
 1862     spec = "s@19700101T000000 UTC";
 1863     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1864     CU_ASSERT_PTR_NOT_NULL(unit);
 1865     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1866     ut_free(unit);
 1867 
 1868     spec = "s@19700101T000000Z";
 1869     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1870     CU_ASSERT_PTR_NOT_NULL(unit);
 1871     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1872     ut_free(unit);
 1873 
 1874     spec = "s@19700101T000000 Z";
 1875     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1876     CU_ASSERT_PTR_NOT_NULL(unit);
 1877     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1878     ut_free(unit);
 1879 
 1880     spec = "s @ 1970-01-01 00:00:00";
 1881     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1882     CU_ASSERT_PTR_NOT_NULL(unit);
 1883     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1884     ut_free(unit);
 1885 
 1886     spec = "s @ 1970-01-01T00:00:00";
 1887     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1888     CU_ASSERT_PTR_NOT_NULL(unit);
 1889     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1890     ut_free(unit);
 1891 
 1892     spec = "s@1970-01-01T00:00:00Z";
 1893     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1894     CU_ASSERT_PTR_NOT_NULL(unit);
 1895     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1896     ut_free(unit);
 1897 
 1898     spec = "s @ 1970-01-01T00:00:00Z";
 1899     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1900     CU_ASSERT_PTR_NOT_NULL(unit);
 1901     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1902     ut_free(unit);
 1903 
 1904     spec = "second@1970-01-01T00:00:00Z";
 1905     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1906     CU_ASSERT_PTR_NOT_NULL(unit);
 1907     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1908     ut_free(unit);
 1909 
 1910     spec = "second @ 1970-01-01T00:00:00Z";
 1911     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1912     CU_ASSERT_PTR_NOT_NULL(unit);
 1913     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1914     ut_free(unit);
 1915 
 1916     spec = "second since 1970-01-01T00:00:00Z";
 1917     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1918     CU_ASSERT_PTR_NOT_NULL(unit);
 1919     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1920     ut_free(unit);
 1921 
 1922     spec = "second ref 1970-01-01T00:00:00Z";
 1923     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1924     CU_ASSERT_PTR_NOT_NULL(unit);
 1925     CU_ASSERT_EQUAL(ut_compare(unit, secondsSinceTheEpoch), 0);
 1926     ut_free(unit);
 1927 
 1928     spec = "kg\xb7m\xb2/s\xb3"; /* "kg" mid-dot "m" squared "/" "s" cubed */
 1929     unit = ut_parse(unitSystem, spec, UT_LATIN1);
 1930     CU_ASSERT_PTR_NOT_NULL(unit);
 1931     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1932     ut_free(unit);
 1933 
 1934     spec = "(kg)(m)^2/(s)^3";
 1935     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1936     CU_ASSERT_PTR_NOT_NULL(unit);
 1937     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1938     ut_free(unit);
 1939 
 1940     spec = "kg\xc2\xb7m\xc2\xb2/s\xc2\xb3";
 1941     unit = ut_parse(unitSystem, spec, UT_UTF8);
 1942     CU_ASSERT_PTR_NOT_NULL(unit);
 1943     CU_ASSERT_EQUAL(ut_compare(unit, watt), 0);
 1944     ut_free(unit);
 1945 
 1946     spec = "0.1 lg(re (1e-6 m)^3)";
 1947     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1948     CU_ASSERT_PTR_NOT_NULL(unit);
 1949     CU_ASSERT_EQUAL(ut_compare(unit, dBZ), 0);
 1950     ut_free(unit);
 1951 
 1952     {
 1953         char    buf[] = " (K/1.8) @ 459.67 ";
 1954 
 1955         (void)ut_trim(buf, UT_ASCII);
 1956 
 1957         unit = ut_parse(unitSystem, buf, UT_ASCII);
 1958         CU_ASSERT_PTR_NOT_NULL(unit);
 1959         CU_ASSERT_EQUAL(ut_are_convertible(unit, fahrenheit), 1);
 1960         ut_free(unit);
 1961     }
 1962 
 1963     spec = "1";
 1964     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1965     CU_ASSERT_PTR_NOT_NULL(unit);
 1966     CU_ASSERT_EQUAL(ut_compare(ut_get_dimensionless_unit_one(unitSystem), unit), 0);
 1967     ut_free(unit);
 1968 
 1969     spec = "3.141592653589793238462643383279";
 1970     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1971     CU_ASSERT_PTR_NOT_NULL(unit);
 1972     ut_free(unit);
 1973 
 1974     spec = "";
 1975     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1976     CU_ASSERT_PTR_NOT_NULL(unit);
 1977     CU_ASSERT_EQUAL(ut_compare(ut_get_dimensionless_unit_one(unitSystem), unit), 0);
 1978     ut_free(unit);
 1979 
 1980     spec = "km";
 1981     unit = ut_parse(unitSystem, spec, UT_ASCII);
 1982     CU_ASSERT_PTR_NOT_NULL(unit);
 1983     CU_ASSERT_EQUAL(ut_compare(kilometer, unit), 0);
 1984     ut_free(unit);
 1985 
 1986     spec = "\xb5m"; /* mu "m" */
 1987     unit = ut_parse(unitSystem, spec, UT_LATIN1);
 1988     CU_ASSERT_PTR_NOT_NULL(unit);
 1989     CU_ASSERT_EQUAL(ut_compare(unit, micron), 0);
 1990     ut_free(unit);
 1991 
 1992     spec = "\xb5megaHz"; /* mu "megaHz" */
 1993     unit = ut_parse(unitSystem, spec, UT_LATIN1);
 1994     CU_ASSERT_PTR_NOT_NULL(unit);
 1995     CU_ASSERT_EQUAL(ut_compare(unit, hertz), 0);
 1996     ut_free(unit);
 1997 
 1998     spec = "MeGa\xb5Hertz"; /* "MeGa" mu "Hertz" */
 1999     unit = ut_parse(unitSystem, spec, UT_LATIN1);
 2000     CU_ASSERT_PTR_NOT_NULL(unit);
 2001     CU_ASSERT_EQUAL(ut_compare(unit, hertz), 0);
 2002     ut_free(unit);
 2003 
 2004     spec = "meter @ 100 @ 10";
 2005     unit = ut_parse(unitSystem, spec, UT_LATIN1);
 2006     CU_ASSERT_PTR_NULL(unit);
 2007     CU_ASSERT_EQUAL(ut_get_status(), UT_SYNTAX);
 2008 }
 2009 
 2010 
 2011 static void
 2012 test_visitor(void)
 2013 {
 2014     CU_ASSERT_EQUAL(ut_accept_visitor(NULL, NULL, NULL), UT_BAD_ARG);
 2015 }
 2016 
 2017 
 2018 static void
 2019 test_xml(void)
 2020 {
 2021     ut_system*          xmlSystem;
 2022     glob_t              files;
 2023     int                 status;
 2024     ut_unit*            unit1;
 2025     ut_unit*            unit2;
 2026     cv_converter*   converter;
 2027     char*       spec;
 2028     ut_unit*        unit;
 2029 
 2030     ut_set_error_message_handler(ut_write_to_stderr);
 2031     xmlSystem = ut_read_xml(xmlPath);
 2032     CU_ASSERT_PTR_NOT_NULL_FATAL(xmlSystem);
 2033 
 2034     spec = "seconds@1970-01-01T00:00:00Z";
 2035     unit = ut_parse(xmlSystem, spec, UT_ASCII);
 2036     CU_ASSERT_PTR_NOT_NULL(unit);
 2037     ut_free(unit);
 2038 
 2039     spec = "seconds @ 1970-01-01T00:00:00Z";
 2040     unit = ut_parse(xmlSystem, spec, UT_ASCII);
 2041     CU_ASSERT_PTR_NOT_NULL(unit);
 2042     ut_free(unit);
 2043 
 2044     spec = "seconds since 1970-01-01T00:00:00Z";
 2045     unit = ut_parse(xmlSystem, spec, UT_ASCII);
 2046     CU_ASSERT_PTR_NOT_NULL(unit);
 2047     ut_free(unit);
 2048 
 2049     spec = "seconds since 1970-01-01T00:00:00Z";
 2050     unit = ut_parse(xmlSystem, spec, UT_ASCII);
 2051     CU_ASSERT_PTR_NOT_NULL(unit);
 2052     ut_free(unit);
 2053 
 2054     unit1 = ut_get_unit_by_symbol(unitSystem, "\xb0K"); /* Latin-1 degree sym */
 2055     CU_ASSERT_PTR_NOT_NULL(unit1);
 2056     CU_ASSERT_EQUAL(ut_compare(unit1, kelvin), 0);
 2057     ut_free(unit1);
 2058 
 2059     unit1 = ut_parse(xmlSystem, "\xb0K", UT_LATIN1);    /* degree sign */
 2060     CU_ASSERT_PTR_NOT_NULL(unit1);
 2061 
 2062     unit2 = ut_parse(xmlSystem, "K", UT_LATIN1);
 2063     CU_ASSERT_PTR_NOT_NULL(unit2);
 2064 
 2065     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2066 
 2067     ut_free(unit1);
 2068 
 2069     unit1 = ut_parse(xmlSystem, "\xc2\xb5K", UT_UTF8);  /* "mu" character */
 2070     CU_ASSERT_PTR_NOT_NULL(unit1);
 2071     converter = ut_get_converter(unit1, unit2);
 2072     CU_ASSERT_PTR_NOT_NULL_FATAL(converter);
 2073     CU_ASSERT_TRUE(areCloseDoubles(cv_convert_double(converter, 1e6), 1.0));
 2074 
 2075     cv_free(converter);
 2076     ut_free(unit1);
 2077     ut_free(unit2);
 2078 
 2079     unit1 = ut_parse(xmlSystem, "arc_degree", UT_ASCII);
 2080     CU_ASSERT_PTR_NOT_NULL(unit1);
 2081     unit2 = ut_parse(xmlSystem, "arc""\xA0""degree", UT_LATIN1);  /* NBSP */
 2082     CU_ASSERT_PTR_NOT_NULL(unit2);
 2083     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2084     ut_free(unit2);
 2085     unit2 = ut_parse(xmlSystem, "\xB0", UT_LATIN1);  /* degree sign */
 2086     CU_ASSERT_PTR_NOT_NULL(unit2);
 2087     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2088     ut_free(unit2);
 2089     unit2 = ut_parse(xmlSystem, "\xC2\xB0", UT_UTF8);  /* degree sign */
 2090     CU_ASSERT_PTR_NOT_NULL(unit2);
 2091     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2092     ut_free(unit2);
 2093     ut_free(unit1);
 2094 
 2095     unit1 = ut_parse(xmlSystem, "arc_minute", UT_ASCII);
 2096     CU_ASSERT_PTR_NOT_NULL(unit1);
 2097     unit2 = ut_parse(xmlSystem, "arc""\xA0""minute", UT_LATIN1);  /* NBSP */
 2098     CU_ASSERT_PTR_NOT_NULL(unit2);
 2099     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2100     ut_free(unit2);
 2101     unit2 = ut_parse(xmlSystem, "'", UT_ASCII);
 2102     CU_ASSERT_PTR_NOT_NULL(unit2);
 2103     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2104     ut_free(unit2);
 2105     unit2 = ut_parse(xmlSystem, "\xE2\x80\xB2", UT_UTF8);  /* PRIME */
 2106     CU_ASSERT_PTR_NOT_NULL(unit2);
 2107     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2108     ut_free(unit2);
 2109     ut_free(unit1);
 2110 
 2111     unit1 = ut_parse(xmlSystem, "arc_second", UT_ASCII);
 2112     CU_ASSERT_PTR_NOT_NULL(unit1);
 2113     unit2 = ut_parse(xmlSystem, "arc""\xA0""second", UT_LATIN1);  /* NBSP */
 2114     CU_ASSERT_PTR_NOT_NULL(unit2);
 2115     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2116     ut_free(unit2);
 2117     unit2 = ut_parse(xmlSystem, "\"", UT_ASCII);
 2118     CU_ASSERT_PTR_NOT_NULL(unit2);
 2119     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2120     ut_free(unit2);
 2121     unit2 = ut_parse(xmlSystem, "\xE2\x80\xB3", UT_UTF8);  /* DOUBLE PRIME */
 2122     CU_ASSERT_PTR_NOT_NULL(unit2);
 2123     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2124     ut_free(unit2);
 2125     ut_free(unit1);
 2126 
 2127     unit1 = ut_parse(xmlSystem, "ohm", UT_ASCII);
 2128     CU_ASSERT_PTR_NOT_NULL(unit1);
 2129     unit2 = ut_parse(xmlSystem, "\xCE\xA9", UT_UTF8);  /* UPPER CASE OMEGA */
 2130     CU_ASSERT_PTR_NOT_NULL(unit2);
 2131     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2132     ut_free(unit2);
 2133     unit2 = ut_parse(xmlSystem, "\xE2\x84\xA6", UT_UTF8);  /* OHM SIGN */
 2134     CU_ASSERT_PTR_NOT_NULL(unit2);
 2135     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2136     ut_free(unit2);
 2137     ut_free(unit1);
 2138 
 2139     unit1 = ut_parse(xmlSystem, "degree_celsius", UT_ASCII);
 2140     CU_ASSERT_PTR_NOT_NULL(unit1);
 2141     unit2 = ut_parse(xmlSystem, "degree""\xA0""celsius", UT_LATIN1);/* NBSP */
 2142     CU_ASSERT_PTR_NOT_NULL(unit2);
 2143     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2144     ut_free(unit2);
 2145     unit2 = ut_parse(xmlSystem, "\xB0""C", UT_LATIN1);  /* degree sign */
 2146     CU_ASSERT_PTR_NOT_NULL(unit2);
 2147     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2148     ut_free(unit2);
 2149     unit2 = ut_parse(xmlSystem, "\xE2\x84\x83", UT_UTF8); /* DEGREE CELSIUS */
 2150     CU_ASSERT_PTR_NOT_NULL(unit2);
 2151     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2152     ut_free(unit2);
 2153     ut_free(unit1);
 2154 
 2155     unit1 = ut_parse(xmlSystem, "angstrom", UT_ASCII);
 2156     CU_ASSERT_PTR_NOT_NULL(unit1);
 2157     unit2 = ut_parse(xmlSystem, "\xe5ngstr\xf6m", UT_LATIN1);/* small A with ring */
 2158     CU_ASSERT_PTR_NOT_NULL(unit2);
 2159     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2160     ut_free(unit2);
 2161 #if 0
 2162     unit2 = ut_parse(xmlSystem, "\xc5ngstr\xf6m", UT_LATIN1);/* capital A with ring */
 2163     CU_ASSERT_PTR_NOT_NULL(unit2);
 2164     CU_ASSERT_EQUAL(ut_compare(unit1, unit2), 0);
 2165     ut_free(unit2);
 2166 #endif
 2167     ut_free(unit1);
 2168 
 2169     ut_free_system(xmlSystem);
 2170 
 2171     ut_set_error_message_handler(ut_ignore);
 2172 
 2173     xmlSystem = ut_read_xml(NULL);
 2174     if (xmlSystem == NULL) {
 2175         CU_ASSERT_EQUAL(ut_get_status(), getenv("UDUNITS2_XML_PATH") == NULL
 2176                 ? UT_OPEN_DEFAULT : UT_OPEN_ENV);
 2177     }
 2178     else {
 2179         ut_free_system(xmlSystem);
 2180     }
 2181 
 2182     xmlSystem = ut_read_xml("xmlFailure/noExist.xml");
 2183     CU_ASSERT_PTR_NULL(xmlSystem);
 2184     CU_ASSERT_EQUAL(ut_get_status(), UT_OPEN_ARG);
 2185 
 2186     status = glob("xmlFailure/*.xml", 0, NULL, &files);
 2187 
 2188     if (status != 0 && status != GLOB_NOMATCH) {
 2189         CU_ASSERT_TRUE(0);
 2190     }
 2191     else {
 2192         size_t  i;
 2193 
 2194         for (i = 0; i < files.gl_pathc; ++i) {
 2195             xmlSystem = ut_read_xml(files.gl_pathv[i]);
 2196 
 2197             CU_ASSERT(xmlSystem == NULL);
 2198 
 2199             if (xmlSystem == NULL) {
 2200                 CU_ASSERT(ut_get_status() == UT_PARSE);
 2201 
 2202                 if (ut_get_status() != UT_PARSE)
 2203                     (void)fprintf(stderr, "File didn't fail: \"%s\"\n",
 2204                         files.gl_pathv[i]);
 2205             }
 2206             else {
 2207                 (void)fprintf(stderr, "File didn't fail: \"%s\"\n",
 2208                     files.gl_pathv[i]);
 2209                 ut_free_system(xmlSystem);
 2210             }
 2211         }
 2212     }
 2213 
 2214     globfree(&files);
 2215 
 2216     ut_set_error_message_handler(ut_write_to_stderr);
 2217 
 2218     status = glob("xmlSuccess/*.xml", 0, NULL, &files);
 2219 
 2220     if (status != 0 && status != GLOB_NOMATCH) {
 2221         CU_ASSERT_TRUE(0);
 2222     }
 2223     else {
 2224         size_t  i;
 2225 
 2226         for (i = 0; i < files.gl_pathc; ++i) {
 2227             xmlSystem = ut_read_xml(files.gl_pathv[i]);
 2228 
 2229             CU_ASSERT_PTR_NOT_NULL(xmlSystem);
 2230 
 2231             if (xmlSystem != NULL) {
 2232                 ut_free_system(xmlSystem);
 2233             }
 2234             else {
 2235                 (void)fprintf(stderr, "File failed: \"%s\"\n",
 2236                     files.gl_pathv[i]);
 2237             }
 2238         }
 2239     }
 2240 
 2241     globfree(&files);
 2242 
 2243     /*
 2244      * Test again to ensure any persistent state doesn't interfere.
 2245      */
 2246     ut_set_error_message_handler(ut_ignore);
 2247     xmlSystem = ut_read_xml(xmlPath);
 2248     CU_ASSERT_PTR_NOT_NULL(xmlSystem);
 2249     ut_free_system(xmlSystem);
 2250 }
 2251 
 2252 static void
 2253 test_mm2_day2_divide(void)
 2254 {
 2255     ut_system*  xmlSystem;
 2256     ut_unit*    unit1;
 2257     ut_unit*    unit2;
 2258     const char* spec = "mm2 day-2";
 2259 
 2260     ut_set_error_message_handler(ut_write_to_stderr);
 2261     xmlSystem = ut_read_xml(xmlPath);
 2262     CU_ASSERT_PTR_NOT_NULL_FATAL(xmlSystem);
 2263 
 2264     unit1 = ut_parse(xmlSystem, spec, UT_ASCII);
 2265     CU_ASSERT_PTR_NOT_NULL(unit1);
 2266     unit2 = ut_divide(unit1, unit1);
 2267 
 2268     const char* expect = "1";
 2269     char        actual[128];
 2270     ut_format(unit2, actual, 128, UT_ASCII);
 2271     CU_ASSERT_STRING_EQUAL(actual, expect);
 2272     if (strcmp(actual, expect))
 2273         fprintf(stderr, "(%s)/(%s) = \"%s\"\n", spec, spec, actual);
 2274 
 2275     ut_free(unit1);
 2276     ut_free(unit2);
 2277     ut_free_system(xmlSystem);
 2278 }
 2279 
 2280 
 2281 static void
 2282 test_timeResolution(void)
 2283 {
 2284     ut_system*  xmlSystem;
 2285 
 2286     ut_set_error_message_handler(ut_write_to_stderr);
 2287     xmlSystem = ut_read_xml(xmlPath);
 2288     CU_ASSERT_PTR_NOT_NULL_FATAL(xmlSystem);
 2289 
 2290     // Maximum temporal resolution:
 2291     const char string[] = "day since 2001-01-01 00:00:00.000000000 UTC";
 2292     ut_unit* unit = ut_parse(xmlSystem, string, UT_ASCII);
 2293     CU_ASSERT_PTR_NOT_NULL_FATAL(unit);
 2294 
 2295     char buf[128];
 2296     int  len = ut_format(unit, buf, sizeof(buf), UT_ASCII | UT_NAMES);
 2297     CU_ASSERT_NOT_EQUAL_FATAL(len, -1);
 2298     printf("test_timeResolution() unit=\"%s\"", buf);
 2299     CU_ASSERT_STRING_EQUAL(buf, string);
 2300 
 2301     ut_free(unit);
 2302 }
 2303 
 2304 int
 2305 main(
 2306     const int           argc,
 2307     const char* const*  argv)
 2308 {
 2309     int exitCode = EXIT_FAILURE;
 2310 
 2311     xmlPath = argv[1]
 2312             ? argv[1]
 2313             : getenv("UDUNITS2_XML_PATH");
 2314 
 2315     if (CU_initialize_registry() == CUE_SUCCESS) {
 2316     CU_Suite*   testSuite = CU_add_suite(__FILE__, setup, teardown);
 2317 
 2318     if (testSuite != NULL) {
 2319         CU_ADD_TEST(testSuite, test_mm2_day2_divide);
 2320         CU_ADD_TEST(testSuite, test_unitSystem);
 2321         CU_ADD_TEST(testSuite, test_utNewBaseUnit);
 2322         CU_ADD_TEST(testSuite, test_utNewDimensionlessUnit);
 2323         CU_ADD_TEST(testSuite, test_utGetUnitByName);
 2324         CU_ADD_TEST(testSuite, test_utGetUnitBySymbol);
 2325         CU_ADD_TEST(testSuite, test_utAddNamePrefix);
 2326         CU_ADD_TEST(testSuite, test_utAddSymbolPrefix);
 2327         CU_ADD_TEST(testSuite, test_utMapNameToUnit);
 2328         CU_ADD_TEST(testSuite, test_utMapSymbolToUnit);
 2329         CU_ADD_TEST(testSuite, test_utScale);
 2330         CU_ADD_TEST(testSuite, test_utOffset);
 2331         CU_ADD_TEST(testSuite, test_utOffsetByTime);
 2332         CU_ADD_TEST(testSuite, test_ut_decode_time);
 2333         CU_ADD_TEST(testSuite, test_utMultiply);
 2334         CU_ADD_TEST(testSuite, test_utInvert);
 2335         CU_ADD_TEST(testSuite, test_utDivide);
 2336         CU_ADD_TEST(testSuite, test_utRaise);
 2337         CU_ADD_TEST(testSuite, test_utRoot);
 2338         CU_ADD_TEST(testSuite, test_utLog);
 2339         CU_ADD_TEST(testSuite, test_utMapUnitToName);
 2340         CU_ADD_TEST(testSuite, test_utGetName);
 2341         CU_ADD_TEST(testSuite, test_utGetSymbol);
 2342         CU_ADD_TEST(testSuite, test_utToString);
 2343         CU_ADD_TEST(testSuite, test_utGetDimensionlessUnitOne);
 2344         CU_ADD_TEST(testSuite, test_utGetSystem);
 2345         CU_ADD_TEST(testSuite, test_utSameSystem);
 2346         CU_ADD_TEST(testSuite, test_utIsDimensionless);
 2347         CU_ADD_TEST(testSuite, test_utClone);
 2348         CU_ADD_TEST(testSuite, test_utAreConvertible);
 2349         CU_ADD_TEST(testSuite, test_utGetConverter);
 2350         CU_ADD_TEST(testSuite, test_utSetEncoding);
 2351         CU_ADD_TEST(testSuite, test_utCompare);
 2352         CU_ADD_TEST(testSuite, test_parsing);
 2353         CU_ADD_TEST(testSuite, test_visitor);
 2354         CU_ADD_TEST(testSuite, test_xml);
 2355         CU_ADD_TEST(testSuite, test_timeResolution);
 2356         /*
 2357         */
 2358 
 2359         ut_set_error_message_handler(ut_ignore);
 2360 
 2361         if (CU_basic_run_tests() == CUE_SUCCESS) {
 2362         if (CU_get_number_of_tests_failed() == 0)
 2363             exitCode = EXIT_SUCCESS;
 2364         }
 2365     }
 2366 
 2367     CU_cleanup_registry();
 2368     }
 2369 
 2370     return exitCode;
 2371 }