#include #include #include "xmlrpc_config.h" #include "girstring.h" #include "casprintf.h" #include "xmlrpc-c/base.h" #include "testtool.h" #include "xml_data.h" #include "parse_xml.h" static void testParseNumberValue(void) { char const xmldata[] = XML_PROLOGUE "\r\n" "test\r\n" "\r\n" "2147483647\r\n" \ "-2147483648\r\n" \ "10\r\n" "10\r\n" "10\r\n" "10\r\n" "10\r\n" "10\r\n" "10.1\r\n" "-10.1\r\n" "+10.1\r\n" "0\r\n" ".01\r\n" "5.\r\n" "5.3E6\r\n" " 1\r\n" "\r\n" "\r\n"; xmlrpc_env env; xmlrpc_value * paramArrayP; const char * methodName; int arraySize; xmlrpc_int int_max, int_min; xmlrpc_int32 i_i1, i_i2, i_i4; xmlrpc_int64 i_i8, i_ex_i8; double d1, d2, d3, d4, d5, d6, d7, d8, d9; xmlrpc_env_init(&env); xmlrpc_parse_call(&env, xmldata, strlen(xmldata), &methodName, ¶mArrayP); TEST_NO_FAULT(&env); arraySize = xmlrpc_array_size(&env, paramArrayP); TEST_NO_FAULT(&env); TEST(arraySize == 16); xmlrpc_decompose_value( &env, paramArrayP, "(iiiiiIIddddddddd)", &int_max, &int_min, &i_i1, &i_i2, &i_i4, &i_i8, &i_ex_i8, &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9); TEST_NO_FAULT(&env); TEST(int_max == INT_MAX); TEST(int_min == INT_MIN); TEST(i_i1 == 10); TEST(i_i2 == 10); TEST(i_i4 == 10); TEST(i_i8 == 10); TEST(i_ex_i8 == 10); TESTFLOATEQUAL(d1, 10.0); TESTFLOATEQUAL(d2, 10.1); TESTFLOATEQUAL(d3, -10.1); TESTFLOATEQUAL(d4, +10.1); TESTFLOATEQUAL(d5, 0.0); TESTFLOATEQUAL(d6, 0.01); TESTFLOATEQUAL(d7, 5.0); TESTFLOATEQUAL(d8, 5.3E6); TESTFLOATEQUAL(d9, 1.0); xmlrpc_DECREF(paramArrayP); strfree(methodName); xmlrpc_env_clean(&env); } static void testParseMiscSimpleValue(void) { char const xmldata[] = XML_PROLOGUE "\r\n" "test\r\n" "\r\n" "hello\r\n" "0\r\n" "1\r\n" "19980717T14:08:55" "\r\n" "" "19980717T14:08:55.123456" "\r\n" "YmFzZTY0IGRhdGE=\r\n" "\r\n" "\r\n" "\r\n" "\r\n"; xmlrpc_env env; xmlrpc_value * paramArrayP; const char * methodName; int arraySize; const char * str_hello; xmlrpc_bool b_false, b_true; const char * datetime_sec; const char * datetime_usec; unsigned char * b64_data; size_t b64_len; xmlrpc_env_init(&env); xmlrpc_parse_call(&env, xmldata, strlen(xmldata), &methodName, ¶mArrayP); TEST_NO_FAULT(&env); arraySize = xmlrpc_array_size(&env, paramArrayP); TEST_NO_FAULT(&env); TEST(arraySize == 8); xmlrpc_decompose_value( &env, paramArrayP, "(sbb886nn)", &str_hello, &b_false, &b_true, &datetime_sec, &datetime_usec, &b64_data, &b64_len); TEST_NO_FAULT(&env); TEST(streq(str_hello, "hello")); TEST(!b_false); TEST(b_true); TEST(streq(datetime_sec, "19980717T14:08:55")); TEST(streq(datetime_usec, "19980717T14:08:55.123456")); TEST(b64_len == 11); TEST(memcmp(b64_data, "base64 data", b64_len) == 0); free(b64_data); strfree(str_hello); strfree(datetime_sec); strfree(datetime_usec); xmlrpc_DECREF(paramArrayP); strfree(methodName); xmlrpc_env_clean(&env); } static void validateParseResponseResult(xmlrpc_value * const valueP) { xmlrpc_env env; xmlrpc_value * s; xmlrpc_int32 int_max; xmlrpc_int32 int_min; xmlrpc_int32 int_one; xmlrpc_bool bool_false; xmlrpc_bool bool_true; char * str_hello; char * str_untagged; char * datetime; unsigned char * b64_data; size_t b64_len; double negone; double zero; double one; xmlrpc_env_init(&env); xmlrpc_decompose_value( &env, valueP, "((iibbs68())idddSs)", &int_max, &int_min, &bool_false, &bool_true, &str_hello, &b64_data, &b64_len, &datetime, &int_one, &negone, &zero, &one, &s, &str_untagged); TEST_NO_FAULT(&env); TEST(int_max == INT_MAX); TEST(int_min == INT_MIN); TEST(!bool_false); TEST(bool_true); TEST(strlen(str_hello) == strlen("Hello, world! <&>")); TEST(streq(str_hello, "Hello, world! <&>")); TEST(b64_len == 11); TEST(memcmp(b64_data, "base64 data", b64_len) == 0); TEST(streq(datetime, "19980717T14:08:55")); TEST(int_one == 1); TEST(negone == -1.0); TEST(zero == 0.0); TEST(one == 1.0); TEST(streq(str_untagged, "Untagged string")); free(str_hello); free(b64_data); free(datetime); free(str_untagged); { /* Analyze the contents of our struct. */ xmlrpc_value * sval; int size, sval_int; TEST(s != NULL); size = xmlrpc_struct_size(&env, s); TEST_NO_FAULT(&env); TEST(size == 2); sval = xmlrpc_struct_get_value(&env, s, "ten <&>"); TEST_NO_FAULT(&env); xmlrpc_decompose_value(&env, sval, "i", &sval_int); TEST_NO_FAULT(&env); TEST(sval_int == 10); sval = xmlrpc_struct_get_value(&env, s, "twenty"); TEST_NO_FAULT(&env); xmlrpc_decompose_value(&env, sval, "i", &sval_int); TEST_NO_FAULT(&env); TEST(sval_int == 20); xmlrpc_DECREF(s); } xmlrpc_env_clean(&env); } static void testParseGoodResponse(void) { xmlrpc_env env; xmlrpc_value * valueP; int faultCode; const char * faultString; xmlrpc_env_init(&env); xmlrpc_parse_response2(&env, good_response_xml, strlen(good_response_xml), &valueP, &faultCode, &faultString); TEST_NO_FAULT(&env); TEST(faultString == NULL); validateParseResponseResult(valueP); xmlrpc_DECREF(valueP); /* Try it again with old interface */ valueP = xmlrpc_parse_response(&env, good_response_xml, strlen(good_response_xml)); TEST_NO_FAULT(&env); TEST(valueP != NULL); validateParseResponseResult(valueP); xmlrpc_DECREF(valueP); xmlrpc_env_clean(&env); } static void testParseBadResponseXml(void) { /*---------------------------------------------------------------------------- Test parsing of data that is supposed to be a response, but in not even valid XML. -----------------------------------------------------------------------------*/ xmlrpc_env env; xmlrpc_value * valueP; int faultCode; const char * faultString; xmlrpc_env_init(&env); xmlrpc_parse_response2(&env, unparseable_value, strlen(unparseable_value), &valueP, &faultCode, &faultString); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); xmlrpc_env_clean(&env); xmlrpc_env_init(&env); /* And again with the old interface */ valueP = xmlrpc_parse_response(&env, unparseable_value, strlen(unparseable_value)); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); xmlrpc_env_clean(&env); TEST(valueP == NULL); } static void testParseBadResponseXmlRpc(void) { /*---------------------------------------------------------------------------- Test parsing of data that is supposed to be a response, and is valid XML, but is not valid XML-RPC. -----------------------------------------------------------------------------*/ unsigned int i; /* For this test, we test up to but not including the in a successful RPC response. */ /* Next, check for bogus responses. These are all well-formed XML, but ** they aren't legal XML-RPC. */ for (i = 15; bad_responses[i] != NULL; ++i) { const char * const bad_resp = bad_responses[i]; xmlrpc_env env; xmlrpc_value * v; xmlrpc_env_init(&env); /* Now, make sure the higher-level routine barfs appropriately. */ v = xmlrpc_parse_response(&env, bad_resp, strlen(bad_resp)); TEST(env.fault_occurred); TEST(env.fault_code != 0); /* We use 0 as a code in our bad faults. */ TEST(v == NULL); xmlrpc_env_clean(&env); } } static void testParseBadResult(void) { /*---------------------------------------------------------------------------- Test parsing of data that is supposed to be a response, but is not valid. It looks like a valid success response, but the result value is not valid XML-RPC. -----------------------------------------------------------------------------*/ unsigned int i; for (i = 0; bad_values[i] != NULL; ++i) { const char * const bad_resp = bad_values[i]; xmlrpc_env env; xmlrpc_value * valueP; int faultCode; const char * faultString; xmlrpc_env_init(&env); xmlrpc_parse_response2(&env, bad_resp, strlen(bad_resp), &valueP, &faultCode, &faultString); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); xmlrpc_env_clean(&env); xmlrpc_env_init(&env); /* And again with the old interface */ valueP = xmlrpc_parse_response(&env, bad_resp, strlen(bad_resp)); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); TEST(valueP == NULL); xmlrpc_env_clean(&env); } } static void testParseBadResponse(void) { /*---------------------------------------------------------------------------- Test parsing of data that is supposed to be a response, but is not valid. Either not valid XML or not valid XML-RPC. -----------------------------------------------------------------------------*/ testParseBadResponseXml(); testParseBadResponseXmlRpc(); testParseBadResult(); } static void testParseFaultResponse(void) { /*---------------------------------------------------------------------------- Test parsing of a valid response that indicates the RPC failed. -----------------------------------------------------------------------------*/ xmlrpc_env env; xmlrpc_env_init(&env); { xmlrpc_value * resultP; int faultCode; const char * faultString; xmlrpc_parse_response2(&env, serialized_fault, strlen(serialized_fault), &resultP, &faultCode, &faultString); TEST_NO_FAULT(&env); TEST(faultString != NULL); TEST(faultCode == 6); TEST(streq(faultString, "A fault occurred")); strfree(faultString); } /* Now with the old interface */ { xmlrpc_env fault; /* Parse a valid fault. */ xmlrpc_env_init(&fault); xmlrpc_parse_response(&fault, serialized_fault, strlen(serialized_fault)); TEST(fault.fault_occurred); TEST(fault.fault_code == 6); TEST(streq(fault.fault_string, "A fault occurred")); xmlrpc_env_clean(&fault); } xmlrpc_env_clean(&env); } static void testParseXmlCall(void) { xmlrpc_env env; const char *method_name; xmlrpc_value *params; int i1, i2; const char **bad_call; xmlrpc_env_init(&env); /* Parse a valid call. */ xmlrpc_parse_call(&env, serialized_call, strlen(serialized_call), &method_name, ¶ms); TEST_NO_FAULT(&env); TEST(params != NULL); xmlrpc_decompose_value(&env, params, "(ii)", &i1, &i2); xmlrpc_DECREF(params); TEST_NO_FAULT(&env); TEST(streq(method_name, "gloom&doom")); TEST(i1 == 10 && i2 == 20); strfree(method_name); /* Test some poorly-formed XML data. */ xmlrpc_parse_call(&env, unparseable_value, strlen(unparseable_value), &method_name, ¶ms); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); TEST(method_name == NULL && params == NULL); /* Next, check for bogus values. These are all well-formed XML, but they aren't legal XML-RPC. */ for (bad_call = bad_calls; *bad_call != NULL; ++bad_call) { xmlrpc_parse_call(&env, *bad_call, strlen(*bad_call), &method_name, ¶ms); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); TEST(method_name == NULL && params == NULL); } xmlrpc_env_clean(&env); } static void testParseXmlValue(void) { const char * const xmlInt7 = "7"; const char * const xmlBadVal1 = "hello"; const char * const xmlBadVal2 = ""; xmlrpc_value * valueP; xmlrpc_env env; xmlrpc_env_init(&env); xmlrpc_parse_value_xml(&env, xmlInt7, strlen(xmlInt7), &valueP); TEST_NO_FAULT(&env); xmlrpc_DECREF(valueP); xmlrpc_parse_value_xml(&env, xmlBadVal1, strlen(xmlBadVal1), &valueP); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); xmlrpc_env_clean(&env); xmlrpc_env_init(&env); xmlrpc_parse_value_xml(&env, xmlBadVal2, strlen(xmlBadVal2), &valueP); TEST_FAULT(&env, XMLRPC_PARSE_ERROR); xmlrpc_env_clean(&env); } void test_parse_xml(void) { printf("Running XML parsing tests.\n"); testParseNumberValue(); testParseMiscSimpleValue(); testParseGoodResponse(); testParseFaultResponse(); testParseBadResponse(); testParseXmlCall(); testParseXmlValue(); printf("\n"); printf("XML parsing tests done.\n"); }