diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/.gitignore | 5 | ||||
| -rw-r--r-- | test/Makefile.am | 16 | ||||
| -rw-r--r-- | test/test-header-parser.cc | 83 | ||||
| -rw-r--r-- | test/test-multipart-formdata-parser.cc | 109 | ||||
| -rw-r--r-- | test/test-query-parser.cc | 88 |
5 files changed, 301 insertions, 0 deletions
diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..8ab7990 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,5 @@ +/test-*.log +/*.trs +/test-header-parser +/test-multipart-formdata-parser +/test-query-parser diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..3017b6f --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,16 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = @DEFINES@ -I$(top_builddir)/src + +TESTS = test-query-parser test-header-parser test-multipart-formdata-parser + +check_PROGRAMS = $(TESTS) + +test_query_parser_SOURCES = test-query-parser.cc +test_query_parser_LDADD = $(top_srcdir)/src/libcgi.la + +test_header_parser_SOURCES = test-header-parser.cc +test_header_parser_LDADD = $(top_srcdir)/src/libcgi.la + +test_multipart_formdata_parser_SOURCES = test-multipart-formdata-parser.cc +test_multipart_formdata_parser_LDADD = $(top_srcdir)/src/libcgi.la diff --git a/test/test-header-parser.cc b/test/test-header-parser.cc new file mode 100644 index 0000000..c2b78f7 --- /dev/null +++ b/test/test-header-parser.cc @@ -0,0 +1,83 @@ +#include "common.hh" + +#include <cstdarg> +#include <cstdlib> +#include <iostream> + +#include "header_parser.hh" + +using namespace stuff; + +namespace { + +bool test(const char* in, const char* token, ...) { + std::string tmp_token; + std::map<std::string, std::string> tmp; + if (!HeaderParser::parse(in, &tmp_token, &tmp)) { + std::cerr << "expected success: " << in << std::endl; + return false; + } + if (tmp_token.compare(token) != 0) { + std::cerr << "expected token not to be " << tmp_token << " in: " + << in << std::endl; + return false; + } + va_list args; + va_start(args, token); + while (true) { + const char* key = va_arg(args, const char*); + if (!key) break; + const char* value = va_arg(args, const char*); + auto it = tmp.find(key); + if (it == tmp.end()) { + std::cerr << "expected a value for " << key + << " in: " << in << std::endl; + return false; + } + if (it->second.compare(value) != 0) { + std::cerr << "expected value for " << key << " not to be " + << it->second << " in: " << in << std::endl; + return false; + } + tmp.erase(it); + } + va_end(args); + for (auto& pair : tmp) { + std::cerr << "unexpected value for " << pair.first << ": " + << pair.second << " in: " << in << std::endl; + return false; + } + return true; +} + +bool test_fail(const std::string& in) { + std::string token; + if (!HeaderParser::parse(in, &token, nullptr)) return true; + std::cerr << "expected fail: " << in << std::endl; + return false; +} + +} // namespace + +int main() { + unsigned int ok = 0, tot = 0; + + tot++; if (test("text/html", "text/html", NULL)) ok++; + tot++; if (test("text/html;charset=utf-8", + "text/html", "charset", "utf-8", NULL)) ok++; + tot++; if (test("text/html;charset=UTF-8", + "text/html", "charset", "utf-8", NULL)) ok++; + tot++; if (test("Text/HTML;Charset=\"utf-8\"", + "text/html", "charset", "utf-8", NULL)) ok++; + tot++; if (test("text/html; charset=\"utf-8\"", + "text/html", "charset", "utf-8", NULL)) ok++; + tot++; if (test("a/b; key=\"\\\"\"", "a/b", "key", "\"", NULL)) ok++; + tot++; if (test_fail("")) ok++; + tot++; if (test_fail("text/html;charset = utf-8")) ok++; + tot++; if (test_fail("a/b;key=\"")) ok++; + tot++; if (test_fail("a/b;key=\"\\")) ok++; + tot++; if (test_fail("a/b;key=\"\\\"")) ok++; + + std::cout << "OK " << ok << "/" << tot << std::endl; + return ok == tot ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/test-multipart-formdata-parser.cc b/test/test-multipart-formdata-parser.cc new file mode 100644 index 0000000..a5b57e0 --- /dev/null +++ b/test/test-multipart-formdata-parser.cc @@ -0,0 +1,109 @@ +#include "common.hh" + +#include <cstdarg> +#include <cstdlib> +#include <iostream> + +#include "multipart_formdata_parser.hh" + +using namespace stuff; + +namespace { + +bool test(const std::string& in, const char* boundary, ...) { + std::map<std::string, std::string> tmp; + std::vector<char> data(in.begin(), in.end()); + if (!MultipartFormDataParser::parse(data, boundary, &tmp)) { + std::cerr << "expected success: " << in << std::endl; + return false; + } + va_list args; + va_start(args, boundary); + while (true) { + const char* key = va_arg(args, const char*); + if (!key) break; + const char* value = va_arg(args, const char*); + auto it = tmp.find(key); + if (it == tmp.end()) { + std::cerr << "expected a value for " << key + << " in: " << in << std::endl; + return false; + } + if (it->second.compare(value) != 0) { + std::cerr << "expected value for " << key << " not to be " + << it->second << " in: " << in << std::endl; + return false; + } + tmp.erase(it); + } + va_end(args); + for (auto& pair : tmp) { + std::cerr << "unexpected value for " << pair.first << ": " + << pair.second << " in: " << in << std::endl; + return false; + } + return true; +} + +bool test_fail(const std::string& in, const std::string& boundary) { + std::map<std::string, std::string> tmp; + std::vector<char> data(in.begin(), in.end()); + if (!MultipartFormDataParser::parse(data, boundary, &tmp)) return true; + std::cerr << "expected fail: " << in << std::endl; + return false; +} + +} // namespace + +int main() { + unsigned int ok = 0, tot = 0; + + tot++; if (test("", "AaB03x", NULL)) ok++; + + tot++; if (test( +"--AaB03x\r\n" +"Content-Disposition: form-data; name=\"submit-name\"\r\n" +"\r\n" +"Larry\r\n" +"--AaB03x\r\n" +"Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r\n" +"Content-Type: text/plain\r\n" +"\r\n" +"... contents of file1.txt ...\r\n" +"--AaB03x--\r\n", +"AaB03x", +"submit-name", "Larry", +"files", "... contents of file1.txt ...", +NULL)) ok++; + + tot++; if (test( +"--AaB03x\r\n" +"Content-Disposition: form-data; name=\"submit-name\"\r\n" +"\r\n" +"Larry\r\n" +"--AaB03x\r\n" +"Content-Disposition: form-data; name=\"files\"\r\n" +"Content-Type: multipart/mixed; boundary=BbC04y\r\n" +"\r\n" +"--BbC04y\r\n" +"Content-Disposition: file; filename=\"file1.txt\"\r\n" +"Content-Type: text/plain\r\n" +"\r\n" +"... contents of file1.txt ...\r\n" +"--BbC04y\r\n" +"Content-Disposition: file; filename=\"file2.gif\"\r\n" +"Content-Type: image/gif\r\n" +"Content-Transfer-Encoding: binary\r\n" +"\r\n" +"...contents of file2.gif...\r\n" +"--BbC04y--\r\n" +"--AaB03x--\r\n", +"AaB03x", +"submit-name", "Larry", +NULL)) ok++; + + tot++; if (test_fail("--X", "X")) ok++; + + std::cout << "OK " << ok << "/" << tot << std::endl; + return ok == tot ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/test-query-parser.cc b/test/test-query-parser.cc new file mode 100644 index 0000000..d6d10cd --- /dev/null +++ b/test/test-query-parser.cc @@ -0,0 +1,88 @@ +#include "common.hh" + +#include <cstdarg> +#include <cstdlib> +#include <iostream> + +#include "query_parser.hh" + +using namespace stuff; + +namespace { + +bool test(const char* in, ...) { + std::map<std::string, std::string> tmp; + if (!QueryParser::parse(in, &tmp)) { + std::cerr << "expected success: " << in << std::endl; + return false; + } + va_list args; + va_start(args, in); + while (true) { + const char* key = va_arg(args, const char*); + if (!key) break; + const char* value = va_arg(args, const char*); + auto it = tmp.find(key); + if (it == tmp.end()) { + std::cerr << "expected a value for " << key + << " in: " << in << std::endl; + return false; + } + if (it->second.compare(value) != 0) { + std::cerr << "expected value for " << key << " not to be " + << it->second << " in: " << in << std::endl; + return false; + } + tmp.erase(it); + } + va_end(args); + for (auto& pair : tmp) { + std::cerr << "unexpected value for " << pair.first << ": " + << pair.second << " in: " << in << std::endl; + return false; + } + return true; +} + +bool test_fail(const std::string& in) { + std::map<std::string, std::string> tmp; + if (!QueryParser::parse(in, &tmp)) return true; + std::cerr << "expected fail: " << in << std::endl; + return false; +} + +} // namespace + +int main() { + unsigned int ok = 0, tot = 0; + + tot++; if (test("", NULL)) ok++; + tot++; if (test("key=value", "key", "value", NULL)) ok++; + tot++; if (test("?key=value", "key", "value", NULL)) ok++; + tot++; if (test("?key=value&", "key", "value", NULL)) ok++; + tot++; if (test("key=value&foo=bar", + "key", "value", "foo", "bar", NULL)) ok++; + tot++; if (test("key=value&key=bar", "key", "bar", NULL)) ok++; + tot++; if (test("key=", "key", "", NULL)) ok++; + tot++; if (test("key=%c3%A5", "key", "\xc3\xa5", NULL)) ok++; + tot++; if (test("key=foo%20bar", "key", "foo bar", NULL)) ok++; + tot++; if (test("key=foo+bar", "key", "foo bar", NULL)) ok++; + tot++; + if (test("first=this+is+a+field&second=was+it+clear+%28already%29%3F", + "first", "this is a field", + "second", "was it clear (already)?", + NULL)) ok++; + tot++; if (test_fail("=value")) ok++; + tot++; if (test_fail("=")) ok++; + tot++; if (test_fail("\xc3\xa5")) ok++; + tot++; if (test_fail("&&")) ok++; + tot++; if (test_fail("key=&&")) ok++; + tot++; if (test_fail("==")) ok++; + tot++; if (test_fail("=&=")) ok++; + tot++; if (test_fail("%")) ok++; + tot++; if (test_fail("%A")) ok++; + tot++; if (test_fail("%1z")) ok++; + + std::cout << "OK " << ok << "/" << tot << std::endl; + return ok == tot ? EXIT_SUCCESS : EXIT_FAILURE; +} |
