diff --git a/.travis.yml b/.travis.yml index 4efbe916b..c111cbc8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ matrix: - env: TEST_NAME="arm-linux-gnueabi- (make)" script: - - ./configure --omit=Data/ODBC,Data/MySQL,Crypto,NetSSL && make -s -j2 CROSS_COMPILE=arm-linux-gnueabi- POCO_TARGET_OSARCH=armv7l + - ./configure --omit=Data/ODBC,Data/MySQL,Crypto,NetSSL,PageCompiler && make -s -j2 CROSS_COMPILE=arm-linux-gnueabi- POCO_TARGET_OSARCH=armv7l - env: TEST_NAME="gcc (CMake)" compiler: gcc diff --git a/Foundation/include/Poco/Thread.h b/Foundation/include/Poco/Thread.h index 541fa1bdc..d5653292c 100644 --- a/Foundation/include/Poco/Thread.h +++ b/Foundation/include/Poco/Thread.h @@ -122,7 +122,7 @@ public: /// May return 0 if the priority has not been explicitly set. static int getMinOSPriority(int policy = POLICY_DEFAULT); - /// Returns the mininum operating system-specific priority value, + /// Returns the minimum operating system-specific priority value, /// which can be passed to setOSPriority() for the given policy. static int getMaxOSPriority(int policy = POLICY_DEFAULT); @@ -149,6 +149,13 @@ public: void start(Callable target, void* pData = 0); /// Starts the thread with the given target and parameter. + template + void startFunc(Functor fn) + /// Starts the thread with the given functor object or lambda. + { + startImpl(new FunctorRunnable(fn)); + } + void join(); /// Waits until the thread completes execution. /// If multiple threads try to join the same @@ -221,7 +228,29 @@ protected: static int uniqueId(); /// Creates and returns a unique id for a thread. - + + template + class FunctorRunnable: public Runnable + { + public: + FunctorRunnable(const Functor& functor): + _functor(functor) + { + } + + ~FunctorRunnable() + { + } + + void run() + { + _functor(); + } + + private: + Functor _functor; + }; + private: Thread(const Thread&); Thread& operator = (const Thread&); diff --git a/Foundation/include/Poco/Thread_POSIX.h b/Foundation/include/Poco/Thread_POSIX.h index 120f7a86e..5bfae4a28 100644 --- a/Foundation/include/Poco/Thread_POSIX.h +++ b/Foundation/include/Poco/Thread_POSIX.h @@ -26,6 +26,7 @@ #include "Poco/Event.h" #include "Poco/RefCountedObject.h" #include "Poco/AutoPtr.h" +#include "Poco/SharedPtr.h" #include // must be limits.h (not ) for PTHREAD_STACK_MIN on Solaris #include @@ -61,16 +62,6 @@ public: POLICY_DEFAULT_IMPL = SCHED_OTHER }; - struct CallbackData: public RefCountedObject - { - CallbackData(): callback(0), pData(0) - { - } - - Callable callback; - void* pData; - }; - ThreadImpl(); ~ThreadImpl(); @@ -83,9 +74,7 @@ public: static int getMaxOSPriorityImpl(int policy); void setStackSizeImpl(int size); int getStackSizeImpl() const; - void startImpl(Runnable& target); - void startImpl(Callable target, void* pData = 0); - + void startImpl(SharedPtr pTarget); void joinImpl(); bool joinImpl(long milliseconds); bool isRunningImpl() const; @@ -96,7 +85,6 @@ public: protected: static void* runnableEntry(void* pThread); - static void* callableEntry(void* pThread); static int mapPrio(int prio, int policy = SCHED_OTHER); static int reverseMapPrio(int osPrio, int policy = SCHED_OTHER); @@ -129,8 +117,6 @@ private: struct ThreadData: public RefCountedObject { ThreadData(): - pRunnableTarget(0), - pCallbackTarget(0), thread(0), prio(PRIO_NORMAL_IMPL), policy(SCHED_OTHER), @@ -146,8 +132,7 @@ private: #endif } - Runnable* pRunnableTarget; - AutoPtr pCallbackTarget; + SharedPtr pRunnableTarget; pthread_t thread; int prio; int osPrio; @@ -186,8 +171,7 @@ inline int ThreadImpl::getOSPriorityImpl() const inline bool ThreadImpl::isRunningImpl() const { - return _pData->pRunnableTarget != 0 || - (_pData->pCallbackTarget.get() != 0 && _pData->pCallbackTarget->callback != 0); + return !_pData->pRunnableTarget.isNull(); } diff --git a/Foundation/include/Poco/Thread_WIN32.h b/Foundation/include/Poco/Thread_WIN32.h index a954c2a4a..598db8e7a 100644 --- a/Foundation/include/Poco/Thread_WIN32.h +++ b/Foundation/include/Poco/Thread_WIN32.h @@ -22,6 +22,7 @@ #include "Poco/Foundation.h" #include "Poco/Runnable.h" +#include "Poco/SharedPtr.h" #include "Poco/UnWindows.h" @@ -40,16 +41,6 @@ public: typedef unsigned (__stdcall *Entry)(void*); #endif - struct CallbackData - { - CallbackData(): callback(0), pData(0) - { - } - - Callable callback; - void* pData; - }; - enum Priority { PRIO_LOWEST_IMPL = THREAD_PRIORITY_LOWEST, @@ -76,9 +67,7 @@ public: static int getMaxOSPriorityImpl(int policy); void setStackSizeImpl(int size); int getStackSizeImpl() const; - void startImpl(Runnable& target); - void startImpl(Callable target, void* pData = 0); - + void startImpl(SharedPtr pTarget); void joinImpl(); bool joinImpl(long milliseconds); bool isRunningImpl() const; @@ -94,12 +83,6 @@ protected: static unsigned __stdcall runnableEntry(void* pThread); #endif -#if defined(_DLL) - static DWORD WINAPI callableEntry(LPVOID pThread); -#else - static unsigned __stdcall callableEntry(void* pThread); -#endif - void createImpl(Entry ent, void* pData); void threadCleanup(); @@ -129,12 +112,11 @@ private: DWORD _slot; }; - Runnable* _pRunnableTarget; - CallbackData _callbackTarget; - HANDLE _thread; - DWORD _threadId; - int _prio; - int _stackSize; + SharedPtr _pRunnableTarget; + HANDLE _thread; + DWORD _threadId; + int _prio; + int _stackSize; static CurrentThreadHolder _currentThreadHolder; }; diff --git a/Foundation/include/Poco/UTF8String.h b/Foundation/include/Poco/UTF8String.h index 36c280dea..d719b609e 100644 --- a/Foundation/include/Poco/UTF8String.h +++ b/Foundation/include/Poco/UTF8String.h @@ -35,6 +35,9 @@ struct Foundation_API UTF8 /// /// toUpper(), toUpperInPlace(), toLower() and toLowerInPlace() provide /// Unicode-based character case transformation for UTF-8 encoded strings. + /// + /// removeBOM() removes the UTF-8 Byte Order Mark sequence (0xEF, 0xBB, 0xBF) + /// from the beginning of the given string, if it's there. { static int icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2); static int icompare(const std::string& str1, const std::string& str2); @@ -51,6 +54,10 @@ struct Foundation_API UTF8 static std::string& toUpperInPlace(std::string& str); static std::string toLower(const std::string& str); static std::string& toLowerInPlace(std::string& str); + + static void removeBOM(std::string& str); + /// Remove the UTF-8 Byte Order Mark sequence (0xEF, 0xBB, 0xBF) + /// from the beginning of the string, if it's there. }; diff --git a/Foundation/src/Thread.cpp b/Foundation/src/Thread.cpp index 2b55fed79..e4a87dad0 100644 --- a/Foundation/src/Thread.cpp +++ b/Foundation/src/Thread.cpp @@ -38,6 +38,57 @@ namespace Poco { +namespace { + +class RunnableHolder: public Runnable +{ +public: + RunnableHolder(Runnable& target): + _target(target) + { + } + + ~RunnableHolder() + { + } + + void run() + { + _target.run(); + } + +private: + Runnable& _target; +}; + + +class CallableHolder: public Runnable +{ +public: + CallableHolder(Thread::Callable callable, void* pData): + _callable(callable), + _pData(pData) + { + } + + ~CallableHolder() + { + } + + void run() + { + _callable(_pData); + } + +private: + Thread::Callable _callable; + void* _pData; +}; + + +} // namespace + + Thread::Thread(): _id(uniqueId()), _name(makeName()), @@ -76,13 +127,13 @@ Thread::Priority Thread::getPriority() const void Thread::start(Runnable& target) { - startImpl(target); + startImpl(new RunnableHolder(target)); } void Thread::start(Callable target, void* pData) { - startImpl(target, pData); + startImpl(new CallableHolder(target, pData)); } diff --git a/Foundation/src/Thread_POSIX.cpp b/Foundation/src/Thread_POSIX.cpp index ae9707769..48af45cd1 100644 --- a/Foundation/src/Thread_POSIX.cpp +++ b/Foundation/src/Thread_POSIX.cpp @@ -104,7 +104,10 @@ void ThreadImpl::setPriorityImpl(int prio) _pData->policy = SCHED_OTHER; if (isRunningImpl()) { - struct sched_param par; + struct sched_param par; struct MyStruct + { + + }; par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER); if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par)) throw SystemException("cannot set thread priority"); @@ -117,7 +120,7 @@ void ThreadImpl::setOSPriorityImpl(int prio, int policy) { if (prio != _pData->osPrio || policy != _pData->policy) { - if (_pData->pRunnableTarget || _pData->pCallbackTarget) + if (_pData->pRunnableTarget) { struct sched_param par; par.sched_priority = prio; @@ -177,7 +180,7 @@ void ThreadImpl::setStackSizeImpl(int size) } -void ThreadImpl::startImpl(Runnable& target) +void ThreadImpl::startImpl(SharedPtr pTarget) { if (_pData->pRunnableTarget) throw SystemException("thread already running"); @@ -194,7 +197,7 @@ void ThreadImpl::startImpl(Runnable& target) } } - _pData->pRunnableTarget = ⌖ + _pData->pRunnableTarget = pTarget; if (pthread_create(&_pData->thread, &attributes, runnableEntry, this)) { _pData->pRunnableTarget = 0; @@ -224,56 +227,6 @@ void ThreadImpl::startImpl(Runnable& target) } -void ThreadImpl::startImpl(Callable target, void* pData) -{ - if (_pData->pCallbackTarget && _pData->pCallbackTarget->callback) - throw SystemException("thread already running"); - - pthread_attr_t attributes; - pthread_attr_init(&attributes); - - if (_pData->stackSize != 0) - { - if (0 != pthread_attr_setstacksize(&attributes, _pData->stackSize)) - throw SystemException("can not set thread stack size"); - } - - if (0 == _pData->pCallbackTarget.get()) - _pData->pCallbackTarget = new CallbackData; - - _pData->pCallbackTarget->callback = target; - _pData->pCallbackTarget->pData = pData; - - if (pthread_create(&_pData->thread, &attributes, callableEntry, this)) - { - _pData->pCallbackTarget->callback = 0; - _pData->pCallbackTarget->pData = 0; - pthread_attr_destroy(&attributes); - throw SystemException("cannot start thread"); - } - _pData->started = true; - pthread_attr_destroy(&attributes); - - if (_pData->policy == SCHED_OTHER) - { - if (_pData->prio != PRIO_NORMAL_IMPL) - { - struct sched_param par; - par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER); - if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par)) - throw SystemException("cannot set thread priority"); - } - } - else - { - struct sched_param par; - par.sched_priority = _pData->osPrio; - if (pthread_setschedparam(_pData->thread, _pData->policy, &par)) - throw SystemException("cannot set thread priority"); - } -} - - void ThreadImpl::joinImpl() { if (!_pData->started) return; @@ -409,48 +362,6 @@ void* ThreadImpl::runnableEntry(void* pThread) } -void* ThreadImpl::callableEntry(void* pThread) -{ - _currentThreadHolder.set(reinterpret_cast(pThread)); - -#if defined(POCO_OS_FAMILY_UNIX) - sigset_t sset; - sigemptyset(&sset); - sigaddset(&sset, SIGQUIT); - sigaddset(&sset, SIGTERM); - sigaddset(&sset, SIGPIPE); - pthread_sigmask(SIG_BLOCK, &sset, 0); -#endif - - ThreadImpl* pThreadImpl = reinterpret_cast(pThread); -#if defined(POCO_POSIX_DEBUGGER_THREAD_NAMES) - setThreadName(pThreadImpl->_pData->thread, reinterpret_cast(pThread)->getName().c_str()); -#endif - AutoPtr pData = pThreadImpl->_pData; - try - { - pData->pCallbackTarget->callback(pData->pCallbackTarget->pData); - } - catch (Exception& exc) - { - ErrorHandler::handle(exc); - } - catch (std::exception& exc) - { - ErrorHandler::handle(exc); - } - catch (...) - { - ErrorHandler::handle(); - } - - pData->pCallbackTarget->callback = 0; - pData->pCallbackTarget->pData = 0; - pData->done.set(); - return 0; -} - - int ThreadImpl::mapPrio(int prio, int policy) { int pmin = getMinOSPriorityImpl(policy); diff --git a/Foundation/src/Thread_WIN32.cpp b/Foundation/src/Thread_WIN32.cpp index 8a6c34f04..0eb2c4c4f 100644 --- a/Foundation/src/Thread_WIN32.cpp +++ b/Foundation/src/Thread_WIN32.cpp @@ -70,7 +70,6 @@ ThreadImpl::CurrentThreadHolder ThreadImpl::_currentThreadHolder; ThreadImpl::ThreadImpl(): - _pRunnableTarget(0), _thread(0), _threadId(0), _prio(PRIO_NORMAL_IMPL), @@ -105,30 +104,16 @@ void ThreadImpl::setOSPriorityImpl(int prio, int /* policy */) } -void ThreadImpl::startImpl(Runnable& target) +void ThreadImpl::startImpl(SharedPtr pTarget) { if (isRunningImpl()) throw SystemException("thread already running"); - _pRunnableTarget = ⌖ - + _pRunnableTarget = pTarget; createImpl(runnableEntry, this); } -void ThreadImpl::startImpl(Callable target, void* pData) -{ - if (isRunningImpl()) - throw SystemException("thread already running"); - - threadCleanup(); - _callbackTarget.callback = target; - _callbackTarget.pData = pData; - - createImpl(callableEntry, this); -} - - void ThreadImpl::createImpl(Entry ent, void* pData) { #if defined(_DLL) @@ -237,35 +222,4 @@ unsigned __stdcall ThreadImpl::runnableEntry(void* pThread) } -#if defined(_DLL) -DWORD WINAPI ThreadImpl::callableEntry(LPVOID pThread) -#else -unsigned __stdcall ThreadImpl::callableEntry(void* pThread) -#endif -{ - _currentThreadHolder.set(reinterpret_cast(pThread)); -#if defined(POCO_WIN32_DEBUGGER_THREAD_NAMES) - setThreadName(-1, reinterpret_cast(pThread)->getName().c_str()); -#endif - try - { - ThreadImpl* pTI = reinterpret_cast(pThread); - pTI->_callbackTarget.callback(pTI->_callbackTarget.pData); - } - catch (Exception& exc) - { - ErrorHandler::handle(exc); - } - catch (std::exception& exc) - { - ErrorHandler::handle(exc); - } - catch (...) - { - ErrorHandler::handle(); - } - return 0; -} - - } // namespace Poco diff --git a/Foundation/src/UTF8String.cpp b/Foundation/src/UTF8String.cpp index 8f10d8a0f..b7c6eb877 100644 --- a/Foundation/src/UTF8String.cpp +++ b/Foundation/src/UTF8String.cpp @@ -160,4 +160,16 @@ std::string& UTF8::toLowerInPlace(std::string& str) } +void UTF8::removeBOM(std::string& str) +{ + if (str.size() >= 3 + && static_cast(str[0]) == 0xEF + && static_cast(str[1]) == 0xBB + && static_cast(str[2]) == 0xBF) + { + str.erase(0, 3); + } +} + + } // namespace Poco diff --git a/Foundation/testsuite/src/ThreadTest.cpp b/Foundation/testsuite/src/ThreadTest.cpp index 1509e6e4b..e9fa73072 100644 --- a/Foundation/testsuite/src/ThreadTest.cpp +++ b/Foundation/testsuite/src/ThreadTest.cpp @@ -363,6 +363,45 @@ void ThreadTest::testThreadFunction() } +struct Functor +{ + void operator () () + { + ++MyRunnable::_staticVar; + } +}; + + +void ThreadTest::testThreadFunctor() +{ + Thread thread; + + assert (!thread.isRunning()); + + MyRunnable::_staticVar = 0; + thread.startFunc(Functor()); + thread.join(); + assert (1 == MyRunnable::_staticVar); + + assert (!thread.isRunning()); + +#if __cplusplus >= 201103L + + Thread thread2; + + assert (!thread2.isRunning()); + + MyRunnable::_staticVar = 0; + thread.startFunc([] () {MyRunnable::_staticVar++;}); + thread.join(); + assert (1 == MyRunnable::_staticVar); + + assert (!thread2.isRunning()); + +#endif +} + + void ThreadTest::testThreadStackSize() { int stackSize = 50000000; @@ -436,6 +475,7 @@ CppUnit::Test* ThreadTest::suite() CppUnit_addTest(pSuite, ThreadTest, testTrySleep); CppUnit_addTest(pSuite, ThreadTest, testThreadTarget); CppUnit_addTest(pSuite, ThreadTest, testThreadFunction); + CppUnit_addTest(pSuite, ThreadTest, testThreadFunctor); CppUnit_addTest(pSuite, ThreadTest, testThreadStackSize); CppUnit_addTest(pSuite, ThreadTest, testSleep); diff --git a/Foundation/testsuite/src/ThreadTest.h b/Foundation/testsuite/src/ThreadTest.h index b984e869c..3e9f50dae 100644 --- a/Foundation/testsuite/src/ThreadTest.h +++ b/Foundation/testsuite/src/ThreadTest.h @@ -37,6 +37,7 @@ public: void testTrySleep(); void testThreadTarget(); void testThreadFunction(); + void testThreadFunctor(); void testThreadStackSize(); void testSleep(); diff --git a/Net/include/Poco/Net/HTTPClientSession.h b/Net/include/Poco/Net/HTTPClientSession.h index e5dd85937..04e4e3ab4 100644 --- a/Net/include/Poco/Net/HTTPClientSession.h +++ b/Net/include/Poco/Net/HTTPClientSession.h @@ -1,7 +1,7 @@ // // HTTPClientSession.h // -// $Id: //poco/1.4/Net/include/Poco/Net/HTTPClientSession.h#7 $ +// $Id: //poco/1.4/Net/include/Poco/Net/HTTPClientSession.h#8 $ // // Library: Net // Package: HTTPClient @@ -100,6 +100,9 @@ public: HTTPClientSession(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT); /// Creates a HTTPClientSession using the given host and port. + HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig); + /// Creates a HTTPClientSession using the given host, port and proxy configuration. + virtual ~HTTPClientSession(); /// Destroys the HTTPClientSession and closes /// the underlying socket. diff --git a/Net/src/HTMLForm.cpp b/Net/src/HTMLForm.cpp index 92943092d..24ee4a60b 100644 --- a/Net/src/HTMLForm.cpp +++ b/Net/src/HTMLForm.cpp @@ -28,6 +28,7 @@ #include "Poco/URI.h" #include "Poco/String.h" #include "Poco/CountingStream.h" +#include "Poco/UTF8String.h" #include @@ -42,20 +43,31 @@ namespace Poco { namespace Net { -const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded"; -const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data"; -const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1; +const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded"; +const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data"; +const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1; -class HTMLFormCountingOutputStream : public CountingOutputStream +class HTMLFormCountingOutputStream: public CountingOutputStream { public: - HTMLFormCountingOutputStream() : _isvalid(true) {} + HTMLFormCountingOutputStream(): + _valid(true) + { + } + + bool isValid() const + { + return _valid; + } + + void setValid(bool v) + { + _valid = v; + } - bool getIsValid() const { return _isvalid; } - void setIsValid(bool v) { _isvalid = v; } private: - bool _isvalid; + bool _valid; }; @@ -238,7 +250,7 @@ std::streamsize HTMLForm::calculateContentLength() HTMLFormCountingOutputStream c; write(c); - if (c.getIsValid()) + if (c.isValid()) return c.chars(); else return UNKNOWN_CONTENT_LENGTH; @@ -274,6 +286,7 @@ void HTMLForm::readUrl(std::istream& istr) int fields = 0; int ch = istr.get(); + bool isFirst = true; while (ch != eof) { if (_fieldLimit > 0 && fields == _fieldLimit) @@ -296,6 +309,11 @@ void HTMLForm::readUrl(std::istream& istr) ch = istr.get(); } } + // remove UTF-8 byte order mark from first name, if present + if (isFirst) + { + UTF8::removeBOM(name); + } std::string decodedName; std::string decodedValue; URI::decode(name, decodedName); @@ -303,6 +321,7 @@ void HTMLForm::readUrl(std::istream& istr) add(decodedName, decodedValue); ++fields; if (ch == '&') ch = istr.get(); + isFirst = false; } } @@ -402,7 +421,7 @@ void HTMLForm::writeMultipart(std::ostream& ostr) if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH) costr->addChars(static_cast(partlen)); else - costr->setIsValid(false); + costr->setValid(false); } else StreamCopier::copyStream(ita->pSource->stream(), ostr); diff --git a/Net/src/HTTPClientSession.cpp b/Net/src/HTTPClientSession.cpp index ccf16d704..b10f56e20 100644 --- a/Net/src/HTTPClientSession.cpp +++ b/Net/src/HTTPClientSession.cpp @@ -1,7 +1,7 @@ // // HTTPClientSession.cpp // -// $Id: //poco/1.4/Net/src/HTTPClientSession.cpp#14 $ +// $Id: //poco/1.4/Net/src/HTTPClientSession.cpp#15 $ // // Library: Net // Package: HTTPClient @@ -87,6 +87,18 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port) } +HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig): + _host(host), + _port(port), + _proxyConfig(proxyConfig), + _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), + _reconnect(false), + _mustReconnect(false), + _expectResponseBody(false) +{ +} + + HTTPClientSession::~HTTPClientSession() { } @@ -379,7 +391,8 @@ void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request) StreamSocket HTTPClientSession::proxyConnect() { - HTTPClientSession proxySession(getProxyHost(), getProxyPort()); + ProxyConfig emptyProxyConfig; + HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig); proxySession.setTimeout(getTimeout()); std::string targetAddress(_host); targetAddress.append(":"); diff --git a/Net/testsuite/src/HTMLFormTest.cpp b/Net/testsuite/src/HTMLFormTest.cpp index 3f0693571..318c66b83 100644 --- a/Net/testsuite/src/HTMLFormTest.cpp +++ b/Net/testsuite/src/HTMLFormTest.cpp @@ -191,6 +191,20 @@ void HTMLFormTest::testReadUrlPUT() } +void HTMLFormTest::testReadUrlBOM() +{ + HTTPRequest req("PUT", "/form.cgi?field0=value0"); + std::istringstream istr("\357\273\277field1=value1&field2=value%202&field3=value%3D3&field4=value%264"); + HTMLForm form(req, istr); + assert (form.size() == 5); + assert (form["field0"] == "value0"); + assert (form["field1"] == "value1"); + assert (form["field2"] == "value 2"); + assert (form["field3"] == "value=3"); + assert (form["field4"] == "value&4"); +} + + void HTMLFormTest::testReadMultipart() { std::istringstream istr( @@ -359,6 +373,7 @@ CppUnit::Test* HTMLFormTest::suite() CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlGET); CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPOST); CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPUT); + CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlBOM); CppUnit_addTest(pSuite, HTMLFormTest, testReadMultipart); CppUnit_addTest(pSuite, HTMLFormTest, testSubmit1); CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2); diff --git a/Net/testsuite/src/HTMLFormTest.h b/Net/testsuite/src/HTMLFormTest.h index 2da5923fa..7f9242d49 100644 --- a/Net/testsuite/src/HTMLFormTest.h +++ b/Net/testsuite/src/HTMLFormTest.h @@ -31,6 +31,7 @@ public: void testReadUrlGET(); void testReadUrlPOST(); void testReadUrlPUT(); + void testReadUrlBOM(); void testReadMultipart(); void testSubmit1(); void testSubmit2();