TEST_P(StyleParserTest, ParseStyle) {
    const std::string &base = "test/fixtures/style_parser/" + GetParam();

    rapidjson::Document infoDoc;
    infoDoc.Parse<0>(util::read_file(base + ".info.json").c_str());
    ASSERT_FALSE(infoDoc.HasParseError());
    ASSERT_TRUE(infoDoc.IsObject());

    rapidjson::Document styleDoc;
    styleDoc.Parse<0>(util::read_file(base + ".style.json").c_str());
    ASSERT_FALSE(styleDoc.HasParseError());
    ASSERT_TRUE(styleDoc.IsObject());

    FixtureLogObserver* observer = new FixtureLogObserver();
    Log::setObserver(std::unique_ptr<Log::Observer>(observer));

    MapMode mapMode = MapMode::Continuous;
    GLContextMode contextMode = GLContextMode::Unique;
    const float pixelRatio = 1.0f;

    MapData data(mapMode, contextMode, pixelRatio);
    StyleParser parser(data);
    parser.parse(styleDoc);

    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;
        ASSERT_EQ(true, value.IsObject());

        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());

                const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint();
                const FixtureLogObserver::LogMessage message {
                    EventSeverityClass(js_entry[rapidjson::SizeType(1)].GetString()),
                    EventClass(js_entry[rapidjson::SizeType(2)].GetString()),
                    int64_t(-1),
                    js_entry[rapidjson::SizeType(3)].GetString()
                };

                EXPECT_EQ(count, observer->count(message)) << "Message: " << message << std::endl;
            }
        }

        const auto &unchecked = observer->unchecked();
        if (unchecked.size()) {
            std::cerr << "Unchecked Log Messages (" << base << "/" << name << "): " << std::endl << unchecked;
        }

        ASSERT_EQ(0ul, unchecked.size());
    }
}
TEST(API, RenderWithoutCallback) {
    FixtureLogObserver* log = new FixtureLogObserver();
    Log::setObserver(std::unique_ptr<Log::Observer>(log));

    auto display = std::make_shared<mbgl::HeadlessDisplay>();
    HeadlessView view(display, 1);
    view.resize(128, 512);
    OnlineFileSource fileSource;

    std::unique_ptr<Map> map = std::make_unique<Map>(view, fileSource, MapMode::Still);
    map->renderStill(nullptr);

    // Force Map thread to join.
    map.reset();

    const FixtureLogObserver::LogMessage logMessage {
        EventSeverity::Error,
        Event::General,
        int64_t(-1),
        "StillImageCallback not set",
    };

    EXPECT_EQ(log->count(logMessage), 1u);
}