--- /dev/null
+/* Copyright information is at the end of the file. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "casprintf.h"
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+
+#include "test.h"
+#include "value.h"
+#include "serialize.h"
+#include "parse_xml.h"
+#include "cgi.h"
+#include "xml_data.h"
+#include "client.h"
+#include "server_abyss.h"
+#include "method_registry.h"
+
+/*=========================================================================
+** Test Harness
+**=========================================================================
+** This is a super light-weight test harness. It's vaguely inspired by
+** Kent Beck's book on eXtreme Programming (XP)--the output is succinct,
+** new tests can be coded quickly, and the whole thing runs in a few
+** second's time.
+**
+** To run the tests, type './rpctest'.
+** To check for memory leaks, install RedHat's 'memprof' utility, and
+** type 'memprof rpctest'.
+**
+** If you add new tests to this file, please deallocate any data
+** structures you use in the appropriate fashion. This allows us to test
+** various destructor code for memory leaks.
+*/
+
+int total_tests = 0;
+int total_failures = 0;
+
+
+/*=========================================================================
+** Test Data
+**=========================================================================
+** Some common test data which need to be allocated at a fixed address,
+** or which are inconvenient to allocate inline.
+*/
+
+static char* test_string_1 = "foo";
+static char* test_string_2 = "bar";
+static int test_int_array_1[5] = {1, 2, 3, 4, 5};
+static int test_int_array_2[3] = {6, 7, 8};
+static int test_int_array_3[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+
+/*=========================================================================
+** Test Suites
+**=========================================================================
+*/
+
+static void test_env(void)
+{
+ xmlrpc_env env, env2;
+ char *s;
+
+ /* Test xmlrpc_env_init. */
+ xmlrpc_env_init(&env);
+ TEST(!env.fault_occurred);
+ TEST(env.fault_code == 0);
+ TEST(env.fault_string == NULL);
+
+ /* Test xmlrpc_set_fault. */
+ xmlrpc_env_set_fault(&env, 1, test_string_1);
+ TEST(env.fault_occurred);
+ TEST(env.fault_code == 1);
+ TEST(env.fault_string != test_string_1);
+ TEST(strcmp(env.fault_string, test_string_1) == 0);
+
+ /* Change an existing fault. */
+ xmlrpc_env_set_fault(&env, 2, test_string_2);
+ TEST(env.fault_occurred);
+ TEST(env.fault_code == 2);
+ TEST(strcmp(env.fault_string, test_string_2) == 0);
+
+ /* Set a fault with a format string. */
+ xmlrpc_env_set_fault_formatted(&env, 3, "a%s%d", "bar", 9);
+ TEST(env.fault_occurred);
+ TEST(env.fault_code == 3);
+ TEST(strcmp(env.fault_string, "abar9") == 0);
+
+ /* Set a fault with an oversized string. */
+ s = "12345678901234567890123456789012345678901234567890";
+ xmlrpc_env_set_fault_formatted(&env, 4, "%s%s%s%s%s%s", s, s, s, s, s, s);
+ TEST(env.fault_occurred);
+ TEST(env.fault_code == 4);
+ TEST(strlen(env.fault_string) == 255);
+
+ /* Test cleanup code (with help from memprof). */
+ xmlrpc_env_clean(&env);
+
+ /* Test cleanup code on in absence of xmlrpc_env_set_fault. */
+ xmlrpc_env_init(&env2);
+ xmlrpc_env_clean(&env2);
+}
+
+static void test_mem_block (void)
+{
+ xmlrpc_env env;
+ xmlrpc_mem_block* block;
+
+ xmlrpc_mem_block* typed_heap_block;
+ xmlrpc_mem_block typed_auto_block;
+ void** typed_contents;
+
+ xmlrpc_env_init(&env);
+
+ /* Allocate a zero-size block. */
+ block = xmlrpc_mem_block_new(&env, 0);
+ TEST_NO_FAULT(&env);
+ TEST(block != NULL);
+ TEST(xmlrpc_mem_block_size(block) == 0);
+
+ /* Grow the block a little bit. */
+ xmlrpc_mem_block_resize(&env, block, strlen(test_string_1) + 1);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_mem_block_size(block) == strlen(test_string_1) + 1);
+
+ /* Insert a string into the block, and resize it by large amount.
+ ** We want to cause a reallocation and copy of the block contents. */
+ strcpy(xmlrpc_mem_block_contents(block), test_string_1);
+ xmlrpc_mem_block_resize(&env, block, 10000);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_mem_block_size(block) == 10000);
+ TEST(strcmp(xmlrpc_mem_block_contents(block), test_string_1) == 0);
+
+ /* Test cleanup code (with help from memprof). */
+ xmlrpc_mem_block_free(block);
+
+ /* Allocate a bigger block. */
+ block = xmlrpc_mem_block_new(&env, 128);
+ TEST_NO_FAULT(&env);
+ TEST(block != NULL);
+ TEST(xmlrpc_mem_block_size(block) == 128);
+
+ /* Test cleanup code (with help from memprof). */
+ xmlrpc_mem_block_free(block);
+
+ /* Allocate a "typed" memory block. */
+ typed_heap_block = XMLRPC_TYPED_MEM_BLOCK_NEW(void*, &env, 20);
+ TEST_NO_FAULT(&env);
+ TEST(typed_heap_block != NULL);
+ TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(void*, typed_heap_block) == 20);
+ typed_contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(void*, typed_heap_block);
+ TEST(typed_contents != NULL);
+
+ /* Resize a typed memory block. */
+ XMLRPC_TYPED_MEM_BLOCK_RESIZE(void*, &env, typed_heap_block, 100);
+ TEST_NO_FAULT(&env);
+ TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(void*, typed_heap_block) == 100);
+
+ /* Test cleanup code (with help from memprof). */
+ XMLRPC_TYPED_MEM_BLOCK_FREE(void*, typed_heap_block);
+
+ /* Test _INIT and _CLEAN for stack-based memory blocks. */
+ XMLRPC_TYPED_MEM_BLOCK_INIT(void*, &env, &typed_auto_block, 30);
+ TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(void*, &typed_auto_block) == 30);
+ XMLRPC_TYPED_MEM_BLOCK_CLEAN(void*, &typed_auto_block);
+
+ /* Test xmlrpc_mem_block_append. */
+ block = XMLRPC_TYPED_MEM_BLOCK_NEW(int, &env, 5);
+ TEST_NO_FAULT(&env);
+ memcpy(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(int, block),
+ test_int_array_1, sizeof(test_int_array_1));
+ XMLRPC_TYPED_MEM_BLOCK_APPEND(int, &env, block, test_int_array_2, 3);
+ TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(int, block) == 8);
+ TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(int, block),
+ test_int_array_3, sizeof(test_int_array_3)) == 0);
+ XMLRPC_TYPED_MEM_BLOCK_FREE(int, block);
+
+ xmlrpc_env_clean(&env);
+}
+
+static char *(base64_triplets[]) = {
+ "", "", "\r\n",
+ "a", "YQ==", "YQ==\r\n",
+ "aa", "YWE=", "YWE=\r\n",
+ "aaa", "YWFh", "YWFh\r\n",
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY"
+ "2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=",
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY"
+ "2Rl\r\n"
+ "ZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=\r\n",
+ NULL};
+
+static void
+test_base64_conversion(void) {
+ xmlrpc_env env;
+ char ** triplet;
+
+ xmlrpc_env_init(&env);
+
+ for (triplet = base64_triplets; *triplet != NULL; triplet += 3) {
+ char * bin_data;
+ char * nocrlf_ascii_data;
+ char * ascii_data;
+ xmlrpc_mem_block * output;
+
+ bin_data = *triplet;
+ nocrlf_ascii_data = *(triplet + 1);
+ ascii_data = *(triplet + 2);
+
+ /* Test our encoding routine. */
+ output = xmlrpc_base64_encode(&env,
+ (unsigned char*) bin_data,
+ strlen(bin_data));
+ TEST_NO_FAULT(&env);
+ TEST(output != NULL);
+ TEST(xmlrpc_mem_block_size(output) == strlen(ascii_data));
+ TEST(memcmp(xmlrpc_mem_block_contents(output), ascii_data,
+ strlen(ascii_data)) == 0);
+ xmlrpc_mem_block_free(output);
+
+ /* Test our newline-free encoding routine. */
+ output =
+ xmlrpc_base64_encode_without_newlines(&env,
+ (unsigned char*) bin_data,
+ strlen(bin_data));
+ TEST_NO_FAULT(&env);
+ TEST(output != NULL);
+ TEST(xmlrpc_mem_block_size(output) == strlen(nocrlf_ascii_data));
+ TEST(memcmp(xmlrpc_mem_block_contents(output), nocrlf_ascii_data,
+ strlen(nocrlf_ascii_data)) == 0);
+ xmlrpc_mem_block_free(output);
+
+ /* Test our decoding routine. */
+ output = xmlrpc_base64_decode(&env, ascii_data, strlen(ascii_data));
+ TEST_NO_FAULT(&env);
+ TEST(output != NULL);
+ TEST(xmlrpc_mem_block_size(output) == strlen(bin_data));
+ TEST(memcmp(xmlrpc_mem_block_contents(output), bin_data,
+ strlen(bin_data)) == 0);
+ xmlrpc_mem_block_free(output);
+ }
+
+ /* Now for something broken... */
+ {
+ xmlrpc_env env2;
+ xmlrpc_mem_block * output;
+
+ xmlrpc_env_init(&env2);
+ output = xmlrpc_base64_decode(&env2, "====", 4);
+ TEST(output == NULL);
+ TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+ xmlrpc_env_clean(&env2);
+ }
+ /* Now for something broken in a really sneaky way... */
+ {
+ xmlrpc_env env2;
+ xmlrpc_mem_block * output;
+ xmlrpc_env_init(&env2);
+ output = xmlrpc_base64_decode(&env2, "a==", 4);
+ TEST(output == NULL);
+ TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+ xmlrpc_env_clean(&env2);
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void test_bounds_checks (void)
+{
+ xmlrpc_env env;
+ xmlrpc_value *array;
+ int i1, i2, i3, i4;
+
+ /* Get an array to work with. */
+ xmlrpc_env_init(&env);
+ array = xmlrpc_build_value(&env, "(iii)", 100, 200, 300);
+ TEST_NO_FAULT(&env);
+ xmlrpc_env_clean(&env);
+
+ /* Test xmlrpc_decompose_value with too few values. */
+ xmlrpc_env_init(&env);
+ xmlrpc_decompose_value(&env, array, "(iiii)", &i1, &i2, &i3, &i4);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+ xmlrpc_env_clean(&env);
+
+ /* Test xmlrpc_decompose_value with too many values. */
+ xmlrpc_env_init(&env);
+ xmlrpc_decompose_value(&env, array, "(ii)", &i1, &i2, &i3, &i4);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+ xmlrpc_env_clean(&env);
+
+ /* Dispose of our array. */
+ xmlrpc_DECREF(array);
+}
+
+
+
+static void test_nesting_limit (void)
+{
+ xmlrpc_env env;
+ xmlrpc_value *val;
+
+ xmlrpc_env_init(&env);
+
+ /* Test with an adequate limit for a result value which is an
+ array which contains an element which is a struct, whose values
+ are simple: 3.
+ */
+ xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 3);
+ val = xmlrpc_parse_response(&env,
+ good_response_xml, strlen(good_response_xml));
+ TEST_NO_FAULT(&env);
+ TEST(val != NULL);
+ xmlrpc_DECREF(val);
+
+ /* Test with an inadequate limit. */
+ xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 2);
+ val = xmlrpc_parse_response(&env,
+ good_response_xml, strlen(good_response_xml));
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR); /* BREAKME - Will change. */
+ TEST(val == NULL);
+
+ /* Reset the default limit. */
+ xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, XMLRPC_NESTING_LIMIT_DEFAULT);
+ TEST(xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID)
+ == XMLRPC_NESTING_LIMIT_DEFAULT);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_xml_size_limit(void) {
+
+ xmlrpc_env env;
+ const char * methodName;
+ xmlrpc_value * paramsP;
+
+ /* NOTE - This test suite only verifies the last-ditch size-checking
+ code. There should also be matching code in all server (and
+ preferably all client) modules as well.
+ */
+
+ /* Set our XML size limit to something ridiculous. */
+ xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, 6);
+
+ /* Attempt to parse a call. */
+ xmlrpc_env_init(&env);
+ xmlrpc_parse_call(&env, serialized_call, strlen(serialized_call),
+ &methodName, ¶msP);
+ TEST_FAULT(&env, XMLRPC_LIMIT_EXCEEDED_ERROR);
+ xmlrpc_env_clean(&env);
+
+ {
+ xmlrpc_value * resultP;
+ int faultCode;
+ const char * faultString;
+
+ /* Attempt to parse a response. */
+ xmlrpc_env_init(&env);
+ xmlrpc_parse_response2(&env,
+ good_response_xml, strlen(good_response_xml),
+ &resultP, &faultCode, &faultString);
+ TEST_FAULT(&env, XMLRPC_LIMIT_EXCEEDED_ERROR);
+ xmlrpc_env_clean(&env);
+ }
+ /* Reset the default limit. */
+ xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, XMLRPC_XML_SIZE_LIMIT_DEFAULT);
+}
+
+
+
+/*=========================================================================
+** test_sample_files
+**=========================================================================
+** Read in a bunch of sample test files and make sure we get plausible
+** results.
+**
+** We use these files to test strange-but-legal encodings, illegal-but-
+** supported encodings, etc.
+*/
+
+#define TESTDATA_DIR "data"
+
+static char *good_requests[] = {
+ TESTDATA_DIR DIRECTORY_SEPARATOR "req_out_of_order.xml",
+ TESTDATA_DIR DIRECTORY_SEPARATOR "req_no_params.xml",
+ TESTDATA_DIR DIRECTORY_SEPARATOR "req_value_name.xml",
+ NULL
+};
+
+#define MAX_SAMPLE_FILE_LEN (16 * 1024)
+
+static char file_buff [MAX_SAMPLE_FILE_LEN];
+
+static void
+read_file (char *path, char **out_data, size_t *out_size)
+{
+ FILE *f;
+ size_t bytes_read;
+
+ /* Open the file. */
+ f = fopen(path, "r");
+ if (f == NULL) {
+ /* Since this error is fairly likely to happen, give an
+ ** informative error message... */
+ fflush(stdout);
+ fprintf(stderr, "Could not open file '%s'. errno=%d (%s)\n",
+ path, errno, strerror(errno));
+ abort();
+ }
+
+ /* Read in one buffer full of data, and make sure that everything
+ ** fit. (We perform a lazy error/no-eof/zero-length-file test using
+ ** bytes_read.) */
+ bytes_read = fread(file_buff, sizeof(char), MAX_SAMPLE_FILE_LEN, f);
+ TEST(0 < bytes_read && bytes_read < MAX_SAMPLE_FILE_LEN);
+
+ /* Close the file and return our data. */
+ fclose(f);
+ *out_data = file_buff;
+ *out_size = bytes_read;
+}
+
+static void test_sample_files (void)
+{
+ xmlrpc_env env;
+ char **paths, *path;
+ char *data;
+ size_t data_len;
+ const char *method_name;
+ xmlrpc_value *params;
+
+ xmlrpc_env_init(&env);
+
+ /* Test our good requests. */
+ for (paths = good_requests; *paths != NULL; paths++) {
+ path = *paths;
+ read_file(path, &data, &data_len);
+ xmlrpc_parse_call(&env, data, data_len, &method_name, ¶ms);
+ TEST_NO_FAULT(&env);
+ strfree(method_name);
+ xmlrpc_DECREF(params);
+ }
+
+ xmlrpc_env_clean(&env);
+}
+
+
+/*=========================================================================
+** test_utf8_coding
+**=========================================================================
+** We need to test our UTF-8 decoder thoroughly. Most of these test
+** cases are taken from the UTF-8-test.txt file by Markus Kuhn
+** <mkuhn@acm.org>:
+** http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+*/
+
+#if HAVE_UNICODE_WCHAR
+
+typedef struct {
+ char *utf8;
+ wchar_t wcs[16];
+} utf8_and_wcs;
+
+static utf8_and_wcs good_utf8[] = {
+
+ /* Greek 'kosme'. */
+ {"\316\272\341\275\271\317\203\316\274\316\265",
+ {0x03BA, 0x1F79, 0x03C3, 0x03BC, 0x03B5, 0}},
+
+ /* First sequences of a given length. */
+ /* '\000' is not a legal C string. */
+ {"\302\200", {0x0080, 0}},
+ {"\340\240\200", {0x0800, 0}},
+
+ /* Last sequences of a given length. */
+ {"\177", {0x007F, 0}},
+ {"\337\277", {0x07FF, 0}},
+ /* 0xFFFF is not a legal Unicode character. */
+
+ /* Other boundry conditions. */
+ {"\001", {0x0001, 0}},
+ {"\355\237\277", {0xD7FF, 0}},
+ {"\356\200\200", {0xE000, 0}},
+ {"\357\277\275", {0xFFFD, 0}},
+
+ /* Other random test cases. */
+ {"", {0}},
+ {"abc", {0x0061, 0x0062, 0x0063, 0}},
+ {"[\302\251]", {0x005B, 0x00A9, 0x005D, 0}},
+
+ {NULL, {0}}
+};
+
+static char *(bad_utf8[]) = {
+
+ /* Continuation bytes. */
+ "\200", "\277",
+
+ /* Lonely start characters. */
+ "\300", "\300x", "\300xx",
+ "\340", "\340x", "\340xx", "\340xxx",
+
+ /* Last byte missing. */
+ "\340\200", "\340\200x", "\340\200xx",
+ "\357\277", "\357\277x", "\357\277xx",
+
+ /* Illegal bytes. */
+ "\376", "\377",
+
+ /* Overlong '/'. */
+ "\300\257", "\340\200\257",
+
+ /* Overlong ASCII NUL. */
+ "\300\200", "\340\200\200",
+
+ /* Maximum overlong sequences. */
+ "\301\277", "\340\237\277",
+
+ /* Illegal code positions. */
+ "\357\277\276", /* U+FFFE */
+ "\357\277\277", /* U+FFFF */
+
+ /* UTF-16 surrogates (unpaired and paired). */
+ "\355\240\200",
+ "\355\277\277",
+ "\355\240\200\355\260\200",
+ "\355\257\277\355\277\277",
+
+ /* Valid UCS-4 characters (we don't handle these yet).
+ ** On systems with UCS-4 or UTF-16 wchar_t values, we
+ ** may eventually handle these in some fashion. */
+ "\360\220\200\200",
+ "\370\210\200\200\200",
+ "\374\204\200\200\200\200",
+
+ NULL
+};
+#endif /* HAVE_UNICODE_WCHAR */
+
+/* This routine is missing on certain platforms. This implementation
+** *appears* to be correct. */
+#if 0
+#ifndef HAVE_WCSNCMP
+int wcsncmp(wchar_t *wcs1, wchar_t* wcs2, size_t len)
+{
+ size_t i;
+ /* XXX - 'unsigned long' should be 'uwchar_t'. */
+ unsigned long c1, c2;
+ for (i=0; i < len; i++) {
+ c1 = wcs1[i];
+ c2 = wcs2[i];
+ /* This clever comparison borrowed from the GNU C Library. */
+ if (c1 == 0 || c1 != c2)
+ return c1 - c2;
+ }
+ return 0;
+}
+#endif /* HAVE_WCSNCMP */
+#endif
+
+static void
+test_utf8_coding(void) {
+
+#if HAVE_UNICODE_WCHAR
+ xmlrpc_env env, env2;
+ utf8_and_wcs *good_data;
+ char **bad_data;
+ char *utf8;
+ wchar_t *wcs;
+ xmlrpc_mem_block *output;
+
+ xmlrpc_env_init(&env);
+
+ /* Test each of our valid UTF-8 sequences. */
+ for (good_data = good_utf8; good_data->utf8 != NULL; good_data++) {
+ utf8 = good_data->utf8;
+ wcs = good_data->wcs;
+
+ /* Attempt to validate the UTF-8 string. */
+ xmlrpc_validate_utf8(&env, utf8, strlen(utf8));
+ TEST_NO_FAULT(&env);
+
+ /* Attempt to decode the UTF-8 string. */
+ output = xmlrpc_utf8_to_wcs(&env, utf8, strlen(utf8));
+ TEST_NO_FAULT(&env);
+ TEST(output != NULL);
+ TEST(wcslen(wcs) == XMLRPC_TYPED_MEM_BLOCK_SIZE(wchar_t, output));
+ TEST(0 ==
+ wcsncmp(wcs, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(wchar_t, output),
+ wcslen(wcs)));
+ xmlrpc_mem_block_free(output);
+
+ /* Test the UTF-8 encoder, too. */
+ output = xmlrpc_wcs_to_utf8(&env, wcs, wcslen(wcs));
+ TEST_NO_FAULT(&env);
+ TEST(output != NULL);
+ TEST(strlen(utf8) == XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output));
+ TEST(0 ==
+ strncmp(utf8, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+ strlen(utf8)));
+ xmlrpc_mem_block_free(output);
+ }
+
+ /* Test each of our illegal UTF-8 sequences. */
+ for (bad_data = bad_utf8; *bad_data != NULL; bad_data++) {
+ utf8 = *bad_data;
+
+ /* Attempt to validate the UTF-8 string. */
+ xmlrpc_env_init(&env2);
+ xmlrpc_validate_utf8(&env2, utf8, strlen(utf8));
+ TEST_FAULT(&env2, XMLRPC_INVALID_UTF8_ERROR);
+ /* printf("Fault: %s\n", env2.fault_string); --Hand-checked */
+ xmlrpc_env_clean(&env2);
+
+ /* Attempt to decode the UTF-8 string. */
+ xmlrpc_env_init(&env2);
+ output = xmlrpc_utf8_to_wcs(&env2, utf8, strlen(utf8));
+ TEST_FAULT(&env2, XMLRPC_INVALID_UTF8_ERROR);
+ TEST(output == NULL);
+ xmlrpc_env_clean(&env2);
+ }
+ xmlrpc_env_clean(&env);
+#endif /* HAVE_UNICODE_WCHAR */
+}
+
+
+
+static void
+test_server_cgi_maybe(void) {
+
+#ifndef WIN32
+
+ test_server_cgi();
+
+#endif
+}
+
+
+
+static void
+test_client_maybe(void) {
+
+#ifndef WIN32 /* Must get Windows Curl transport working for this to work */
+
+ test_client();
+
+#endif
+}
+
+
+
+int
+main(int argc,
+ char ** argv ATTR_UNUSED) {
+
+ int retval;
+
+ if (argc-1 > 0) {
+ fprintf(stderr, "There are no arguments.");
+ retval = 1;
+ } else {
+ /* Add your test suites here. */
+ test_env();
+ test_mem_block();
+ test_base64_conversion();
+ printf("\n");
+ test_value();
+ test_bounds_checks();
+ printf("\n");
+ test_serialize();
+ test_parse_xml();
+ test_method_registry();
+ test_nesting_limit();
+ test_xml_size_limit();
+ test_sample_files();
+ printf("\n");
+ test_server_cgi_maybe();
+ test_server_abyss();
+
+ test_utf8_coding();
+
+ printf("\n");
+
+ test_client_maybe();
+
+ /* Summarize our test run. */
+ printf("\nRan %d tests, %d failed, %.1f%% passed\n",
+ total_tests, total_failures,
+ 100.0 - (100.0 * total_failures) / total_tests);
+
+ /* Print the final result. */
+ if (total_failures == 0) {
+ printf("OK\n");
+ retval = 0;
+ } else {
+ retval = 1;
+ printf("FAILED\n");
+ }
+ }
+ return retval;
+}
+
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */