<commit_before>#include "curltools.h"

#include "json_spirit.h"
#include "util.h"
#include <boost/thread.hpp>
#include <iostream>
#include <openssl/ssl.h>

boost::once_flag init_openssl_once_flag     = BOOST_ONCE_INIT;
boost::once_flag init_curl_global_once_flag = BOOST_ONCE_INIT;
boost::mutex     curl_global_init_lock;

class CurlCleaner
{
    CURL* curl_obj_to_clean;

public:
    CurlCleaner(CURL* Curl_obj_to_clean) : curl_obj_to_clean(Curl_obj_to_clean) {}

    ~CurlCleaner() { curl_easy_cleanup(curl_obj_to_clean); }
};

size_t cURLTools::CurlWrite_CallbackFunc_StdString(void* contents, size_t size, size_t nmemb,
                                                   std::deque<char>* s)
{
    size_t newLength = size * nmemb;
    size_t oldLength = s->size();
    try {
        s->resize(oldLength + newLength);
    } catch (std::bad_alloc& e) {
        std::stringstream msg;
        msg << "Error allocating memory: " << e.what() << std::endl;
        printf("%s", msg.str().c_str());
        return 0;
    }

    std::copy((char*)contents, (char*)contents + newLength, s->begin() + oldLength);
    return size * nmemb;
}

size_t cURLTools::CurlRead_CallbackFunc_StdString(void* dest, size_t /*size*/, size_t /*nmemb*/,
                                                  void* userp)
{
    std::string* from = (std::string*)userp;
    std::string* to   = (std::string*)dest;

    std::copy(from->begin(), from->end(), std::back_inserter(*to));

    return 0; /* no more data left to deliver */
}

size_t cURLTools::CurlWrite_CallbackFunc_File(void* contents, size_t size, size_t nmemb,
                                              boost::filesystem::fstream* fs)
{
    size_t newLength = size * nmemb;
    fs->write(reinterpret_cast<char*>(contents), newLength);
    return size * nmemb;
}

int cURLTools::CurlProgress_CallbackFunc(void*, double TotalToDownload, double NowDownloaded,
                                         double /*TotalToUpload*/, double /*NowUploaded*/)
{
    std::clog << "Download progress: " << ToString(NowDownloaded) << " / " << ToString(TotalToDownload)
              << std::endl;
    return CURLE_OK;
}

int cURLTools::CurlAtomicProgress_CallbackFunc(void* number, double TotalToDownload,
                                               double NowDownloaded, double /*TotalToUpload*/,
                                               double /*NowUploaded*/)
{
    std::atomic<float>* progress = reinterpret_cast<std::atomic<float>*>(number);
    float               val      = 0;
    if (NowDownloaded > 0.) {
        val = static_cast<float>( NowDownloaded / 1000 / 1000); // bytes to MB
        if (val < 0.0001) {
            val = 0;
        }
    }
    progress->store(val, std::memory_order_relaxed);
    return CURLE_OK;
}

void cURLTools::CurlGlobalInit_ThreadSafe()
{
    boost::lock_guard<boost::mutex> lg(curl_global_init_lock);
    curl_global_init(CURL_GLOBAL_DEFAULT);
}

void cURLTools::GetLargeFileFromHTTPS(const std::string& URL, long ConnectionTimeout,
                                      const boost::filesystem::path& targetPath,
                                      std::atomic<float>&            progress,
                                      const std::set<CURLcode>&      errorsToIgnore)
{

#if OPENSSL_VERSION_NUMBER < 0x10100000L
    boost::call_once(init_openssl_once_flag, SSL_library_init);
#else
    boost::call_once(init_openssl_once_flag, OPENSSL_init_ssl, 0,
                     static_cast<const ossl_init_settings_st*>(NULL));
#endif

    CURL*    curl;
    CURLcode res;

    boost::call_once(init_curl_global_once_flag, CurlGlobalInit_ThreadSafe);

    curl = curl_easy_init();
    boost::filesystem::fstream outputStream(targetPath, std::ios::out | std::ios::binary);

    std::string agent = GetUserAgent();
    if (curl) {

        CurlCleaner cleaner(curl);

        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
        curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_File);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Dark Secret Ninja/1.0");
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outputStream);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, agent.c_str());

        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, CurlAtomicProgress_CallbackFunc);
        curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progress);
        curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); //verbose output
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ConnectionTimeout);
        /* abort if slower than 1k bytes/sec during 60 seconds */
        curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60L);
        curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1000L);

        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);
        /* Check for errors */
        if (res != CURLE_OK && errorsToIgnore.find(res) == errorsToIgnore.cend()) {
            std::string errorMsg(curl_easy_strerror(res));
            printf("Curl error: %s\n", errorMsg.c_str());
            throw std::runtime_error(std::string(errorMsg).c_str());
        } else {
            long http_response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);
            if (http_response_code != 200) {
                std::string errorMsg("Error retrieving data with https protocol from URL \"" + URL +
                                     "\", error code: " + ToString(http_response_code) +
                                     ". Probably the URL is invalid.");
                printf("Curl http code error: %s\n", errorMsg.c_str());
                throw std::runtime_error(errorMsg);
            }
        }

        /* always cleanup */
        // This is replaced by a smart cleaning object with the destructor (CurlCleaner)
        // curl_easy_cleanup(curl);
    }
}

std::string cURLTools::GetUserAgent()
{
    std::string agent;
#ifdef QT_GUI
    agent += "Neblio-Qt";
#else
    agent += "Neblio";
#endif
    std::string version =
        std::to_string(CLIENT_VERSION_MAJOR) + "." + std::to_string(CLIENT_VERSION_MINOR) + "." +
        std::to_string(CLIENT_VERSION_REVISION) + "." + std::to_string(CLIENT_VERSION_BUILD);
    agent += "/";
    agent += version;
    return agent;
}

std::string cURLTools::GetFileFromHTTPS(const std::string& URL, long ConnectionTimeout,
                                        bool IncludeProgressBar)
{

#if OPENSSL_VERSION_NUMBER < 0x10100000L
    boost::call_once(init_openssl_once_flag, SSL_library_init);
#else
    boost::call_once(init_openssl_once_flag, OPENSSL_init_ssl, 0,
                     static_cast<const ossl_init_settings_st*>(NULL));
#endif

    CURL*    curl;
    CURLcode res;

    boost::call_once(init_curl_global_once_flag, CurlGlobalInit_ThreadSafe);

    curl = curl_easy_init();
    std::deque<char> s;

    std::string agent = GetUserAgent();
    if (curl) {

        CurlCleaner cleaner(curl);

        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
        curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Dark Secret Ninja/1.0");
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, agent.c_str());
        if (IncludeProgressBar) {
            curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
            curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, CurlProgress_CallbackFunc);
        } else {
            curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
        }
        // curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); //verbose output
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ConnectionTimeout);

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);
        /* Check for errors */
        if (res != CURLE_OK) {
            std::string errorMsg(curl_easy_strerror(res));
            throw std::runtime_error(std::string(errorMsg).c_str());
        } else {
            long http_response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);
            if (http_response_code != 200) {
                throw std::runtime_error("Error retrieving data with https protocol from URL \"" + URL +
                                         "\", error code: " + ToString(http_response_code) +
                                         ". Probably the URL is invalid.");
            }
        }

        /* always cleanup */
        // This is replaced by a smart cleaning object with the destructor (CurlCleaner)
        // curl_easy_cleanup(curl);
    }
    std::string fileStr(s.begin(), s.end());
    return fileStr;
}

std::string cURLTools::PostJsonToHTTPS(const std::string& URL, long ConnectionTimeout,
                                       const std::string& readdata, bool chunked)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
    boost::call_once(init_openssl_once_flag, SSL_library_init);
#else
    boost::call_once(init_openssl_once_flag, OPENSSL_init_ssl, 0,
                     static_cast<const ossl_init_settings_st*>(NULL));
#endif

    CURL*    curl;
    CURLcode res;

    boost::call_once(init_curl_global_once_flag, CurlGlobalInit_ThreadSafe);

    /* get a curl handle */
    curl = curl_easy_init();
    std::deque<char> writedata;
    std::string      agent = GetUserAgent();
    if (curl) {

        CurlCleaner cleaner(curl);

        struct curl_slist* headers = NULL;

        /* First set the URL that is about to receive our POST. This URL can
         just as well be a https:// URL if that is what should receive the
         data. */
        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
        //        curl_easy_setopt(curl, CURLOPT_READDATA, &readdata);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &writedata);
        curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, CurlRead_CallbackFunc_StdString);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
        /* Now specify the POST data */
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, readdata.c_str());
        curl_easy_setopt(curl, CURLOPT_POST, 1);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, agent.c_str());

        headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, "charsets: utf-8");

        // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); // verbose output
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ConnectionTimeout);
        if (chunked) {

            headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
            /* use curl_slist_free_all() after the *perform() call to free this
         list again */
        } else {
            /* Set the expected POST size. If you want to POST large amounts of data,
       consider CURLOPT_POSTFIELDSIZE_LARGE */
            curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)readdata.size());
        }

        /*
              Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue"
              header.  You can disable this header with CURLOPT_HTTPHEADER as usual.
              NOTE: if you want chunked transfer too, you need to combine these two
              since you can only set one list of headers with CURLOPT_HTTPHEADER. */

        /* A less good option would be to enforce HTTP 1.0, but that might also
               have other implications. */
        const bool disable_expect = false;
        if (disable_expect) {
            headers = curl_slist_append(headers, "Expect:");
            /* use curl_slist_free_all() after the *perform() call to free this
                 list again */
        }

        res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);
        /* Check for errors */
        if (res != CURLE_OK) {
            std::string errorMsg(curl_easy_strerror(res));
            throw std::runtime_error(std::string(errorMsg).c_str());
        } else {
            long http_response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);
            if (http_response_code != 200) {
                json_spirit::Value errorData;
                if (json_spirit::read(std::string(writedata.begin(), writedata.end()), errorData)) {
                    json_spirit::Value errorMsg;
                    errorMsg = json_spirit::find_value(errorData.get_obj(), "message");
                    throw std::runtime_error("Failed to create transaction with error: " +
                                             errorMsg.get_str());
                } else {
                    throw std::runtime_error("Error posting data with https protocol from URL \"" + URL +
                                             "\", error code: " + ToString(http_response_code) +
                                             ". Probably the URL is invalid. Could not retrieve more "
                                             "information on the error.");
                }
            }
        }

        /* always cleanup */
        // This is replaced by a smart cleaning object with the destructor (CurlCleaner)
        // curl_easy_cleanup(curl);
    }
    std::string fileStr(writedata.begin(), writedata.end());
    return fileStr;
}
<commit_msg>Remove verbose curl output<commit_after>#include "curltools.h"

#include "json_spirit.h"
#include "util.h"
#include <boost/thread.hpp>
#include <iostream>
#include <openssl/ssl.h>

boost::once_flag init_openssl_once_flag     = BOOST_ONCE_INIT;
boost::once_flag init_curl_global_once_flag = BOOST_ONCE_INIT;
boost::mutex     curl_global_init_lock;

class CurlCleaner
{
    CURL* curl_obj_to_clean;

public:
    CurlCleaner(CURL* Curl_obj_to_clean) : curl_obj_to_clean(Curl_obj_to_clean) {}

    ~CurlCleaner() { curl_easy_cleanup(curl_obj_to_clean); }
};

size_t cURLTools::CurlWrite_CallbackFunc_StdString(void* contents, size_t size, size_t nmemb,
                                                   std::deque<char>* s)
{
    size_t newLength = size * nmemb;
    size_t oldLength = s->size();
    try {
        s->resize(oldLength + newLength);
    } catch (std::bad_alloc& e) {
        std::stringstream msg;
        msg << "Error allocating memory: " << e.what() << std::endl;
        printf("%s", msg.str().c_str());
        return 0;
    }

    std::copy((char*)contents, (char*)contents + newLength, s->begin() + oldLength);
    return size * nmemb;
}

size_t cURLTools::CurlRead_CallbackFunc_StdString(void* dest, size_t /*size*/, size_t /*nmemb*/,
                                                  void* userp)
{
    std::string* from = (std::string*)userp;
    std::string* to   = (std::string*)dest;

    std::copy(from->begin(), from->end(), std::back_inserter(*to));

    return 0; /* no more data left to deliver */
}

size_t cURLTools::CurlWrite_CallbackFunc_File(void* contents, size_t size, size_t nmemb,
                                              boost::filesystem::fstream* fs)
{
    size_t newLength = size * nmemb;
    fs->write(reinterpret_cast<char*>(contents), newLength);
    return size * nmemb;
}

int cURLTools::CurlProgress_CallbackFunc(void*, double TotalToDownload, double NowDownloaded,
                                         double /*TotalToUpload*/, double /*NowUploaded*/)
{
    std::clog << "Download progress: " << ToString(NowDownloaded) << " / " << ToString(TotalToDownload)
              << std::endl;
    return CURLE_OK;
}

int cURLTools::CurlAtomicProgress_CallbackFunc(void* number, double TotalToDownload,
                                               double NowDownloaded, double /*TotalToUpload*/,
                                               double /*NowUploaded*/)
{
    std::atomic<float>* progress = reinterpret_cast<std::atomic<float>*>(number);
    float               val      = 0;
    if (NowDownloaded > 0.) {
        val = static_cast<float>( NowDownloaded / 1000 / 1000); // bytes to MB
        if (val < 0.0001) {
            val = 0;
        }
    }
    progress->store(val, std::memory_order_relaxed);
    return CURLE_OK;
}

void cURLTools::CurlGlobalInit_ThreadSafe()
{
    boost::lock_guard<boost::mutex> lg(curl_global_init_lock);
    curl_global_init(CURL_GLOBAL_DEFAULT);
}

void cURLTools::GetLargeFileFromHTTPS(const std::string& URL, long ConnectionTimeout,
                                      const boost::filesystem::path& targetPath,
                                      std::atomic<float>&            progress,
                                      const std::set<CURLcode>&      errorsToIgnore)
{

#if OPENSSL_VERSION_NUMBER < 0x10100000L
    boost::call_once(init_openssl_once_flag, SSL_library_init);
#else
    boost::call_once(init_openssl_once_flag, OPENSSL_init_ssl, 0,
                     static_cast<const ossl_init_settings_st*>(NULL));
#endif

    CURL*    curl;
    CURLcode res;

    boost::call_once(init_curl_global_once_flag, CurlGlobalInit_ThreadSafe);

    curl = curl_easy_init();
    boost::filesystem::fstream outputStream(targetPath, std::ios::out | std::ios::binary);

    std::string agent = GetUserAgent();
    if (curl) {

        CurlCleaner cleaner(curl);

        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
        curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_File);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Dark Secret Ninja/1.0");
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outputStream);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, agent.c_str());

        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, CurlAtomicProgress_CallbackFunc);
        curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progress);
        // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //verbose output
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ConnectionTimeout);
        /* abort if slower than 1k bytes/sec during 60 seconds */
        curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60L);
        curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1000L);

        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);
        /* Check for errors */
        if (res != CURLE_OK && errorsToIgnore.find(res) == errorsToIgnore.cend()) {
            std::string errorMsg(curl_easy_strerror(res));
            printf("Curl error: %s\n", errorMsg.c_str());
            throw std::runtime_error(std::string(errorMsg).c_str());
        } else {
            long http_response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);
            if (http_response_code != 200) {
                std::string errorMsg("Error retrieving data with https protocol from URL \"" + URL +
                                     "\", error code: " + ToString(http_response_code) +
                                     ". Probably the URL is invalid.");
                printf("Curl http code error: %s\n", errorMsg.c_str());
                throw std::runtime_error(errorMsg);
            }
        }

        /* always cleanup */
        // This is replaced by a smart cleaning object with the destructor (CurlCleaner)
        // curl_easy_cleanup(curl);
    }
}

std::string cURLTools::GetUserAgent()
{
    std::string agent;
#ifdef QT_GUI
    agent += "Neblio-Qt";
#else
    agent += "Neblio";
#endif
    std::string version =
        std::to_string(CLIENT_VERSION_MAJOR) + "." + std::to_string(CLIENT_VERSION_MINOR) + "." +
        std::to_string(CLIENT_VERSION_REVISION) + "." + std::to_string(CLIENT_VERSION_BUILD);
    agent += "/";
    agent += version;
    return agent;
}

std::string cURLTools::GetFileFromHTTPS(const std::string& URL, long ConnectionTimeout,
                                        bool IncludeProgressBar)
{

#if OPENSSL_VERSION_NUMBER < 0x10100000L
    boost::call_once(init_openssl_once_flag, SSL_library_init);
#else
    boost::call_once(init_openssl_once_flag, OPENSSL_init_ssl, 0,
                     static_cast<const ossl_init_settings_st*>(NULL));
#endif

    CURL*    curl;
    CURLcode res;

    boost::call_once(init_curl_global_once_flag, CurlGlobalInit_ThreadSafe);

    curl = curl_easy_init();
    std::deque<char> s;

    std::string agent = GetUserAgent();
    if (curl) {

        CurlCleaner cleaner(curl);

        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
        curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "Dark Secret Ninja/1.0");
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, agent.c_str());
        if (IncludeProgressBar) {
            curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
            curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, CurlProgress_CallbackFunc);
        } else {
            curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true);
        }
        // curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); //verbose output
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ConnectionTimeout);

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);
        /* Check for errors */
        if (res != CURLE_OK) {
            std::string errorMsg(curl_easy_strerror(res));
            throw std::runtime_error(std::string(errorMsg).c_str());
        } else {
            long http_response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);
            if (http_response_code != 200) {
                throw std::runtime_error("Error retrieving data with https protocol from URL \"" + URL +
                                         "\", error code: " + ToString(http_response_code) +
                                         ". Probably the URL is invalid.");
            }
        }

        /* always cleanup */
        // This is replaced by a smart cleaning object with the destructor (CurlCleaner)
        // curl_easy_cleanup(curl);
    }
    std::string fileStr(s.begin(), s.end());
    return fileStr;
}

std::string cURLTools::PostJsonToHTTPS(const std::string& URL, long ConnectionTimeout,
                                       const std::string& readdata, bool chunked)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
    boost::call_once(init_openssl_once_flag, SSL_library_init);
#else
    boost::call_once(init_openssl_once_flag, OPENSSL_init_ssl, 0,
                     static_cast<const ossl_init_settings_st*>(NULL));
#endif

    CURL*    curl;
    CURLcode res;

    boost::call_once(init_curl_global_once_flag, CurlGlobalInit_ThreadSafe);

    /* get a curl handle */
    curl = curl_easy_init();
    std::deque<char> writedata;
    std::string      agent = GetUserAgent();
    if (curl) {

        CurlCleaner cleaner(curl);

        struct curl_slist* headers = NULL;

        /* First set the URL that is about to receive our POST. This URL can
         just as well be a https:// URL if that is what should receive the
         data. */
        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
        //        curl_easy_setopt(curl, CURLOPT_READDATA, &readdata);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &writedata);
        curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, CurlRead_CallbackFunc_StdString);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
        /* Now specify the POST data */
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, readdata.c_str());
        curl_easy_setopt(curl, CURLOPT_POST, 1);
        curl_easy_setopt(curl, CURLOPT_USERAGENT, agent.c_str());

        headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, "charsets: utf-8");

        // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); // verbose output
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ConnectionTimeout);
        if (chunked) {

            headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
            /* use curl_slist_free_all() after the *perform() call to free this
         list again */
        } else {
            /* Set the expected POST size. If you want to POST large amounts of data,
       consider CURLOPT_POSTFIELDSIZE_LARGE */
            curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)readdata.size());
        }

        /*
              Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue"
              header.  You can disable this header with CURLOPT_HTTPHEADER as usual.
              NOTE: if you want chunked transfer too, you need to combine these two
              since you can only set one list of headers with CURLOPT_HTTPHEADER. */

        /* A less good option would be to enforce HTTP 1.0, but that might also
               have other implications. */
        const bool disable_expect = false;
        if (disable_expect) {
            headers = curl_slist_append(headers, "Expect:");
            /* use curl_slist_free_all() after the *perform() call to free this
                 list again */
        }

        res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        /* Perform the request, res will get the return code */
        res = curl_easy_perform(curl);
        /* Check for errors */
        if (res != CURLE_OK) {
            std::string errorMsg(curl_easy_strerror(res));
            throw std::runtime_error(std::string(errorMsg).c_str());
        } else {
            long http_response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);
            if (http_response_code != 200) {
                json_spirit::Value errorData;
                if (json_spirit::read(std::string(writedata.begin(), writedata.end()), errorData)) {
                    json_spirit::Value errorMsg;
                    errorMsg = json_spirit::find_value(errorData.get_obj(), "message");
                    throw std::runtime_error("Failed to create transaction with error: " +
                                             errorMsg.get_str());
                } else {
                    throw std::runtime_error("Error posting data with https protocol from URL \"" + URL +
                                             "\", error code: " + ToString(http_response_code) +
                                             ". Probably the URL is invalid. Could not retrieve more "
                                             "information on the error.");
                }
            }
        }

        /* always cleanup */
        // This is replaced by a smart cleaning object with the destructor (CurlCleaner)
        // curl_easy_cleanup(curl);
    }
    std::string fileStr(writedata.begin(), writedata.end());
    return fileStr;
}
<|endoftext|>


<commit_before>#include <stan/math/mix/mat.hpp>
#include <gtest/gtest.h>
#include <vector>

typedef std::vector<double> VEC;
using stan::math::fvar;
using stan::math::sort_indices_asc;
using stan::math::sort_indices_desc;
using stan::math::var;

void test_sort_indices_asc2(std::vector<double> val) {
  std::vector<fvar<var> > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<var>(val[i]));

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

void test_sort_indices_asc4(std::vector<double> val) {
  std::vector<fvar<fvar<var> > > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<fvar<var> >(val[i]));

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

void test_sort_indices_desc2(VEC val) {
  std::vector<fvar<var> > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<var>(val[i]));

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

void test_sort_indices_desc4(VEC val) {
  std::vector<fvar<fvar<var> > > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<fvar<var> >(val[i]));

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

template <typename T, int R, int C>
void test_sort_indices_asc2(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<var>, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  for (size_t i = 0U; i < val_size; i++)
    x.data()[i] = fvar<var>(val[i]);

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

template <typename T, int R, int C>
void test_sort_indices_asc4(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<fvar<var> >, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  for (size_t i = 0U; i < val_size; i++)
    x.data()[i] = fvar<fvar<var> >(val[i]);

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

template <typename T, int R, int C>
void test_sort_indices_desc2(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<var>, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  changes for (size_t i = 0U; i < val_size; i++) x.data()[i]
      = fvar<var>(val[i]);

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

template <typename T, int R, int C>
void test_sort_indices_desc4(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<fvar<var> >, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  for (size_t i = 0U; i < val_size; i++)
    x.data()[i] = fvar<fvar<var> >(val[i]);

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

TEST(AgradMixSortIndices, var) {
  VEC a;
  a.push_back(1);
  a.push_back(2);
  a.push_back(2);
  a.push_back(3);
  test_sort_indices_asc2(a);
  test_sort_indices_desc2(a);

  VEC b;
  b.push_back(1.1);
  b.push_back(2.2);
  b.push_back(33.1);
  b.push_back(-12.1);
  b.push_back(33.1);
  test_sort_indices_asc2(b);
  test_sort_indices_desc2(b);

  VEC c;
  c.push_back(1.1);
  c.push_back(-2);
  c.push_back(2.1);
  c.push_back(3);
  c.push_back(2.1);
  test_sort_indices_asc2(c);
  test_sort_indices_desc2(c);

  Eigen::RowVectorXd vec1(4);
  vec1 << 1, -33.1, 2.1, -33.1;
  test_sort_indices_asc2(vec1);
  test_sort_indices_desc2(vec1);

  Eigen::RowVectorXd vec2(5);
  vec2 << 1.1e-6, -2.3, 31.1, 1, -10.1;
  test_sort_indices_asc2(vec2);
  test_sort_indices_desc2(vec2);

  Eigen::VectorXd vec3(4);
  vec3 << -11.1, 2.2, -3.6, 2.2;
  test_sort_indices_asc2(vec3);
  test_sort_indices_desc2(vec3);

  Eigen::VectorXd vec4(3);
  vec4 << -10.1, 2.12, 3.102;
  test_sort_indices_asc2(vec4);
  test_sort_indices_desc2(vec4);

  Eigen::RowVectorXd vec5 = Eigen::RowVectorXd::Random(1, 10);
  test_sort_indices_asc2(vec5);
  test_sort_indices_desc2(vec5);

  Eigen::VectorXd vec6 = Eigen::VectorXd::Random(20, 1);
  test_sort_indices_asc2(vec6);
  test_sort_indices_desc2(vec6);
}

TEST(AgradMixSortIndices, fv_no_thrown) {
  Eigen::Matrix<fvar<var>, Eigen::Dynamic, 1> vec1;
  EXPECT_EQ(0, vec1.size());
  EXPECT_NO_THROW(sort_indices_asc(vec1));
  EXPECT_NO_THROW(sort_indices_desc(vec1));

  Eigen::Matrix<fvar<var>, 1, Eigen::Dynamic> vec2;
  EXPECT_EQ(0, vec2.size());
  EXPECT_NO_THROW(sort_indices_asc(vec2));
  EXPECT_NO_THROW(sort_indices_desc(vec2));
}

TEST(AgradMixSortIndices, ffv_sort) {
  VEC a;
  a.push_back(1);
  a.push_back(2);
  a.push_back(2);
  a.push_back(3);
  test_sort_indices_asc4(a);
  test_sort_indices_desc4(a);

  VEC b;
  b.push_back(1.1);
  b.push_back(2.2);
  b.push_back(33.1);
  b.push_back(-12.1);
  b.push_back(33.1);
  test_sort_indices_asc4(b);
  test_sort_indices_desc4(b);

  VEC c;
  c.push_back(1.1);
  c.push_back(-2);
  c.push_back(2.1);
  c.push_back(3);
  c.push_back(2.1);
  test_sort_indices_asc4(c);
  test_sort_indices_desc4(c);

  Eigen::RowVectorXd vec1(4);
  vec1 << 1, -33.1, 2.1, -33.1;
  test_sort_indices_asc4(vec1);
  test_sort_indices_desc4(vec1);

  Eigen::RowVectorXd vec2(5);
  vec2 << 1.1e-6, -2.3, 31.1, 1, -10.1;
  test_sort_indices_asc4(vec2);
  test_sort_indices_desc4(vec2);

  Eigen::VectorXd vec3(4);
  vec3 << -11.1, 2.2, -3.6, 2.2;
  test_sort_indices_asc4(vec3);
  test_sort_indices_desc4(vec3);

  Eigen::VectorXd vec4(3);
  vec4 << -10.1, 2.12, 3.102;
  test_sort_indices_asc4(vec4);
  test_sort_indices_desc4(vec4);

  Eigen::RowVectorXd vec5 = Eigen::RowVectorXd::Random(1, 10);
  test_sort_indices_asc4(vec5);
  test_sort_indices_desc4(vec5);

  Eigen::VectorXd vec6 = Eigen::VectorXd::Random(20, 1);
  test_sort_indices_asc4(vec6);
  test_sort_indices_desc4(vec6);
}

TEST(AgradMixSortIndices, ffv_no_thrown) {
  Eigen::Matrix<fvar<fvar<var> >, Eigen::Dynamic, 1> vec1;
  EXPECT_EQ(0, vec1.size());
  EXPECT_NO_THROW(sort_indices_asc(vec1));
  EXPECT_NO_THROW(sort_indices_desc(vec1));

  Eigen::Matrix<fvar<fvar<var> >, 1, Eigen::Dynamic> vec2;
  EXPECT_EQ(0, vec2.size());
  EXPECT_NO_THROW(sort_indices_asc(vec2));
  EXPECT_NO_THROW(sort_indices_desc(vec2));
}
<commit_msg>more cleanup<commit_after>#include <stan/math/mix/mat.hpp>
#include <gtest/gtest.h>
#include <vector>

typedef std::vector<double> VEC;
using stan::math::fvar;
using stan::math::sort_indices_asc;
using stan::math::sort_indices_desc;
using stan::math::var;

void test_sort_indices_asc2(std::vector<double> val) {
  std::vector<fvar<var> > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<var>(val[i]));

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

void test_sort_indices_asc4(std::vector<double> val) {
  std::vector<fvar<fvar<var> > > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<fvar<var> >(val[i]));

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

void test_sort_indices_desc2(VEC val) {
  std::vector<fvar<var> > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<var>(val[i]));

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

void test_sort_indices_desc4(VEC val) {
  std::vector<fvar<fvar<var> > > x;
  for (size_t i = 0U; i < val.size(); i++)
    x.push_back(fvar<fvar<var> >(val[i]));

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val.size(); i++)
    EXPECT_EQ(val_sorted[i], x_sorted[i]);

  for (size_t i = 0U; i < val.size(); i++)
    for (size_t j = 0U; j < val.size(); j++)
      if (val_sorted[i] == val[j])
        EXPECT_EQ(x_sorted[i], x[j]);
      else
        EXPECT_FALSE(x_sorted[i] == x[j]);
}

template <typename T, int R, int C>
void test_sort_indices_asc2(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<var>, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  for (size_t i = 0U; i < val_size; i++)
    x.data()[i] = fvar<var>(val[i]);

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

template <typename T, int R, int C>
void test_sort_indices_asc4(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<fvar<var> >, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  for (size_t i = 0U; i < val_size; i++)
    x.data()[i] = fvar<fvar<var> >(val[i]);

  std::vector<int> val_sorted = sort_indices_asc(val);
  std::vector<int> x_sorted = sort_indices_asc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

template <typename T, int R, int C>
void test_sort_indices_desc2(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<var>, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  for (size_t i = 0U; i < val_size; i++) x.data()[i]
      = fvar<var>(val[i]);

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

template <typename T, int R, int C>
void test_sort_indices_desc4(Eigen::Matrix<T, R, C> val) {
  typedef Eigen::Matrix<fvar<fvar<var> >, R, C> AVEC;

  const size_t val_size = val.size();

  AVEC x(val_size);
  for (size_t i = 0U; i < val_size; i++)
    x.data()[i] = fvar<fvar<var> >(val[i]);

  std::vector<int> val_sorted = sort_indices_desc(val);
  std::vector<int> x_sorted = sort_indices_desc(x);

  for (size_t i = 0U; i < val_size; i++)
    EXPECT_EQ(val_sorted.data()[i], x_sorted.data()[i]);

  for (size_t i = 0U; i < val_size; i++)
    for (size_t j = 0U; j < val_size; j++)
      if (val_sorted.data()[i] == val.data()[j])
        EXPECT_EQ(x_sorted.data()[i], x.data()[j]);
      else
        EXPECT_FALSE(x_sorted.data()[i] == x.data()[j]);
}

TEST(AgradMixSortIndices, var) {
  VEC a;
  a.push_back(1);
  a.push_back(2);
  a.push_back(2);
  a.push_back(3);
  test_sort_indices_asc2(a);
  test_sort_indices_desc2(a);

  VEC b;
  b.push_back(1.1);
  b.push_back(2.2);
  b.push_back(33.1);
  b.push_back(-12.1);
  b.push_back(33.1);
  test_sort_indices_asc2(b);
  test_sort_indices_desc2(b);

  VEC c;
  c.push_back(1.1);
  c.push_back(-2);
  c.push_back(2.1);
  c.push_back(3);
  c.push_back(2.1);
  test_sort_indices_asc2(c);
  test_sort_indices_desc2(c);

  Eigen::RowVectorXd vec1(4);
  vec1 << 1, -33.1, 2.1, -33.1;
  test_sort_indices_asc2(vec1);
  test_sort_indices_desc2(vec1);

  Eigen::RowVectorXd vec2(5);
  vec2 << 1.1e-6, -2.3, 31.1, 1, -10.1;
  test_sort_indices_asc2(vec2);
  test_sort_indices_desc2(vec2);

  Eigen::VectorXd vec3(4);
  vec3 << -11.1, 2.2, -3.6, 2.2;
  test_sort_indices_asc2(vec3);
  test_sort_indices_desc2(vec3);

  Eigen::VectorXd vec4(3);
  vec4 << -10.1, 2.12, 3.102;
  test_sort_indices_asc2(vec4);
  test_sort_indices_desc2(vec4);

  Eigen::RowVectorXd vec5 = Eigen::RowVectorXd::Random(1, 10);
  test_sort_indices_asc2(vec5);
  test_sort_indices_desc2(vec5);

  Eigen::VectorXd vec6 = Eigen::VectorXd::Random(20, 1);
  test_sort_indices_asc2(vec6);
  test_sort_indices_desc2(vec6);
}

TEST(AgradMixSortIndices, fv_no_thrown) {
  Eigen::Matrix<fvar<var>, Eigen::Dynamic, 1> vec1;
  EXPECT_EQ(0, vec1.size());
  EXPECT_NO_THROW(sort_indices_asc(vec1));
  EXPECT_NO_THROW(sort_indices_desc(vec1));

  Eigen::Matrix<fvar<var>, 1, Eigen::Dynamic> vec2;
  EXPECT_EQ(0, vec2.size());
  EXPECT_NO_THROW(sort_indices_asc(vec2));
  EXPECT_NO_THROW(sort_indices_desc(vec2));
}

TEST(AgradMixSortIndices, ffv_sort) {
  VEC a;
  a.push_back(1);
  a.push_back(2);
  a.push_back(2);
  a.push_back(3);
  test_sort_indices_asc4(a);
  test_sort_indices_desc4(a);

  VEC b;
  b.push_back(1.1);
  b.push_back(2.2);
  b.push_back(33.1);
  b.push_back(-12.1);
  b.push_back(33.1);
  test_sort_indices_asc4(b);
  test_sort_indices_desc4(b);

  VEC c;
  c.push_back(1.1);
  c.push_back(-2);
  c.push_back(2.1);
  c.push_back(3);
  c.push_back(2.1);
  test_sort_indices_asc4(c);
  test_sort_indices_desc4(c);

  Eigen::RowVectorXd vec1(4);
  vec1 << 1, -33.1, 2.1, -33.1;
  test_sort_indices_asc4(vec1);
  test_sort_indices_desc4(vec1);

  Eigen::RowVectorXd vec2(5);
  vec2 << 1.1e-6, -2.3, 31.1, 1, -10.1;
  test_sort_indices_asc4(vec2);
  test_sort_indices_desc4(vec2);

  Eigen::VectorXd vec3(4);
  vec3 << -11.1, 2.2, -3.6, 2.2;
  test_sort_indices_asc4(vec3);
  test_sort_indices_desc4(vec3);

  Eigen::VectorXd vec4(3);
  vec4 << -10.1, 2.12, 3.102;
  test_sort_indices_asc4(vec4);
  test_sort_indices_desc4(vec4);

  Eigen::RowVectorXd vec5 = Eigen::RowVectorXd::Random(1, 10);
  test_sort_indices_asc4(vec5);
  test_sort_indices_desc4(vec5);

  Eigen::VectorXd vec6 = Eigen::VectorXd::Random(20, 1);
  test_sort_indices_asc4(vec6);
  test_sort_indices_desc4(vec6);
}

TEST(AgradMixSortIndices, ffv_no_thrown) {
  Eigen::Matrix<fvar<fvar<var> >, Eigen::Dynamic, 1> vec1;
  EXPECT_EQ(0, vec1.size());
  EXPECT_NO_THROW(sort_indices_asc(vec1));
  EXPECT_NO_THROW(sort_indices_desc(vec1));

  Eigen::Matrix<fvar<fvar<var> >, 1, Eigen::Dynamic> vec2;
  EXPECT_EQ(0, vec2.size());
  EXPECT_NO_THROW(sort_indices_asc(vec2));
  EXPECT_NO_THROW(sort_indices_desc(vec2));
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QLibraryInfo>
#include <QDir>
#include <QProcess>
#include <QDebug>
#include "qmlruntime.h"
#include <QDeclarativeView>
#include <QSGView>
#include <QDeclarativeError>

#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
#define SRCDIR "."
#endif

class tst_examples : public QObject
{
    Q_OBJECT
public:
    tst_examples();

private slots:
    void examples_data();
    void examples();
    void sgexamples_data();
    void sgexamples();

    void namingConvention();
private:
    QStringList excludedDirs;

    void namingConvention(const QDir &);
    QStringList findQmlFiles(const QDir &);
};

tst_examples::tst_examples()
{
    // Add directories you want excluded here
    excludedDirs << "doc/src/snippets/declarative/visualdatamodel_rootindex";
    excludedDirs << "doc/src/snippets/declarative/qtbinding";
    excludedDirs << "doc/src/snippets/declarative/imports";

#ifdef QT_NO_WEBKIT
    excludedDirs << "examples/declarative/modelviews/webview";
    excludedDirs << "demos/declarative/webbrowser";
    excludedDirs << "doc/src/snippets/declarative/webview";
#endif

#ifdef QT_NO_XMLPATTERNS
    excludedDirs << "examples/declarative/xml/xmldata";
    excludedDirs << "demos/declarative/twitter";
    excludedDirs << "demos/declarative/flickr";
    excludedDirs << "demos/declarative/photoviewer";
#endif
}

/*
This tests that the demos and examples follow the naming convention required
to have them tested by the examples() test.
*/
void tst_examples::namingConvention(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return;
    }

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);

    bool seenQml = !files.isEmpty();
    bool seenLowercase = false;

    foreach (const QString &file, files) {
        if (file.at(0).isLower())
            seenLowercase = true;
    }

    if (!seenQml) {
        QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                QDir::NoSymLinks);
        foreach (const QString &dir, dirs) {
            QDir sub = d;
            sub.cd(dir);
            namingConvention(sub);
        }
    } else if(!seenLowercase) {
        QFAIL(qPrintable(QString(
            "Directory %1 violates naming convention; expected at least one qml file "
            "starting with lower case, got: %2"
        ).arg(d.absolutePath()).arg(files.join(","))));
    }
}

void tst_examples::namingConvention()
{
    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
    QString demos = QLibraryInfo::location(QLibraryInfo::DemosPath);

    namingConvention(QDir(examples));
    namingConvention(QDir(demos));
}

QStringList tst_examples::findQmlFiles(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return QStringList();
    }

    QStringList rv;

    QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
    if (cppfiles.isEmpty()) {
        QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                        QDir::Files);
        foreach (const QString &file, files) {
            if (file.at(0).isLower()) {
                rv << d.absoluteFilePath(file);
            }
        }
    }

    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                                   QDir::NoSymLinks);
    foreach (const QString &dir, dirs) {
        QDir sub = d;
        sub.cd(dir);
        rv << findQmlFiles(sub);
    }

    return rv;
}

/*
This test runs all the examples in the declarative UI source tree and ensures
that they start and exit cleanly.

Examples are any .qml files under the examples/ or demos/ directory that start
with a lower case letter.
*/
void tst_examples::examples_data()
{
    QTest::addColumn<QString>("file");

    QString examples = QLatin1String(SRCDIR) + "/../../../../demos/declarative/";
    QString demos = QLatin1String(SRCDIR) + "/../../../../examples/declarative/";
    QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/";

    QStringList files;
    files << findQmlFiles(QDir(examples));
    files << findQmlFiles(QDir(demos));
    files << findQmlFiles(QDir(snippets));

    foreach (const QString &file, files)
        QTest::newRow(qPrintable(file)) << file;
}

static void silentErrorsMsgHandler(QtMsgType, const char *)
{
}

void tst_examples::examples()
{
    QFETCH(QString, file);

    QDeclarativeViewer viewer;

    QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
    QVERIFY(viewer.open(file));
    qInstallMsgHandler(old);

    if (viewer.view()->status() == QDeclarativeView::Error)
        qWarning() << viewer.view()->errors();

    QCOMPARE(viewer.view()->status(), QDeclarativeView::Ready);
    viewer.show();

    QTest::qWaitForWindowShown(&viewer);
}

void tst_examples::sgexamples_data()
{
    examples_data();
}

void tst_examples::sgexamples()
{
    qputenv("QMLSCENE_IMPORT_NAME", "quick1");
    QFETCH(QString, file);

    QSGView view;

    QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
    view.setSource(file);
    qInstallMsgHandler(old);

    if (view.status() == QSGView::Error)
        qWarning() << view.errors();

    QCOMPARE(view.status(), QSGView::Ready);
    view.show();

    QTest::qWaitForWindowShown(&view);
}

QTEST_MAIN(tst_examples)

#include "tst_examples.moc"
<commit_msg>Fixed failure of tst_examples::namingConvention<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QLibraryInfo>
#include <QDir>
#include <QProcess>
#include <QDebug>
#include "qmlruntime.h"
#include <QDeclarativeView>
#include <QSGView>
#include <QDeclarativeError>

#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
#define SRCDIR "."
#endif

class tst_examples : public QObject
{
    Q_OBJECT
public:
    tst_examples();

private slots:
    void examples_data();
    void examples();
    void sgexamples_data();
    void sgexamples();

    void namingConvention();
private:
    QStringList excludedDirs;

    void namingConvention(const QDir &);
    QStringList findQmlFiles(const QDir &);
};

tst_examples::tst_examples()
{
    // Add directories you want excluded here
    excludedDirs << "doc/src/snippets/declarative/visualdatamodel_rootindex";
    excludedDirs << "doc/src/snippets/declarative/qtbinding";
    excludedDirs << "doc/src/snippets/declarative/imports";

#ifdef QT_NO_WEBKIT
    excludedDirs << "examples/declarative/modelviews/webview";
    excludedDirs << "demos/declarative/webbrowser";
    excludedDirs << "doc/src/snippets/declarative/webview";
#endif

#ifdef QT_NO_XMLPATTERNS
    excludedDirs << "examples/declarative/xml/xmldata";
    excludedDirs << "demos/declarative/twitter";
    excludedDirs << "demos/declarative/flickr";
    excludedDirs << "demos/declarative/photoviewer";
#endif
}

/*
This tests that the demos and examples follow the naming convention required
to have them tested by the examples() test.
*/
void tst_examples::namingConvention(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return;
    }

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);

    bool seenQml = !files.isEmpty();
    bool seenLowercase = false;

    foreach (const QString &file, files) {
        if (file.at(0).isLower())
            seenLowercase = true;
    }

    if (!seenQml) {
        QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                QDir::NoSymLinks);
        foreach (const QString &dir, dirs) {
            QDir sub = d;
            sub.cd(dir);
            namingConvention(sub);
        }
    } else if(!seenLowercase) {
        QFAIL(qPrintable(QString(
            "Directory %1 violates naming convention; expected at least one qml file "
            "starting with lower case, got: %2"
        ).arg(d.absolutePath()).arg(files.join(","))));
    }
}

void tst_examples::namingConvention()
{
    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);

    namingConvention(QDir(examples));
}

QStringList tst_examples::findQmlFiles(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return QStringList();
    }

    QStringList rv;

    QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
    if (cppfiles.isEmpty()) {
        QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                        QDir::Files);
        foreach (const QString &file, files) {
            if (file.at(0).isLower()) {
                rv << d.absoluteFilePath(file);
            }
        }
    }

    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                                   QDir::NoSymLinks);
    foreach (const QString &dir, dirs) {
        QDir sub = d;
        sub.cd(dir);
        rv << findQmlFiles(sub);
    }

    return rv;
}

/*
This test runs all the examples in the declarative UI source tree and ensures
that they start and exit cleanly.

Examples are any .qml files under the examples/ or demos/ directory that start
with a lower case letter.
*/
void tst_examples::examples_data()
{
    QTest::addColumn<QString>("file");

    QString examples = QLatin1String(SRCDIR) + "/../../../../demos/declarative/";
    QString demos = QLatin1String(SRCDIR) + "/../../../../examples/declarative/";
    QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/";

    QStringList files;
    files << findQmlFiles(QDir(examples));
    files << findQmlFiles(QDir(demos));
    files << findQmlFiles(QDir(snippets));

    foreach (const QString &file, files)
        QTest::newRow(qPrintable(file)) << file;
}

static void silentErrorsMsgHandler(QtMsgType, const char *)
{
}

void tst_examples::examples()
{
    QFETCH(QString, file);

    QDeclarativeViewer viewer;

    QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
    QVERIFY(viewer.open(file));
    qInstallMsgHandler(old);

    if (viewer.view()->status() == QDeclarativeView::Error)
        qWarning() << viewer.view()->errors();

    QCOMPARE(viewer.view()->status(), QDeclarativeView::Ready);
    viewer.show();

    QTest::qWaitForWindowShown(&viewer);
}

void tst_examples::sgexamples_data()
{
    examples_data();
}

void tst_examples::sgexamples()
{
    qputenv("QMLSCENE_IMPORT_NAME", "quick1");
    QFETCH(QString, file);

    QSGView view;

    QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
    view.setSource(file);
    qInstallMsgHandler(old);

    if (view.status() == QSGView::Error)
        qWarning() << view.errors();

    QCOMPARE(view.status(), QSGView::Ready);
    view.show();

    QTest::qWaitForWindowShown(&view);
}

QTEST_MAIN(tst_examples)

#include "tst_examples.moc"
<|endoftext|>


<commit_before>/** This file is part of Contacts daemon
 **
 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
 **
 ** Contact:  Nokia Corporation (info@qt.nokia.com)
 **
 ** GNU Lesser General Public License Usage
 ** This file may be used under the terms of the GNU Lesser General Public License
 ** version 2.1 as published by the Free Software Foundation and appearing in the
 ** file LICENSE.LGPL included in the packaging of this file.  Please review the
 ** following information to ensure the GNU Lesser General Public License version
 ** 2.1 requirements will be met:
 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 ** In addition, as a special exception, Nokia gives you certain additional rights.
 ** These rights are described in the Nokia Qt LGPL Exception version 1.1, included
 ** in the file LGPL_EXCEPTION.txt in this package.
 **
 ** Other Usage
 ** Alternatively, this file may be used in accordance with the terms and
 ** conditions contained in a signed written agreement between you and Nokia.
 **/

#include "test-birthday-plugin.h"

#include <test-common.h>

#include <extendedstorage.h>
#include <extendedcalendar.h>

#include <MGConfDataStore>
#include <MLocale>

#include <QContactBirthday>
#include <QContactName>

// A random ID, from plugins/birthday/cdbirthdaycalendar.cpp.
const QLatin1String calNotebookId("b1376da7-5555-1111-2222-227549c4e570");

static void loopWait(int ms)
{
    QTimer timer;
    timer.setInterval(ms);

    qDebug() << "Waiting for" << (ms/1000) << "seconds";

    QEventLoop loop;
    QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
    timer.start();
    loop.exec();
}

TestBirthdayPlugin::TestBirthdayPlugin(QObject *parent) :
    QObject(parent),
    mManager(0)
{
}

void TestBirthdayPlugin::init()
{
    const QLatin1String trackerManagerName = QLatin1String("tracker");

    mManager = new QContactManager(trackerManagerName, QMap<QString, QString>(), this);
    QVERIFY2(mManager->managerName() == trackerManagerName, "Unable to initialise QContactManager");
}

void TestBirthdayPlugin::initTestCase()
{
}

void TestBirthdayPlugin::testAddAndRemoveBirthday()
{
    const QString contactID = QUuid::createUuid().toString();
    const QDateTime contactBirthDate = QDateTime::currentDateTime();

    // Add contact with birthday to tracker.
    QContactName contactName;
    contactName.setCustomLabel(contactID);
    QContactBirthday contactBirthday;
    contactBirthday.setDateTime(contactBirthDate);
    QContact contact;
    QVERIFY(contact.saveDetail(&contactName));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Error saving contact to tracker");

    // Wait until calendar event gets to calendar.
    loopWait(3000);

    // Open calendar database, which should have been created by the birthday plugin.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check calendar database for contact.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    KCalCore::Event::List eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Delete the contact and see if the birthday is also deleted.
    QVERIFY2(mManager->removeContact(contact.localId()), "Unable to delete test contact from tracker database");

    // Wait until calendar event gets to calendar.
    loopWait(3000);

    // Search for any events in the calendar.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 0);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::testChangeBirthday()
{
    const QString contactID = QUuid::createUuid().toString();
    const QDateTime contactBirthDate = QDateTime::currentDateTime();

    // Add contact with birthday to tracker.
    QContactName contactName;
    contactName.setCustomLabel(contactID);
    QContactBirthday contactBirthday;
    contactBirthday.setDateTime(contactBirthDate);
    QContact contact;
    QVERIFY(contact.saveDetail(&contactName));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Error saving contact to tracker");

    // Wait until calendar event gets to calendar.
    loopWait(3000);

    // Open calendar database.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check calendar database for contact.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    KCalCore::Event::List eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Change the contact and see if the birthday is updated.
    contactBirthday.setDateTime(contactBirthDate.addDays(-3));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Unable to update test contact in tracker");

    // Wait until calendar event gets to calendar.
    loopWait(3000);

    // Search for any events in the calendar.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::testChangeName()
{
    const QString contactID = QUuid::createUuid().toString();
    const QDateTime contactBirthDate = QDateTime::currentDateTime();

    // Add contact with birthday to tracker.
    QContactName contactName;
    contactName.setCustomLabel(contactID);
    QContactBirthday contactBirthday;
    contactBirthday.setDateTime(contactBirthDate);
    QContact contact;
    QVERIFY(contact.saveDetail(&contactName));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Error saving contact to tracker");

    // Wait until calendar event gets to calendar.
    loopWait(3000);

    // Open calendar database.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check calendar database for contact.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    KCalCore::Event::List eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Change the contact name and see if the calendar is updated.
    const QString newContactID = QUuid::createUuid().toString();
    contactName.setCustomLabel(newContactID);
    QVERIFY(contact.saveDetail(&contactName));
    // TODO: Should it be necessary to refetch the contact to get the synthesised displayLabel?
    contact = mManager->contact(contact.localId());
    QVERIFY2(mManager->saveContact(&contact), "Unable to update test contact in tracker");

    // Wait until calendar event gets to calendar.
    loopWait(3000);

    // Search for any events in the calendar.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::testLocaleChange()
{
    MGConfDataStore store(QLatin1String("/meegotouch/i18n"));

    store.setValue(QLatin1String("language"), QLatin1String("en"));

    // Leave the time to react to locale change
    loopWait(1000);

    // Use the C locale so it can be changed to a different locale later.
    MLocale locale;
    QVERIFY2(locale.isValid(), "Invalid locale");

    if (not locale.isInstalledTrCatalog(QLatin1String("calendar"))) {
        locale.installTrCatalog(QLatin1String("calendar"));
    }

    locale.connectSettings();
    MLocale::setDefault(locale);

    // Open calendar database, which should have been created by the birthday plugin.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check if locale name for calendar matches calendar name.
    //QVERIFY2(locale.isInstalledTrCatalog(QLatin1String("calendar")), "Calendar locale catalog not installed");
    const QString cLocaleCalendarName = qtTrId("qtn_caln_birthdays");
    QCOMPARE(storage->notebook(calNotebookId)->name(), cLocaleCalendarName);

    // Change locale and check name again.
    store.setValue(QLatin1String("language"), QLatin1String("fi"));

    loopWait(1000);

    const QString finnishLocaleCalendarName = qtTrId("qtn_caln_birthdays");

    QVERIFY2(storage->notebook(calNotebookId)->name() != cLocaleCalendarName, "Calendar name was not updated on locale change");
    QCOMPARE(storage->notebook(calNotebookId)->name(), finnishLocaleCalendarName);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::cleanupTestCase()
{
}

void TestBirthdayPlugin::cleanup()
{
    // Remove all contacts modified during the test run.
    // This could fail if the contacts were already removed, so the response is ignored.
    mManager->removeContacts(mContactLocalIDs.toList());

    mContactLocalIDs.clear();

    delete mManager;

    mManager = 0;
}

int TestBirthdayPlugin::countCalendarEvents(const KCalCore::Event::List &eventList,
                                            const QContact &contact) const
{
    int found = 0;
    Q_FOREACH(const QSharedPointer<KCalCore::Event> event, eventList) {
        if(event->dtStart().date() == contact.detail<QContactBirthday>().date()) {
            if(event->summary() == contact.detail<QContactDisplayLabel>().label()) {
                found++;
            }
        }
    }

    return found;
}

bool TestBirthdayPlugin::saveContact(QContact &contact)
{
    mContactLocalIDs.insert(contact.localId());

    return mManager->saveContact(&contact);
}

CONTACTSD_TEST_MAIN(TestBirthdayPlugin)
<commit_msg>birthday: test: Wait at least 10 seconds for calendar events<commit_after>/** This file is part of Contacts daemon
 **
 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
 **
 ** Contact:  Nokia Corporation (info@qt.nokia.com)
 **
 ** GNU Lesser General Public License Usage
 ** This file may be used under the terms of the GNU Lesser General Public License
 ** version 2.1 as published by the Free Software Foundation and appearing in the
 ** file LICENSE.LGPL included in the packaging of this file.  Please review the
 ** following information to ensure the GNU Lesser General Public License version
 ** 2.1 requirements will be met:
 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 ** In addition, as a special exception, Nokia gives you certain additional rights.
 ** These rights are described in the Nokia Qt LGPL Exception version 1.1, included
 ** in the file LGPL_EXCEPTION.txt in this package.
 **
 ** Other Usage
 ** Alternatively, this file may be used in accordance with the terms and
 ** conditions contained in a signed written agreement between you and Nokia.
 **/

#include "test-birthday-plugin.h"

#include <test-common.h>

#include <extendedstorage.h>
#include <extendedcalendar.h>

#include <MGConfDataStore>
#include <MLocale>

#include <QContactBirthday>
#include <QContactName>

// A random ID, from plugins/birthday/cdbirthdaycalendar.cpp.
const QLatin1String calNotebookId("b1376da7-5555-1111-2222-227549c4e570");

static const int calendarTimeout = 12000; // ms

static void loopWait(int ms)
{
    QTimer timer;
    timer.setInterval(ms);

    qDebug() << "Waiting for" << (ms/1000) << "seconds";

    QEventLoop loop;
    QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
    timer.start();
    loop.exec();
}

TestBirthdayPlugin::TestBirthdayPlugin(QObject *parent) :
    QObject(parent),
    mManager(0)
{
}

void TestBirthdayPlugin::init()
{
    const QLatin1String trackerManagerName = QLatin1String("tracker");

    mManager = new QContactManager(trackerManagerName, QMap<QString, QString>(), this);
    QVERIFY2(mManager->managerName() == trackerManagerName, "Unable to initialise QContactManager");
}

void TestBirthdayPlugin::initTestCase()
{
}

void TestBirthdayPlugin::testAddAndRemoveBirthday()
{
    const QString contactID = QUuid::createUuid().toString();
    const QDateTime contactBirthDate = QDateTime::currentDateTime();

    // Add contact with birthday to tracker.
    QContactName contactName;
    contactName.setCustomLabel(contactID);
    QContactBirthday contactBirthday;
    contactBirthday.setDateTime(contactBirthDate);
    QContact contact;
    QVERIFY(contact.saveDetail(&contactName));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Error saving contact to tracker");

    // Wait until calendar event gets to calendar.
    loopWait(calendarTimeout);

    // Open calendar database, which should have been created by the birthday plugin.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check calendar database for contact.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    KCalCore::Event::List eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Delete the contact and see if the birthday is also deleted.
    QVERIFY2(mManager->removeContact(contact.localId()), "Unable to delete test contact from tracker database");

    // Wait until calendar event gets to calendar.
    loopWait(calendarTimeout);

    // Search for any events in the calendar.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 0);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::testChangeBirthday()
{
    const QString contactID = QUuid::createUuid().toString();
    const QDateTime contactBirthDate = QDateTime::currentDateTime();

    // Add contact with birthday to tracker.
    QContactName contactName;
    contactName.setCustomLabel(contactID);
    QContactBirthday contactBirthday;
    contactBirthday.setDateTime(contactBirthDate);
    QContact contact;
    QVERIFY(contact.saveDetail(&contactName));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Error saving contact to tracker");

    // Wait until calendar event gets to calendar.
    loopWait(calendarTimeout);

    // Open calendar database.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check calendar database for contact.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    KCalCore::Event::List eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Change the contact and see if the birthday is updated.
    contactBirthday.setDateTime(contactBirthDate.addDays(-3));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Unable to update test contact in tracker");

    // Wait until calendar event gets to calendar.
    loopWait(calendarTimeout);

    // Search for any events in the calendar.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::testChangeName()
{
    const QString contactID = QUuid::createUuid().toString();
    const QDateTime contactBirthDate = QDateTime::currentDateTime();

    // Add contact with birthday to tracker.
    QContactName contactName;
    contactName.setCustomLabel(contactID);
    QContactBirthday contactBirthday;
    contactBirthday.setDateTime(contactBirthDate);
    QContact contact;
    QVERIFY(contact.saveDetail(&contactName));
    QVERIFY(contact.saveDetail(&contactBirthday));
    QVERIFY2(mManager->saveContact(&contact), "Error saving contact to tracker");

    // Wait until calendar event gets to calendar.
    loopWait(calendarTimeout);

    // Open calendar database.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check calendar database for contact.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    KCalCore::Event::List eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Change the contact name and see if the calendar is updated.
    const QString newContactID = QUuid::createUuid().toString();
    contactName.setCustomLabel(newContactID);
    QVERIFY(contact.saveDetail(&contactName));
    // TODO: Should it be necessary to refetch the contact to get the synthesised displayLabel?
    contact = mManager->contact(contact.localId());
    QVERIFY2(mManager->saveContact(&contact), "Unable to update test contact in tracker");

    // Wait until calendar event gets to calendar.
    loopWait(calendarTimeout);

    // Search for any events in the calendar.
    QVERIFY2(storage->loadNotebookIncidences(calNotebookId), "Unable to load events from notebook");
    eventList = calendar->events();
    QCOMPARE(countCalendarEvents(eventList, contact), 1);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::testLocaleChange()
{
    MGConfDataStore store(QLatin1String("/meegotouch/i18n"));

    store.setValue(QLatin1String("language"), QLatin1String("en"));

    // Leave the time to react to locale change
    loopWait(1000);

    // Use the C locale so it can be changed to a different locale later.
    MLocale locale;
    QVERIFY2(locale.isValid(), "Invalid locale");

    if (not locale.isInstalledTrCatalog(QLatin1String("calendar"))) {
        locale.installTrCatalog(QLatin1String("calendar"));
    }

    locale.connectSettings();
    MLocale::setDefault(locale);

    // Open calendar database, which should have been created by the birthday plugin.
    mKCal::ExtendedCalendar::Ptr calendar =
        mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mKCal::ExtendedStorage::Ptr storage =
        mKCal::ExtendedCalendar::defaultStorage(calendar);
    storage->open();
    QVERIFY2(not storage->notebook(calNotebookId).isNull(), "No calendar database found");

    // Check if locale name for calendar matches calendar name.
    //QVERIFY2(locale.isInstalledTrCatalog(QLatin1String("calendar")), "Calendar locale catalog not installed");
    const QString cLocaleCalendarName = qtTrId("qtn_caln_birthdays");
    QCOMPARE(storage->notebook(calNotebookId)->name(), cLocaleCalendarName);

    // Change locale and check name again.
    store.setValue(QLatin1String("language"), QLatin1String("fi"));

    loopWait(1000);

    const QString finnishLocaleCalendarName = qtTrId("qtn_caln_birthdays");

    QVERIFY2(storage->notebook(calNotebookId)->name() != cLocaleCalendarName, "Calendar name was not updated on locale change");
    QCOMPARE(storage->notebook(calNotebookId)->name(), finnishLocaleCalendarName);

    // Close the calendar.
    QVERIFY2(storage->close(), "Error closing the calendar");
}

void TestBirthdayPlugin::cleanupTestCase()
{
}

void TestBirthdayPlugin::cleanup()
{
    // Remove all contacts modified during the test run.
    // This could fail if the contacts were already removed, so the response is ignored.
    mManager->removeContacts(mContactLocalIDs.toList());

    mContactLocalIDs.clear();

    delete mManager;

    mManager = 0;
}

int TestBirthdayPlugin::countCalendarEvents(const KCalCore::Event::List &eventList,
                                            const QContact &contact) const
{
    int found = 0;
    Q_FOREACH(const QSharedPointer<KCalCore::Event> event, eventList) {
        if(event->dtStart().date() == contact.detail<QContactBirthday>().date()) {
            if(event->summary() == contact.detail<QContactDisplayLabel>().label()) {
                found++;
            }
        }
    }

    return found;
}

bool TestBirthdayPlugin::saveContact(QContact &contact)
{
    mContactLocalIDs.insert(contact.localId());

    return mManager->saveContact(&contact);
}

CONTACTSD_TEST_MAIN(TestBirthdayPlugin)
<|endoftext|>