diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-11-04 16:33:39 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-11-04 16:33:39 +0100 |
commit | c575191409f72f631d52c5d88353bf11b91b6a1f (patch) | |
tree | 0ad7174086329c9f8eb0e69c9a7c4ad55952ebd3 | |
parent | 76066c6afda6c5472399d29ced8970363e4b9a33 (diff) | |
parent | 885d61e5def90678c89235e7b79750375f180220 (diff) | |
download | qtlocation-mapboxgl-c575191409f72f631d52c5d88353bf11b91b6a1f.tar.gz |
Merge pull request #540 from mapbox/test-http
Run tests using HTTP requests
-rw-r--r-- | include/mbgl/util/time.hpp | 6 | ||||
-rw-r--r-- | platform/default/http_request_baton_curl.cpp | 14 | ||||
-rw-r--r-- | src/util/time.cpp | 13 | ||||
-rw-r--r-- | test/fixtures/fixture_request.cpp | 72 | ||||
-rw-r--r-- | test/headless.cpp | 69 | ||||
m--------- | test/suite | 0 | ||||
-rw-r--r-- | test/test.gyp | 2 |
7 files changed, 79 insertions, 97 deletions
diff --git a/include/mbgl/util/time.hpp b/include/mbgl/util/time.hpp index 9d61edf75e..e8afbeff6d 100644 --- a/include/mbgl/util/time.hpp +++ b/include/mbgl/util/time.hpp @@ -1,7 +1,9 @@ #ifndef MBGL_UTIL_TIME #define MBGL_UTIL_TIME +#include <string> #include <cstdint> +#include <ctime> namespace mbgl { @@ -15,6 +17,10 @@ namespace util { // comparisons between different timestamps produce meaningful values. timestamp now(); + +// Returns the RFC1123 formatted date. E.g. "Tue, 04 Nov 2014 02:13:24 GMT" +std::string rfc1123(std::time_t time); + } // used for time conversions diff --git a/platform/default/http_request_baton_curl.cpp b/platform/default/http_request_baton_curl.cpp index 0c3d2b43fc..80eed27677 100644 --- a/platform/default/http_request_baton_curl.cpp +++ b/platform/default/http_request_baton_curl.cpp @@ -2,6 +2,7 @@ #include <mbgl/util/uv-messenger.h> #include <mbgl/util/std.hpp> #include <mbgl/util/ptr.hpp> +#include <mbgl/util/time.hpp> #include <uv.h> #include <curl/curl.h> @@ -9,8 +10,6 @@ #include <queue> #include <cassert> #include <cstring> -#include <ctime> -#include <xlocale.h> // This file contains code from http://curl.haxx.se/libcurl/c/multi-uv.html: @@ -369,9 +368,6 @@ void start_request(void *const ptr) { util::ptr<HTTPRequestBaton> &baton = *baton_guard.get(); assert(baton); - // Create a C locale - static locale_t locale = newlocale(LC_ALL_MASK, nullptr, nullptr); - CURL *handle = nullptr; if (!handles.empty()) { handle = handles.front(); @@ -390,11 +386,9 @@ void start_request(void *const ptr) { const std::string header = std::string("If-None-Match: ") + baton->response->etag; context->headers = curl_slist_append(context->headers, header.c_str()); } else if (baton->response->modified) { - const time_t modified = baton->response->modified; - struct tm *timeinfo = std::gmtime(&modified); - char buffer[64]; - strftime_l(buffer, 64, "If-Modified-Since: %a, %d %b %Y %H:%M:%S GMT", timeinfo, locale); - context->headers = curl_slist_append(context->headers, buffer); + const std::string time = std::string("If-Modified-Since: ") + + util::rfc1123(baton->response->modified); + context->headers = curl_slist_append(context->headers, time.c_str()); } } diff --git a/src/util/time.cpp b/src/util/time.cpp index 4cd8077f98..1953975b18 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -8,5 +8,18 @@ timestamp now() { return uv_hrtime(); } +static const char *week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; +static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +std::string rfc1123(std::time_t time) { + std::tm info; + gmtime_r(&time, &info); + char buffer[30]; + snprintf(buffer, 30, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[info.tm_wday], info.tm_mday, + months[info.tm_mon], 1900 + info.tm_year, info.tm_hour, info.tm_min, info.tm_sec); + return buffer; +} + } } diff --git a/test/fixtures/fixture_request.cpp b/test/fixtures/fixture_request.cpp deleted file mode 100644 index cc01760ae1..0000000000 --- a/test/fixtures/fixture_request.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include <mbgl/storage/http_request_baton.hpp> -#include <mbgl/storage/file_request_baton.hpp> -#include <mbgl/storage/response.hpp> -#include <mbgl/util/url.hpp> -#include <mbgl/util/std.hpp> -#include <mbgl/platform/log.hpp> -#include <iostream> - -#include <uv.h> - -#include <cassert> - - -const std::string base_directory = []{ - std::string fn = __FILE__; - fn.erase(fn.find_last_of("/")); - fn.erase(fn.find_last_of("/")); - fn.erase(fn.find_last_of("/")); - return fn + "/test/suite/"; -}(); - -namespace mbgl { - -void HTTPRequestBaton::start(const util::ptr<HTTPRequestBaton> &baton) { - assert(uv_thread_self() == baton->thread_id); - - std::string clean_url = util::percentDecode(baton->path); - if (clean_url.find("local://") == 0) { - clean_url = base_directory + clean_url.substr(8); - } - - baton->response = std::make_unique<Response>(); - FILE *file = fopen(clean_url.c_str(),"rb"); - if (file != NULL) { - fseek(file, 0, SEEK_END); - const size_t size = ftell(file); - fseek(file, 0, SEEK_SET); - baton->response->data.resize(size); - const size_t read = fread(&baton->response->data[0], 1, size, file); - fclose(file); - - if (read == size) { - baton->response->code = 200; - baton->type = HTTPResponseType::Successful; - } else { - baton->response->code = 500; - baton->type = HTTPResponseType::PermanentError; - baton->response->message = "Read bytes differed from file size"; - } - } else { - baton->type = HTTPResponseType::PermanentError; - baton->response->code = 404; - } - - uv_async_send(baton->async); -} - -void HTTPRequestBaton::stop(const util::ptr<HTTPRequestBaton> &/*baton*/) { - fprintf(stderr, "HTTP request cannot be canceled because it is answered immediately"); - abort(); -} - -namespace platform { - -std::string defaultCacheDatabase() { - // Disables the cache. - return ""; -} - -} - -} diff --git a/test/headless.cpp b/test/headless.cpp index 4605d7f288..657bab4c35 100644 --- a/test/headless.cpp +++ b/test/headless.cpp @@ -15,22 +15,63 @@ #include "./fixtures/fixture_log.hpp" #include <dirent.h> +#include <signal.h> +#include <libgen.h> + +std::string base_directory; + + +class ServerEnvironment : public ::testing::Environment { +public: + virtual void SetUp() { + pid = fork(); + if (pid < 0) { + throw std::runtime_error("Cannot create web server"); + } else if (pid == 0) { + char *arg[] = { nullptr }; + int ret = execv((base_directory + "bin/server.py").c_str(), arg); + // This call should not return. In case execve failed, we exit anyway. + if (ret < 0) { + fprintf(stderr, "Failed to start server: %s\n", strerror(errno)); + } + exit(0); + } else { + display = std::make_shared<mbgl::HeadlessDisplay>(); + } + } + virtual void TearDown() { + ASSERT_TRUE(pid); + kill(pid, SIGHUP); + } + + std::shared_ptr<mbgl::HeadlessDisplay> display; -const std::string base_directory = []{ - std::string fn = __FILE__; - fn.erase(fn.find_last_of("/")); - fn.erase(fn.find_last_of("/")); - return fn + "/test/suite/"; -}(); +private: + pid_t pid = 0; +}; -auto display_ = std::make_shared<mbgl::HeadlessDisplay>(); + +ServerEnvironment* env = nullptr; + + +GTEST_API_ int main(int argc, char *argv[]) { + // Note: glibc's dirname() **modifies** the argument and can't handle static strings. + std::string argv0 { argv[0] }; argv0 = dirname(const_cast<char *>(argv0.c_str())); + std::string file { __FILE__ }; file = dirname(const_cast<char *>(file.c_str())); + base_directory = argv0 + "/" + file + "/suite/"; + + testing::InitGoogleTest(&argc, argv); + env = new ServerEnvironment(); + ::testing::AddGlobalTestEnvironment(env); + return RUN_ALL_TESTS(); +} class HeadlessTest : public ::testing::TestWithParam<std::string> {}; TEST_P(HeadlessTest, render) { using namespace mbgl; - const std::string &base = GetParam(); + const std::string& base = GetParam(); std::string style = util::read_file(base_directory + "tests/" + base + "/style.json"); std::string info = util::read_file(base_directory + "tests/" + base + "/info.json"); @@ -55,8 +96,10 @@ TEST_P(HeadlessTest, render) { Log::Set<FixtureLogBackend>(); for (auto it = infoDoc.MemberBegin(), end = infoDoc.MemberEnd(); it != end; it++) { - const std::string name { it->name.GetString(), it->name.GetStringLength() }; - const rapidjson::Value &value = it->value; + const std::string name { + it->name.GetString(), it->name.GetStringLength() + }; + const rapidjson::Value& value = it->value; ASSERT_TRUE(value.IsObject()); if (value.HasMember("center")) ASSERT_TRUE(value["center"].IsArray()); @@ -72,16 +115,16 @@ TEST_P(HeadlessTest, render) { std::vector<std::string> classes; if (value.HasMember("classes")) { - const rapidjson::Value &js_classes = value["classes"]; + const rapidjson::Value& js_classes = value["classes"]; ASSERT_TRUE(js_classes.IsArray()); for (rapidjson::SizeType i = 0; i < js_classes.Size(); i++) { - const rapidjson::Value &js_class = js_classes[i]; + const rapidjson::Value& js_class = js_classes[i]; ASSERT_TRUE(js_class.IsString()); classes.push_back({ js_class.GetString(), js_class.GetStringLength() }); } } - HeadlessView view(display_); + HeadlessView view(env->display); Map map(view); map.setStyleJSON(style, base_directory); diff --git a/test/suite b/test/suite -Subproject 1651a3df444ff83c98f6eff00679d6b84dc8845 +Subproject 8f03d5dabfb7ec6447696b25691794280f39947 diff --git a/test/test.gyp b/test/test.gyp index b9d91a374e..2c6f411cf9 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -162,9 +162,7 @@ 'product_name': 'test_headless', 'type': 'executable', 'sources': [ - './main.cpp', './headless.cpp', - './fixtures/fixture_request.cpp', './fixtures/fixture_log.cpp', ], 'conditions': [ |