void test_value (void) {
    XmlRpcEnv env;

    // Test basic reference counting behavior.
    xmlrpc_value *v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 1);
    env.throwIfFaultOccurred();
    XmlRpcValue val1 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
    v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 2);
    env.throwIfFaultOccurred();
    XmlRpcValue val2 = v;
    xmlrpc_DECREF(v);

    // Borrow a reference.
    v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 3);
    env.throwIfFaultOccurred();
    XmlRpcValue val3 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
    xmlrpc_value *borrowed = val3.borrowReference();
    TEST(borrowed == v);

    // Make a reference.
    v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 4);
    env.throwIfFaultOccurred();
    XmlRpcValue val4 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
    xmlrpc_value *made = val4.makeReference();
    TEST(made == v);
    xmlrpc_DECREF(made);

    // Test our default constructor.
    XmlRpcValue val5;
    TEST(val5.getBool() == false);

    // Test our type introspection.
    TEST(XmlRpcValue::makeInt(0).getType() == XMLRPC_TYPE_INT);
    
    // Test our basic data types.
    TEST(XmlRpcValue::makeInt(30).getInt() == 30);
    TEST(XmlRpcValue::makeInt(-30).getInt() == -30);
    TEST(XmlRpcValue::makeBool(true).getBool() == true);
    TEST(XmlRpcValue::makeBool(false).getBool() == false);
    TEST(XmlRpcValue::makeDateTime("19980717T14:08:55").getRawDateTime() ==
         "19980717T14:08:55");
    TEST(XmlRpcValue::makeString("foo").getString() == "foo");
    TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
    TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
    TEST(XmlRpcValue::makeString("a\0b").getString() == string("a\0b"));
    XmlRpcValue::makeArray().getArray();
    XmlRpcValue::makeStruct().getStruct();

    // Test Base64 values.
    const unsigned char *b64_data;
    size_t b64_len;
    XmlRpcValue val6 = XmlRpcValue::makeBase64((unsigned char*) "a\0\0b", 4);
    val6.getBase64(b64_data, b64_len);
    TEST(b64_len == 4);
    TEST(memcmp(b64_data, "a\0\0b", 4) == 0);

    // Test arrays.
    XmlRpcValue array = XmlRpcValue::makeArray();
    TEST(array.arraySize() == 0);
    array.arrayAppendItem(XmlRpcValue::makeString("foo"));
    TEST(array.arraySize() == 1);
    array.arrayAppendItem(XmlRpcValue::makeString("bar"));
    TEST(array.arraySize() == 2);
    TEST(array.arrayGetItem(0).getString() == "foo");
    TEST(array.arrayGetItem(1).getString() == "bar");

    // Test structs.
    XmlRpcValue strct = XmlRpcValue::makeStruct();
    TEST(strct.structSize() == 0);
    strct.structSetValue("foo", XmlRpcValue::makeString("fooval"));
    TEST(strct.structSize() == 1);
    strct.structSetValue("bar", XmlRpcValue::makeString("barval"));
    TEST(strct.structSize() == 2);
    TEST(strct.structHasKey("bar"));
    TEST(!strct.structHasKey("nosuch"));
    for (size_t i = 0; i < strct.structSize(); i++) {
        string key;
        XmlRpcValue value;
        strct.structGetKeyAndValue(i, key, value);
        TEST(key + "val" == value.getString());
    }
}