diff --git a/Makefile b/Makefile index 13af0f4ba..70d706afa 100644 --- a/Makefile +++ b/Makefile @@ -25,11 +25,11 @@ build/test/Makefile: src common config.gypi test/test.gyp deps/run_gyp test/test.gyp --depth=. -Goutput_dir=.. --generator-output=./build/test -f make test: build/test/Makefile - $(MAKE) -C build/test BUILDTYPE=$(BUILDTYPE) V=$(V) test + $(MAKE) -C build/test BUILDTYPE=Testing V=$(V) test test/%: build/test/Makefile - $(MAKE) -C build/test BUILDTYPE=$(BUILDTYPE) V=$(V) $* - (cd build/$(BUILDTYPE) && exec ./test_$*) + $(MAKE) -C build/test BUILDTYPE=Testing V=$(V) $* + (cd build/Testing && exec ./test_$*) # build Mac OS X project for Xcode xtest: config.gypi clear_xcode_cache node @@ -42,7 +42,7 @@ xtest: config.gypi clear_xcode_cache node # Builds the linux app with make. This is also used by Travis CI linux: config.gypi linux/llmr-app.gyp node deps/run_gyp linux/llmr-app.gyp --depth=. -Goutput_dir=.. --generator-output=./build/linux -f make - $(MAKE) -C build/linux BUILDTYPE=$(BUILDTYPE) V=$(V) linuxapp + $(MAKE) -C build/linux BUILDTYPE=Testing V=$(V) linuxapp # Executes the Linux binary run-linux: linux diff --git a/common.gypi b/common.gypi index a9567d4d3..a38a279ef 100644 --- a/common.gypi +++ b/common.gypi @@ -33,6 +33,16 @@ 'DEAD_CODE_STRIPPING': 'YES', 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES' } + }, + 'Testing': { + 'cflags_cc': [ '-O3' ], + 'defines': [ 'NDEBUG', 'TESTING' ], + 'xcode_settings': { + 'GCC_OPTIMIZATION_LEVEL': '3', + 'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO', + 'DEAD_CODE_STRIPPING': 'YES', + 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES' + } } } } diff --git a/common/nslog_log.hpp b/common/nslog_log.hpp new file mode 100644 index 000000000..d4ea6f6ea --- /dev/null +++ b/common/nslog_log.hpp @@ -0,0 +1,20 @@ +#ifndef LLMR_COMMON_NSLOG_LOG +#define LLMR_COMMON_NSLOG_LOG + +#include + +namespace llmr { + +class NSLogBackend : public LogBackend { +public: + inline ~NSLogBackend() = default; + + void record(EventSeverity severity, Event event, const std::string &msg); + void record(EventSeverity severity, Event event, int64_t code); + void record(EventSeverity severity, Event event, int64_t code, const std::string &msg); +}; + + +} + +#endif diff --git a/common/nslog_log.mm b/common/nslog_log.mm new file mode 100644 index 000000000..eed0810ae --- /dev/null +++ b/common/nslog_log.mm @@ -0,0 +1,24 @@ +#include "nslog_log.hpp" + +#import + +namespace llmr { + +void NSLogBackend::record(EventSeverity severity, Event event, const std::string &msg) { + NSLog(@"[%s] %s: %@", stringifyEventSeverity(severity), stringifyEvent(event), + [[NSString alloc] initWithBytes:msg.data() + length:msg.size() + encoding:NSUTF8StringEncoding]); +} + +void NSLogBackend::record(EventSeverity severity, Event event, int64_t code) { + NSLog(@"[%s] %s: (%lld)", stringifyEventSeverity(severity), stringifyEvent(event), code); +} + +void NSLogBackend::record(EventSeverity severity, Event event, int64_t code, const std::string &msg) { + NSLog(@"[%s] %s: (%lld) %@", stringifyEventSeverity(severity), stringifyEvent(event), code, + [[NSString alloc] initWithBytes:msg.data() + length:msg.size() + encoding:NSUTF8StringEncoding]); +} +} diff --git a/common/stderr_log.cpp b/common/stderr_log.cpp new file mode 100644 index 000000000..b3b1fea33 --- /dev/null +++ b/common/stderr_log.cpp @@ -0,0 +1,20 @@ +#include "stderr_log.hpp" + +#include + +namespace llmr { + +void StderrLogBackend::record(EventSeverity severity, Event event, const std::string &msg) { + std::cerr << "[" << severity << "] " << event << ": " << msg << std::endl; +} + +void StderrLogBackend::record(EventSeverity severity, Event event, int64_t code) { + std::cerr << "[" << severity << "] " << event << ": (" << code << ")" << std::endl; +} + +void StderrLogBackend::record(EventSeverity severity, Event event, int64_t code, const std::string &msg) { + std::cerr << "[" << severity << "] " << event << ": (" << code << ") " << msg << std::endl; + +} + +} diff --git a/common/stderr_log.hpp b/common/stderr_log.hpp new file mode 100644 index 000000000..32b6850cb --- /dev/null +++ b/common/stderr_log.hpp @@ -0,0 +1,20 @@ +#ifndef LLMR_COMMON_STDERR_LOG +#define LLMR_COMMON_STDERR_LOG + +#include + +namespace llmr { + +class StderrLogBackend : public LogBackend { +public: + inline ~StderrLogBackend() = default; + + void record(EventSeverity severity, Event event, const std::string &msg); + void record(EventSeverity severity, Event event, int64_t code); + void record(EventSeverity severity, Event event, int64_t code, const std::string &msg); +}; + + +} + +#endif diff --git a/include/llmr/platform/event.hpp b/include/llmr/platform/event.hpp new file mode 100644 index 000000000..930f79fac --- /dev/null +++ b/include/llmr/platform/event.hpp @@ -0,0 +1,56 @@ +#ifndef LLMR_PLATFORM_EVENT +#define LLMR_PLATFORM_EVENT + +#include +#include + +namespace llmr { + +enum class EventSeverity : uint8_t { + Debug, + Info, + Test, + Warning, + Error, +}; + +EventSeverity parseEventSeverity(const char *name); +const char *stringifyEventSeverity(EventSeverity eventSeverity); +::std::ostream& operator<<(::std::ostream& os, EventSeverity eventSeverity); + +enum class Event : uint8_t { + Setup, + ParseStyle, + ParseTile, + Render, + HttpRequest, +}; + +Event parseEvent(const char *name); +const char *stringifyEvent(Event event); +::std::ostream& operator<<(::std::ostream& os, Event event); + +constexpr EventSeverity enabledEventSeverities[] = { +#if DEBUG + EventSeverity::Debug, +#endif + +#if TESTING + EventSeverity::Test, +#endif + + EventSeverity::Info, + EventSeverity::Warning, + EventSeverity::Error, +}; + +/* enabled event classes */ +constexpr Event enabledEvents[] = { + Event::ParseStyle, + Event::ParseTile, + Event::HttpRequest, +}; + +} + +#endif diff --git a/include/llmr/platform/log.hpp b/include/llmr/platform/log.hpp new file mode 100644 index 000000000..48c88a1fd --- /dev/null +++ b/include/llmr/platform/log.hpp @@ -0,0 +1,69 @@ +#ifndef LLMR_PLATFORM_LOG +#define LLMR_PLATFORM_LOG + +#include "event.hpp" + +#include +#include + +namespace llmr { + +class LogBackend { +public: + virtual inline ~LogBackend() = default; + virtual void record(EventSeverity severity, Event event, const std::string &msg) = 0; + virtual void record(EventSeverity severity, Event event, int64_t code) = 0; + virtual void record(EventSeverity severity, Event event, int64_t code, const std::string &msg) = 0; +}; + +class Log { +private: + template + constexpr static bool includes(const T e, T const *l, const size_t i = 0) { + return i >= sizeof l ? false : *(l + i) == e ? true : includes(e, l, i + 1); + } + +public: + template + static inline void Debug(Event event, Args&& ...args) { + Record(EventSeverity::Debug, event, ::std::forward(args)...); + } + + template + static inline void Info(Event event, Args&& ...args) { + Record(EventSeverity::Info, event, ::std::forward(args)...); + } + + template + static inline void Warning(Event event, Args&& ...args) { + Record(EventSeverity::Warning, event, ::std::forward(args)...); + } + + template + static inline void Error(Event event, Args&& ...args) { + Record(EventSeverity::Error, event, ::std::forward(args)...); + } + + template + static inline void Record(EventSeverity severity, Event event, Args&& ...args) { + if (includes(severity, enabledEventSeverities) && + includes(event, enabledEvents)) { + if (Backend) { + Backend->record(severity, event, ::std::forward(args)...); + } + } + } + + template + static inline const T &Set(Args&& ...args) { + Backend = ::std::unique_ptr(new T(::std::forward(args)...)); + return *dynamic_cast(Backend.get()); + } + +private: + static std::unique_ptr Backend; +}; + +} + +#endif diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa index e16b737da..9d403d2ce 160000 --- a/ios/mapbox-gl-cocoa +++ b/ios/mapbox-gl-cocoa @@ -1 +1 @@ -Subproject commit e16b737daaf9ecd2a02f7ccc61a590e9df8b2050 +Subproject commit 9d403d2cefcd63797a3da2c67d4b653e287aeec5 diff --git a/linux/main.cpp b/linux/main.cpp index 889a246c2..11a21880f 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -8,6 +8,7 @@ #include "../common/settings_json.hpp" #include "../common/glfw_view.hpp" +#include "../common/stderr_log.hpp" GLFWView *view = nullptr; @@ -22,6 +23,8 @@ void quit_handler(int) { } int main(int argc, char *argv[]) { + llmr::Log::Set(); + int fullscreen_flag = 0; const struct option long_options[] = { @@ -63,7 +66,7 @@ int main(int argc, char *argv[]) { // Set access token if present const char *token = getenv("MAPBOX_ACCESS_TOKEN"); if (token == nullptr) { - fprintf(stderr, "[WARNING] no access token set. mapbox.com tiles won't work.\n"); + llmr::Log::Warning(llmr::Event::Setup, "no access token set. mapbox.com tiles won't work."); } else { map.setAccessToken(std::string(token)); } diff --git a/macosx/llmr-app.gyp b/macosx/llmr-app.gyp index 02319da94..139cb744c 100644 --- a/macosx/llmr-app.gyp +++ b/macosx/llmr-app.gyp @@ -16,6 +16,8 @@ '../common/glfw_view.cpp', '../common/foundation_request.h', '../common/foundation_request.mm', + '../common/nslog_log.hpp', + '../common/nslog_log.mm', ], 'product_extension': 'app', 'mac_bundle': 1, diff --git a/macosx/main.mm b/macosx/main.mm index 3b01df04e..f72476cde 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -1,9 +1,12 @@ #include "../common/settings_nsuserdefaults.hpp" #include "../common/glfw_view.hpp" +#include "../common/nslog_log.hpp" #import int main() { + llmr::Log::Set(); + GLFWView view; llmr::Map map(view); @@ -16,7 +19,7 @@ int main() { // Set access token if present const char *token = getenv("MAPBOX_ACCESS_TOKEN"); if (token == nullptr) { - fprintf(stderr, "[WARNING] no access token set. mapbox.com tiles won't work.\n"); + llmr::Log::Warning(llmr::Event::Setup, "no access token set. mapbox.com tiles won't work."); } else { map.setAccessToken(std::string(token)); } @@ -28,8 +31,6 @@ int main() { error:nil]; map.setStyleJSON((std::string)[json cStringUsingEncoding:[NSString defaultCStringEncoding]]); - // fprintf(stderr, "lon: %f, lat: %f, zoom: %f, angle: %f, debug: %d\n", settings.l) - int ret = view.run(); // Save settings diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh index be65356ba..716594824 100755 --- a/scripts/run_tests.sh +++ b/scripts/run_tests.sh @@ -3,9 +3,7 @@ set -e set -o pipefail -BUILDTYPE="${BUILDTYPE:-Release}" - -cd build/${BUILDTYPE} +cd build/Testing for TEST in ./test_* ; do ${TEST} diff --git a/src/platform/event.cpp b/src/platform/event.cpp new file mode 100644 index 000000000..8d5507423 --- /dev/null +++ b/src/platform/event.cpp @@ -0,0 +1,56 @@ +#include + +#include + +namespace llmr { + +EventSeverity parseEventSeverity(const char *name) { + if (strcmp(name, "DEBUG") == 0) return EventSeverity::Debug; + if (strcmp(name, "INFO") == 0) return EventSeverity::Info; + if (strcmp(name, "TEST") == 0) return EventSeverity::Test; + if (strcmp(name, "WARNING") == 0) return EventSeverity::Warning; + if (strcmp(name, "ERROR") == 0) return EventSeverity::Error; + return EventSeverity(-1); +} + +const char *stringifyEventSeverity(EventSeverity eventSeverity) { + switch (eventSeverity) { + case EventSeverity::Debug: return "DEBUG"; + case EventSeverity::Info: return "INFO"; + case EventSeverity::Test: return "TEST"; + case EventSeverity::Warning: return "WARNING"; + case EventSeverity::Error: return "ERROR"; + default: return "UNKNOWN"; + } +} + +::std::ostream& operator<<(::std::ostream& os, EventSeverity eventSeverity) { + return os << stringifyEventSeverity(eventSeverity); +} + +Event parseEvent(const char *name) { + if (strcmp(name, "Setup") == 0) return Event::Setup; + if (strcmp(name, "ParseStyle") == 0) return Event::ParseStyle; + if (strcmp(name, "ParseTile") == 0) return Event::ParseTile; + if (strcmp(name, "Render") == 0) return Event::Render; + if (strcmp(name, "HttpRequest") == 0) return Event::HttpRequest; + return Event(-1); +} + +const char *stringifyEvent(Event event) { + switch (event) { + case Event::Setup: return "Setup"; + case Event::ParseStyle: return "ParseStyle"; + case Event::ParseTile: return "ParseTile"; + case Event::Render: return "Render"; + case Event::HttpRequest: return "HttpRequest"; + default: return "Unknown"; + } +} + +::std::ostream& operator<<(::std::ostream& os, Event event) { + return os << stringifyEvent(event); +} + + +} diff --git a/src/platform/log.cpp b/src/platform/log.cpp new file mode 100644 index 000000000..7974e5ed86 --- /dev/null +++ b/src/platform/log.cpp @@ -0,0 +1,7 @@ +#include + +namespace llmr { + +std::unique_ptr Log::Backend; + +} diff --git a/test/fixtures/fixture_log.cpp b/test/fixtures/fixture_log.cpp new file mode 100644 index 000000000..d260927b5 --- /dev/null +++ b/test/fixtures/fixture_log.cpp @@ -0,0 +1,42 @@ +#include "fixture_log.hpp" + +#include + +namespace llmr { + +size_t FixtureLogBackend::count(const LogMessage &message) const { + size_t count = 0; + for (const LogMessage &msg : messages) { + if (msg == message) { + count++; + msg.checked = true; + } + } + return count; +} + +std::vector FixtureLogBackend::unchecked() const { + std::vector unchecked; + for (const LogMessage &msg : messages) { + if (!msg.checked) { + unchecked.push_back(msg); + } + } + return unchecked; +} + +::std::ostream& operator<<(::std::ostream& os, const std::vector& messages) { + for (const FixtureLogBackend::LogMessage &message : messages) { + os << "- " << message; + } + return os; +} + +::std::ostream& operator<<(::std::ostream& os, const FixtureLogBackend::LogMessage& message) { + os << "[\"" << message.severity.get() << "\", \"" << message.event.get(); + if (message.code) os << "\", " << message.code.get(); + if (message.msg) os << ", \"" << message.msg.get(); + return os << "\"]" << std::endl; +} + +} \ No newline at end of file diff --git a/test/fixtures/fixture_log.hpp b/test/fixtures/fixture_log.hpp new file mode 100644 index 000000000..befba8b2c --- /dev/null +++ b/test/fixtures/fixture_log.hpp @@ -0,0 +1,66 @@ +#ifndef LLMR_TEST_FIXTURE_LOG +#define LLMR_TEST_FIXTURE_LOG + +#include + +#include + +#include + +namespace llmr { + +class FixtureLogBackend : public LogBackend { +public: + struct LogMessage { + inline LogMessage(EventSeverity severity, Event event, int64_t code, const std::string &msg) + : severity(severity), event(event), code(code), msg(msg) {} + inline LogMessage(EventSeverity severity, Event event, int64_t code) + : severity(severity), event(event), code(code) {} + inline LogMessage(EventSeverity severity, Event event, const std::string &msg) + : severity(severity), event(event), msg(msg) {} + inline LogMessage(EventSeverity severity, Event event) + : severity(severity), event(event) {} + + inline bool operator==(const LogMessage &rhs) const { + return (!severity || !rhs.severity || severity.get() == rhs.severity.get()) && + (!event || !rhs.event || event.get() == rhs.event.get()) && + (!code || !rhs.code || code.get() == rhs.code.get()) && + (!msg || !rhs.msg || msg.get() == rhs.msg.get()); + } + + const boost::optional severity; + const boost::optional event; + const boost::optional code; + const boost::optional msg; + + mutable bool checked = false; + }; + + inline ~FixtureLogBackend() = default; + + void record(EventSeverity severity, Event event, const std::string &msg) { + messages.emplace_back(severity, event, msg); + } + + void record(EventSeverity severity, Event event, int64_t code) { + messages.emplace_back(severity, event, code); + } + + void record(EventSeverity severity, Event event, int64_t code, const std::string &msg) { + messages.emplace_back(severity, event, code, msg); + } + + size_t count(const LogMessage &message) const; + std::vector unchecked() const; + +public: + std::vector messages; +}; + +::std::ostream& operator<<(::std::ostream& os, const std::vector& messages); +::std::ostream& operator<<(::std::ostream& os, const FixtureLogBackend::LogMessage& message); + + +} + +#endif diff --git a/test/fixtures/fixture_request.cpp b/test/fixtures/fixture_request.cpp index 8bf1e282b..c2e209bc6 100644 --- a/test/fixtures/fixture_request.cpp +++ b/test/fixtures/fixture_request.cpp @@ -1,6 +1,7 @@ #include #include #include +#include const std::string base_directory = []{ std::string fn = __FILE__; @@ -40,7 +41,7 @@ platform::request_http(const std::string &url, if (err < 0) { req->res->code = err; req->res->error_message = uv_strerror(err); - fprintf(stderr, "[WARNING] fixture request: %s\n", uv_strerror(err)); + Log::Warning(Event::HttpRequest, err, url + ": " + uv_strerror(err)); req->complete(); return req; } @@ -90,7 +91,8 @@ platform::request_http(const std::string &url, req->res->body.swap(body); req->res->code = 200; - fprintf(stderr, "[INFO] fixture request completed: %s\n", clean_url.c_str()); + // fprintf(stderr, "[INFO] fixture request completed: %s\n", clean_url.c_str()); + Log::Info(Event::HttpRequest, 200, url); req->complete(); return req; diff --git a/test/fixtures/styles/line-color.info.json b/test/fixtures/styles/line-color.info.json index 03e33581d..d9be88b10 100644 --- a/test/fixtures/styles/line-color.info.json +++ b/test/fixtures/styles/line-color.info.json @@ -2,12 +2,26 @@ "default": { "zoom": 14, "center": [52.499167, 13.418056], - "height": 256 + "height": 256, + "log": [ + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5374.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5374.vector.pbf"], + [4, "INFO", "HttpRequest"] + ] }, "colored": { "zoom": 14, "center": [52.499167, 13.418056], "height": 256, - "classes": ["colored"] + "classes": ["colored"], + "log": [ + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5374.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5374.vector.pbf"], + [4, "INFO", "HttpRequest"] + ] } } diff --git a/test/fixtures/styles/road-width.info.json b/test/fixtures/styles/road-width.info.json index 0c7033e4e..0094f715c 100644 --- a/test/fixtures/styles/road-width.info.json +++ b/test/fixtures/styles/road-width.info.json @@ -2,21 +2,44 @@ "z13.9": { "zoom": 13.9, "center": [52.499167, 13.418056], - "height": 256 + "height": 256, + "log": [ + [1, "INFO", "HttpRequest", 200, "tiles/13-4401-2687.vector.pbf"], + [1, "INFO", "HttpRequest"] + ] }, "z14.0": { "zoom": 14, "center": [52.499167, 13.418056], - "height": 256 + "height": 256, + "log": [ + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5374.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5374.vector.pbf"], + [4, "INFO", "HttpRequest"] + ] }, "z14.1": { "zoom": 14.1, "center": [52.499167, 13.418056], - "height": 256 + "height": 256, + "log": [ + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5375.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5374.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5374.vector.pbf"], + [4, "INFO", "HttpRequest"] + ] }, "z14.2": { "zoom": 14.2, "center": [52.499167, 13.418056], - "height": 256 + "height": 256, + "log": [ + [1, "INFO", "HttpRequest", 200, "tiles/14-8803-5374.vector.pbf"], + [1, "INFO", "HttpRequest", 200, "tiles/14-8802-5374.vector.pbf"], + [2, "INFO", "HttpRequest"] + ] } } diff --git a/test/fixtures/styles/world-aa.info.json b/test/fixtures/styles/world-aa.info.json index 3a61efdd1..e5e123dce 100644 --- a/test/fixtures/styles/world-aa.info.json +++ b/test/fixtures/styles/world-aa.info.json @@ -1,6 +1,9 @@ { "plain": { "center": [0, 0], - "zoom": 0 + "zoom": 0, + "log": [ + [ 1, "INFO", "HttpRequest", 200, "tiles/0-0-0.vector.pbf" ] + ] } } diff --git a/test/fixtures/styles/world-no-aa.info.json b/test/fixtures/styles/world-no-aa.info.json index 3a61efdd1..f5bc0c146 100644 --- a/test/fixtures/styles/world-no-aa.info.json +++ b/test/fixtures/styles/world-no-aa.info.json @@ -1,6 +1,10 @@ { "plain": { "center": [0, 0], - "zoom": 0 + "zoom": 0, + "log": [ + [1, "INFO", "HttpRequest", 200, "tiles/0-0-0.vector.pbf"], + [1, "INFO", "HttpRequest"] + ] } } diff --git a/test/fixtures/tiles/13-4401-2687.vector.pbf b/test/fixtures/tiles/13-4401-2687.vector.pbf new file mode 100644 index 000000000..f2165b8fe Binary files /dev/null and b/test/fixtures/tiles/13-4401-2687.vector.pbf differ diff --git a/test/headless.cpp b/test/headless.cpp index 97a5e581a..fac38f9fd 100644 --- a/test/headless.cpp +++ b/test/headless.cpp @@ -9,6 +9,8 @@ #include "../common/headless_view.hpp" +#include "./fixtures/fixture_log.hpp" + #include const std::string base_directory = []{ @@ -20,10 +22,12 @@ const std::string base_directory = []{ class HeadlessTest : public ::testing::TestWithParam {}; TEST_P(HeadlessTest, render) { + using namespace llmr; + const std::string &base = GetParam(); - const std::string style = llmr::util::read_file(base_directory + "/" + base + ".style.json"); - const std::string info = llmr::util::read_file(base_directory + "/" + base + ".info.json"); + const std::string style = util::read_file(base_directory + "/" + base + ".style.json"); + const std::string info = util::read_file(base_directory + "/" + base + ".info.json"); // Parse settings. rapidjson::Document doc; @@ -32,10 +36,12 @@ TEST_P(HeadlessTest, render) { ASSERT_EQ(true, doc.IsObject()); // Setup OpenGL - llmr::HeadlessView view; - llmr::Map map(view); + HeadlessView view; + Map map(view); for (auto it = doc.MemberBegin(), end = doc.MemberEnd(); it != end; it++) { + const FixtureLogBackend &log = Log::Set(); + const std::string name { it->name.GetString(), it->name.GetStringLength() }; const rapidjson::Value &value = it->value; ASSERT_EQ(true, value.IsObject()); @@ -74,8 +80,58 @@ TEST_P(HeadlessTest, render) { const std::unique_ptr pixels(new uint32_t[width * height]); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); - const std::string image = llmr::util::compress_png(width, height, pixels.get(), true); - llmr::util::write_file(actual_image, image); + const std::string image = util::compress_png(width, height, pixels.get(), true); + util::write_file(actual_image, image); + + if (value.HasMember("log")) { + const rapidjson::Value &js_log = value["log"]; + ASSERT_EQ(true, js_log.IsArray()); + for (rapidjson::SizeType i = 0; i < js_log.Size(); i++) { + const rapidjson::Value &js_entry = js_log[i]; + ASSERT_EQ(true, js_entry.IsArray()); + if (js_entry.Size() == 5) { + const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint(); + const FixtureLogBackend::LogMessage message { + parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), + parseEvent(js_entry[rapidjson::SizeType(2)].GetString()), + js_entry[rapidjson::SizeType(3)].GetInt64(), + js_entry[rapidjson::SizeType(4)].GetString() + }; + ASSERT_EQ(count, log.count(message)) << "Message: " << message << "Full Log: " << std::endl << log.messages; + } else if (js_entry.Size() == 4) { + const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint(); + if (js_entry[rapidjson::SizeType(3)].IsString()) { + const FixtureLogBackend::LogMessage message { + parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), + parseEvent(js_entry[rapidjson::SizeType(2)].GetString()), + js_entry[rapidjson::SizeType(3)].GetString() + }; + ASSERT_EQ(count, log.count(message)) << "Message: " << message << "Full Log: " << std::endl << log.messages; + } else { + const FixtureLogBackend::LogMessage message { + parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), + parseEvent(js_entry[rapidjson::SizeType(2)].GetString()), + js_entry[rapidjson::SizeType(3)].GetInt64() + }; + ASSERT_EQ(count, log.count(message)) << "Message: " << message << "Full Log: " << std::endl << log.messages; + } + } else if (js_entry.Size() == 3) { + const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint(); + const FixtureLogBackend::LogMessage message { + parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), + parseEvent(js_entry[rapidjson::SizeType(2)].GetString()) + }; + ASSERT_EQ(count, log.count(message)) << "Message: " << message << "Full Log: " << std::endl << log.messages; + } else { + FAIL(); + } + } + } + + const auto &unchecked = log.unchecked(); + if (unchecked.size()) { + std::cerr << "Unchecked Log Messages (" << base << "/" << name << "): " << std::endl << unchecked; + } } } diff --git a/test/test.gyp b/test/test.gyp index bb4bfc759..c6869fd47 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -151,6 +151,8 @@ "../common/headless_view.hpp", "../common/headless_view.cpp", "./fixtures/fixture_request.cpp", + "./fixtures/fixture_log.hpp", + "./fixtures/fixture_log.cpp", ], "dependencies": [ "../deps/gtest/gtest.gyp:gtest",