|
|
#include <limits.h> |
|
|
#include <stdlib.h> |
|
|
|
|
|
#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 |
|
|
"<methodCall>\r\n" |
|
|
"<methodName>test</methodName>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><int>2147483647</int></value></param>\r\n" \ |
|
|
"<param><value><int>-2147483648</int></value></param>\r\n" \ |
|
|
"<param><value><i1>10</i1></value></param>\r\n" |
|
|
"<param><value><i2>10</i2></value></param>\r\n" |
|
|
"<param><value><i4>10</i4></value></param>\r\n" |
|
|
"<param><value><i8>10</i8></value></param>\r\n" |
|
|
"<param><value><ex:i8>10</ex:i8></value></param>\r\n" |
|
|
"<param><value><double>10</double></value></param>\r\n" |
|
|
"<param><value><double>10.1</double></value></param>\r\n" |
|
|
"<param><value><double>-10.1</double></value></param>\r\n" |
|
|
"<param><value><double>+10.1</double></value></param>\r\n" |
|
|
"<param><value><double>0</double></value></param>\r\n" |
|
|
"<param><value><double>.01</double></value></param>\r\n" |
|
|
"<param><value><double>5.</double></value></param>\r\n" |
|
|
"<param><value><double>5.3E6</double></value></param>\r\n" |
|
|
"<param><value><double> 1</double></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodCall>\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 |
|
|
"<methodCall>\r\n" |
|
|
"<methodName>test</methodName>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><string>hello</string></value></param>\r\n" |
|
|
"<param><value><boolean>0</boolean></value></param>\r\n" |
|
|
"<param><value><boolean>1</boolean></value></param>\r\n" |
|
|
"<param><value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601>" |
|
|
"</value></param>\r\n" |
|
|
"<param><value>" |
|
|
"<dateTime.iso8601>19980717T14:08:55.123456</dateTime.iso8601>" |
|
|
"</value></param>\r\n" |
|
|
"<param><value><base64>YmFzZTY0IGRhdGE=</base64></value></param>\r\n" |
|
|
"<param><value><nil/></value></param>\r\n" |
|
|
"<param><value><ex:nil/></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodCall>\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); |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
v = xmlrpc_parse_response(&env, bad_resp, strlen(bad_resp)); |
|
|
TEST(env.fault_occurred); |
|
|
TEST(env.fault_code != 0); |
|
|
TEST(v == NULL); |
|
|
xmlrpc_env_clean(&env); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testParseBadResult(void) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
testParseBadResponseXml(); |
|
|
|
|
|
testParseBadResponseXmlRpc(); |
|
|
|
|
|
testParseBadResult(); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testParseFaultResponse(void) { |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
|
|
|
{ |
|
|
xmlrpc_env 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); |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
xmlrpc_parse_call(&env, unparseable_value, strlen(unparseable_value), |
|
|
&method_name, ¶ms); |
|
|
TEST_FAULT(&env, XMLRPC_PARSE_ERROR); |
|
|
TEST(method_name == NULL && params == NULL); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = "<value><int>7</int ></value>"; |
|
|
const char * const xmlBadVal1 = "hello"; |
|
|
const char * const xmlBadVal2 = "<junk/>"; |
|
|
|
|
|
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"); |
|
|
} |
|
|
|