aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/postprocessor_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/postprocessor_test.c')
-rw-r--r--src/daemon/postprocessor_test.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/daemon/postprocessor_test.c b/src/daemon/postprocessor_test.c
new file mode 100644
index 00000000..46f2463a
--- /dev/null
+++ b/src/daemon/postprocessor_test.c
@@ -0,0 +1,222 @@
1/*
2 This file is part of libmicrohttpd
3 (C) 2007 Christian Grothoff
4
5 libmicrohttpd is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 libmicrohttpd is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libmicrohttpd; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file postprocessor_test.c
23 * @brief Testcase for postprocessor
24 * @author Christian Grothoff
25 */
26
27#include "config.h"
28#include "microhttpd.h"
29#include "internal.h"
30#include <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33
34#ifndef WINDOWS
35#include <unistd.h>
36#endif
37
38/**
39 * Array of values that the value checker "wants".
40 * Each series of checks should be terminated by
41 * five NULL-entries.
42 */
43const char * want[] = {
44#define URL_DATA "abc=def&x=5"
45#define URL_START 0
46 "abc", NULL, NULL, NULL, "def",
47 "x", NULL, NULL, NULL, "5",
48#define URL_END (URL_START + 10)
49 NULL, NULL, NULL, NULL, NULL,
50#define FORM_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJoe Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata\r\n--AaB03x--\r\n"
51#define FORM_START (URL_END + 5)
52 "field1", NULL, NULL, NULL, "Joe Blow",
53 "pics", "file1.txt", "text/plain", "binary", "filedata",
54#define FORM_END (FORM_START + 10)
55 NULL, NULL, NULL, NULL, NULL,
56#define FORM_NESTED_DATA "--AaB03x\r\ncontent-disposition: form-data; name=\"field1\"\r\n\r\nJane Blow\r\n--AaB03x\r\ncontent-disposition: form-data; name=\"pics\"\r\nContent-type: multipart/mixed, boundary=BbC04y\r\n\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file1.txt\"\r\nContent-Type: text/plain\r\n\r\nfiledata1\r\n--BbC04y\r\nContent-disposition: attachment; filename=\"file2.gif\"\r\nContent-type: image/gif\r\nContent-Transfer-Encoding: binary\r\n\r\nfiledata2\r\n--BbC04y--\r\n--AaB03x--"
57#define FORM_NESTED_START (FORM_END + 5)
58 "field1", NULL, NULL, NULL, "Jane Blow",
59 "pics", "file1.txt", "text/plain", NULL, "filedata1",
60 "pics", "file2.gif", "image/gif", "binary", "filedata2",
61#define FORM_NESTED_END (FORM_NESTED_START + 15)
62 NULL, NULL, NULL, NULL, NULL,
63};
64
65static int
66mismatch(const char * a, const char * b) {
67 if (a == b)
68 return 0;
69 if ( (a == NULL) ||
70 (b == NULL) )
71 return 1;
72 return 0 != strcmp(a, b);
73}
74
75static int
76value_checker(void * cls,
77 enum MHD_ValueKind kind,
78 const char * key,
79 const char * filename,
80 const char * content_type,
81 const char * transfer_encoding,
82 const char * data,
83 size_t off,
84 size_t size) {
85 int * want_off = cls;
86 int idx = *want_off;
87
88 fprintf(stderr,
89 "VC: `%s' `%s' `%s' `%s' `%.*s'\n",
90 key, filename, content_type, transfer_encoding, size, data);
91 if (size == 0)
92 return MHD_YES;
93 if ( (idx < 0) ||
94 (want[idx] == NULL) ||
95 (0 != strcmp(key, want[idx])) ||
96 (mismatch(filename, want[idx+1])) ||
97 (mismatch(content_type, want[idx+2])) ||
98 (mismatch(transfer_encoding, want[idx+3])) ||
99 (0 != memcmp(data, &want[idx+4][off], size)) )
100 {
101 *want_off = -1;
102 return MHD_NO;
103 }
104 if (off + size == strlen(want[idx+4]))
105 *want_off = idx + 5;
106 return MHD_YES;
107
108}
109
110
111static int
112test_urlencoding() {
113 struct MHD_Connection connection;
114 struct MHD_HTTP_Header header;
115 struct MHD_PostProcessor * pp;
116 unsigned int want_off = URL_START;
117 int i;
118 int delta;
119 size_t size;
120
121 memset(&connection, 0, sizeof(struct MHD_Connection));
122 memset(&header, 0, sizeof(struct MHD_HTTP_Header));
123 connection.headers_received = &header;
124 header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
125 header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
126 header.kind = MHD_HEADER_KIND;
127 pp = MHD_create_post_processor(&connection,
128 1024,
129 &value_checker,
130 &want_off);
131 i = 0;
132 size = strlen(URL_DATA);
133 while (i < size) {
134 delta = 1 + random() % (size - i);
135 MHD_post_process(pp, &URL_DATA[i], delta);
136 i += delta;
137 }
138 MHD_destroy_post_processor(pp);
139 if (want_off != URL_END)
140 return 1;
141 return 0;
142}
143
144
145static int
146test_multipart() {
147 struct MHD_Connection connection;
148 struct MHD_HTTP_Header header;
149 struct MHD_PostProcessor * pp;
150 unsigned int want_off = FORM_START;
151 int i;
152 int delta;
153 size_t size;
154
155 memset(&connection, 0, sizeof(struct MHD_Connection));
156 memset(&header, 0, sizeof(struct MHD_HTTP_Header));
157 connection.headers_received = &header;
158 header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
159 header.value = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
160 header.kind = MHD_HEADER_KIND;
161 pp = MHD_create_post_processor(&connection,
162 1024,
163 &value_checker,
164 &want_off);
165 i = 0;
166 size = strlen(FORM_DATA);
167 while (i < size) {
168 delta = 1 + random() % (size - i);
169 MHD_post_process(pp, &FORM_DATA[i], delta);
170 i += delta;
171 }
172 MHD_destroy_post_processor(pp);
173 if (want_off != FORM_END)
174 return 2;
175 return 0;
176}
177
178
179static int
180test_nested_multipart() {
181 struct MHD_Connection connection;
182 struct MHD_HTTP_Header header;
183 struct MHD_PostProcessor * pp;
184 unsigned int want_off = FORM_NESTED_START;
185 int i;
186 int delta;
187 size_t size;
188
189 memset(&connection, 0, sizeof(struct MHD_Connection));
190 memset(&header, 0, sizeof(struct MHD_HTTP_Header));
191 connection.headers_received = &header;
192 header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
193 header.value = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA ", boundary=AaB03x";
194 header.kind = MHD_HEADER_KIND;
195 pp = MHD_create_post_processor(&connection,
196 1024,
197 &value_checker,
198 &want_off);
199 i = 0;
200 size = strlen(FORM_NESTED_DATA);
201 while (i < size) {
202 delta = 1 + random() % (size - i);
203 MHD_post_process(pp, &FORM_NESTED_DATA[i], delta);
204 i += delta;
205 }
206 MHD_destroy_post_processor(pp);
207 if (want_off != FORM_NESTED_END)
208 return 4;
209 return 0;
210}
211
212int
213main (int argc, char *const *argv)
214{
215 unsigned int errorCount = 0;
216 errorCount += test_urlencoding();
217 errorCount += test_multipart();
218 errorCount += test_nested_multipart();
219 if (errorCount != 0)
220 fprintf (stderr, "Error (code: %u)\n", errorCount);
221 return errorCount != 0; /* 0 == pass */
222}