diff options
-rw-r--r-- | indra/llplugin/CMakeLists.txt | 17 | ||||
-rw-r--r-- | indra/llplugin/tests/llplugincookiestore_test.cpp | 178 |
2 files changed, 195 insertions, 0 deletions
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index def9fcbeae..441becbae0 100644 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -3,6 +3,7 @@ project(llplugin) include(00-Common) +include(CURL) include(LLCommon) include(LLImage) include(LLMath) @@ -55,3 +56,19 @@ list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) add_library (llplugin ${llplugin_SOURCE_FILES}) add_subdirectory(slplugin) + +# Add tests +include(LLAddBuildTest) +# UNIT TESTS +SET(llplugin_TEST_SOURCE_FILES + llplugincookiestore.cpp + ) + +# llplugincookiestore has a dependency on curl, so we need to link the curl library into the test. +set_source_files_properties( + llplugincookiestore.cpp + PROPERTIES + LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}" + ) + +LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}") diff --git a/indra/llplugin/tests/llplugincookiestore_test.cpp b/indra/llplugin/tests/llplugincookiestore_test.cpp new file mode 100644 index 0000000000..e3e8ac9804 --- /dev/null +++ b/indra/llplugin/tests/llplugincookiestore_test.cpp @@ -0,0 +1,178 @@ +#include "linden_common.h" +#include "../test/lltut.h" + +#include "../llplugincookiestore.h" + + +namespace tut +{ + // Main Setup + struct LLPluginCookieStoreFixture + { + LLPluginCookieStoreFixture() + { + // We need dates definitively in the past and the future to properly test cookie expiration. + LLDate now = LLDate::now(); + LLDate past(now.secondsSinceEpoch() - (60.0 * 60.0 * 24.0)); // 1 day in the past + LLDate future(now.secondsSinceEpoch() + (60.0 * 60.0 * 24.0)); // 1 day in the future + + mPastString = past.asRFC1123(); + mFutureString = future.asRFC1123(); + } + + std::string mPastString; + std::string mFutureString; + LLPluginCookieStore mCookieStore; + + // List of cookies used for validation + std::list<std::string> mCookies; + + // This sets up mCookies from a string returned by one of the functions in LLPluginCookieStore + void setCookies(const std::string &cookies) + { + mCookies.clear(); + std::string::size_type start = 0; + + while(start != std::string::npos) + { + std::string::size_type end = cookies.find_first_of("\r\n", start); + if(end > start) + { + std::string line(cookies, start, end - start); + if(line.find_first_not_of("\r\n\t ") != std::string::npos) + { + // The line has some non-whitespace characters. Save it to the list. + mCookies.push_back(std::string(cookies, start, end - start)); + } + } + start = cookies.find_first_not_of("\r\n ", end); + } + } + + // This ensures that a cookie matching the one passed is in the list. + void ensureCookie(const std::string &cookie) + { + std::list<std::string>::iterator iter; + for(iter = mCookies.begin(); iter != mCookies.end(); iter++) + { + if(*iter == cookie) + { + // Found the cookie + // TODO: this should do a smarter equality comparison on the two cookies, instead of just a string compare. + return; + } + } + + // Didn't find this cookie + std::string message = "cookie not found: "; + message += cookie; + ensure(message, false); + } + + // This ensures that the number of cookies in the list matches what's expected. + void ensureSize(const std::string &message, size_t size) + { + if(mCookies.size() != size) + { + std::stringstream full_message; + + full_message << message << " (expected " << size << ", actual " << mCookies.size() << ")"; + ensure(full_message.str(), false); + } + } + }; + + typedef test_group<LLPluginCookieStoreFixture> factory; + typedef factory::object object; + factory tf("LLPluginCookieStore test"); + + // Tests + template<> template<> + void object::test<1>() + { + // Test 1: cookie uniqueness and update lists. + // Valid, distinct cookies: + + std::string cookie01 = "cookieA=value; domain=example.com; path=/"; + std::string cookie02 = "cookieB=value; domain=example.com; path=/"; // different name + std::string cookie03 = "cookieA=value; domain=foo.example.com; path=/"; // different domain + std::string cookie04 = "cookieA=value; domain=example.com; path=/bar/"; // different path + std::string cookie05 = "cookieC; domain=example.com; path=/"; // empty value + std::string cookie06 = "cookieD=value; domain=example.com; path=/; expires="; // different name, persistent cookie + cookie06 += mFutureString; + + mCookieStore.setCookies(cookie01); + mCookieStore.setCookies(cookie02); + mCookieStore.setCookies(cookie03); + mCookieStore.setCookies(cookie04); + mCookieStore.setCookies(cookie05); + mCookieStore.setCookies(cookie06); + + // Invalid cookies (these will get parse errors and not be added to the store) + + std::string badcookie01 = "cookieD=value; domain=example.com; path=/; foo=bar"; // invalid field name + std::string badcookie02 = "cookieE=value; path=/"; // no domain + + mCookieStore.setCookies(badcookie01); + mCookieStore.setCookies(badcookie02); + + // All cookies added so far should have been marked as "changed" + setCookies(mCookieStore.getChangedCookies()); + ensureSize("count of changed cookies", 6); + ensureCookie(cookie01); + ensureCookie(cookie02); + ensureCookie(cookie03); + ensureCookie(cookie04); + ensureCookie(cookie05); + ensureCookie(cookie06); + + // Save off the current state of the cookie store (we'll restore it later) + std::string savedCookies = mCookieStore.getAllCookies(); + + // Test replacing cookies + std::string cookie01a = "cookieA=newvalue; domain=example.com; path=/"; // updated value + std::string cookie02a = "cookieB=newvalue; domain=example.com; path=/; expires="; // remove cookie (by setting an expire date in the past) + cookie02a += mPastString; + + mCookieStore.setCookies(cookie01a); + mCookieStore.setCookies(cookie02a); + + // test for getting changed cookies + setCookies(mCookieStore.getChangedCookies()); + ensureSize("count of updated cookies", 2); + ensureCookie(cookie01a); + ensureCookie(cookie02a); + + // and for the state of the store after getting changed cookies + setCookies(mCookieStore.getAllCookies()); + ensureSize("count of valid cookies", 5); + ensureCookie(cookie01a); + ensureCookie(cookie03); + ensureCookie(cookie04); + ensureCookie(cookie05); + ensureCookie(cookie06); + + // Check that only the persistent cookie is returned here + setCookies(mCookieStore.getPersistentCookies()); + ensureSize("count of persistent cookies", 1); + ensureCookie(cookie06); + + // Restore the cookie store to a previous state and verify + mCookieStore.setAllCookies(savedCookies); + + // Since setAllCookies defaults to not marking cookies as changed, this list should be empty. + setCookies(mCookieStore.getChangedCookies()); + ensureSize("count of changed cookies after restore", 0); + + // Verify that the restore worked as it should have. + setCookies(mCookieStore.getAllCookies()); + ensureSize("count of restored cookies", 6); + ensureCookie(cookie01); + ensureCookie(cookie02); + ensureCookie(cookie03); + ensureCookie(cookie04); + ensureCookie(cookie05); + ensureCookie(cookie06); + } + +} |