Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit 7c22792

Browse files
committed
[tests] Rewrite resource loading test
Make it more readable and easier to debug.
1 parent d745ff0 commit 7c22792

File tree

4 files changed

+114
-122
lines changed

4 files changed

+114
-122
lines changed

include/mbgl/platform/log.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ class Log {
2121
virtual bool onRecord(EventSeverity severity, Event event, int64_t code, const std::string &msg) = 0;
2222
};
2323

24+
class NullObserver : public Observer {
25+
bool onRecord(EventSeverity, Event, int64_t, const std::string&) override {
26+
return true;
27+
}
28+
};
29+
2430
static void setObserver(std::unique_ptr<Observer> Observer);
2531
static std::unique_ptr<Observer> removeObserver();
2632

include/mbgl/util/string.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ inline std::string toString(int8_t num) {
2222
return boost::lexical_cast<std::string>(int(num));
2323
}
2424

25+
inline std::string toString(std::exception_ptr error) {
26+
try {
27+
std::rethrow_exception(error);
28+
} catch (const std::exception& ex) {
29+
return ex.what();
30+
} catch (...) {
31+
return "Unknown exception type";
32+
}
33+
}
2534

2635
template<size_t max, typename... Args>
2736
inline std::string sprintf(const char *msg, Args... args) {

test/fixtures/resources/style.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"rastersource": {
1010
"url": "test/fixtures/resources/source_raster.json",
1111
"type": "raster",
12-
"tileSize": 256
12+
"tileSize": 512
1313
}
1414
},
1515
"sprite": "test/fixtures/resources/sprite",

test/style/resource_loading.cpp

+98-121
Original file line numberDiff line numberDiff line change
@@ -11,164 +11,141 @@
1111
#include <mbgl/util/run_loop.hpp>
1212
#include <mbgl/util/texture_pool.hpp>
1313
#include <mbgl/util/thread.hpp>
14-
15-
#include <regex>
14+
#include <mbgl/util/string.hpp>
1615

1716
using namespace mbgl;
1817

19-
namespace {
20-
21-
class MockMapContext : public Style::Observer {
18+
class StyleObserver : public Style::Observer {
2219
public:
23-
MockMapContext(View& view,
24-
FileSource& fileSource,
25-
const std::function<void(std::exception_ptr error)>& callback)
26-
: data_(MapMode::Still, GLContextMode::Unique, view.getPixelRatio()),
27-
transform_(view, ConstrainMode::HeightOnly),
28-
callback_(callback) {
29-
util::ThreadContext::setFileSource(&fileSource);
30-
31-
transform_.resize({{ 1000, 1000 }});
32-
transform_.setLatLngZoom({0, 0}, 16);
33-
34-
const std::string style = util::read_file("test/fixtures/resources/style.json");
35-
style_ = std::make_unique<Style>(data_);
36-
style_->setJSON(style, "");
37-
style_->setObserver(this);
20+
void onTileDataChanged() override {
21+
tileDataChanged();
3822
}
3923

40-
~MockMapContext() {
41-
cleanup();
24+
void onResourceLoadingFailed(std::exception_ptr error) override {
25+
resourceLoadingFailed(error);
4226
}
4327

44-
void cleanup() {
45-
style_.reset();
46-
}
28+
std::function<void ()> tileDataChanged = [] {};
29+
std::function<void (std::exception_ptr)> resourceLoadingFailed = [] (auto) {};
30+
};
4731

48-
void update() {
49-
const auto now = Clock::now();
32+
std::string resourceErrorString(MockFileSource::Type type, const std::string& param) {
33+
Log::setObserver(std::make_unique<Log::NullObserver>()); // Squelch logging.
5034

51-
data_.setAnimationTime(now);
52-
transform_.updateTransitions(now);
35+
util::RunLoop loop;
5336

54-
style_->cascade();
55-
style_->recalculate(16);
56-
style_->update(transform_.getState(), texturePool_);
57-
}
37+
util::ThreadContext context("Map", util::ThreadType::Map, util::ThreadPriority::Regular);
38+
util::ThreadContext::Set(&context);
5839

59-
// Style::Observer implementation.
60-
void onTileDataChanged() override {
61-
update();
40+
MockFileSource fileSource(type, param);
41+
util::ThreadContext::setFileSource(&fileSource);
6242

63-
if (style_->isLoaded()) {
64-
callback_(nullptr);
65-
}
66-
};
43+
MapData data(MapMode::Still, GLContextMode::Unique, 1.0);
44+
MockView view;
45+
Transform transform(view, ConstrainMode::HeightOnly);
46+
TexturePool texturePool;
47+
Style style(data);
6748

68-
void onResourceLoadingFailed(std::exception_ptr error) override {
69-
callback_(error);
70-
}
49+
StyleObserver observer;
50+
std::string result;
7151

72-
private:
73-
MapData data_;
74-
Transform transform_;
75-
TexturePool texturePool_;
52+
observer.tileDataChanged = [&] () {
53+
// Prompt tile loading after sources load.
54+
style.update(transform.getState(), texturePool);
7655

77-
std::unique_ptr<Style> style_;
56+
if (style.isLoaded()) {
57+
loop.stop();
58+
}
59+
};
7860

79-
std::function<void(std::exception_ptr error)> callback_;
80-
};
61+
observer.resourceLoadingFailed = [&] (std::exception_ptr error) {
62+
result = util::toString(error);
63+
loop.stop();
64+
};
8165

82-
void runTestCase(MockFileSource::Type type,
83-
const std::string& param,
84-
const std::string& message) {
85-
util::RunLoop loop;
66+
transform.resize({{ 512, 512 }});
67+
transform.setLatLngZoom({0, 0}, 0);
8668

87-
MockView view;
88-
MockFileSource fileSource(type, param);
69+
style.setObserver(&observer);
70+
style.setJSON(util::read_file("test/fixtures/resources/style.json"), "");
71+
style.cascade();
72+
style.recalculate(16);
8973

90-
FixtureLogObserver* log = new FixtureLogObserver();
91-
Log::setObserver(std::unique_ptr<Log::Observer>(log));
74+
loop.run();
9275

93-
auto callback = [type, &loop, &param](std::exception_ptr error) {
94-
if (type == MockFileSource::Success) {
95-
EXPECT_TRUE(error == nullptr);
96-
} else {
97-
EXPECT_TRUE(error != nullptr);
98-
}
76+
return result;
77+
}
9978

100-
try {
101-
if (error) {
102-
std::rethrow_exception(error);
103-
}
104-
} catch (const util::GlyphRangeLoadingException&) {
105-
EXPECT_EQ(param, "glyphs.pbf");
106-
} catch (const util::SourceLoadingException&) {
107-
EXPECT_TRUE(param == "source_raster.json" || param == "source_vector.json");
108-
} catch (const util::SpriteLoadingException&) {
109-
EXPECT_TRUE(param == "sprite.png" || param == "sprite.json");
110-
} catch (const util::TileLoadingException&) {
111-
EXPECT_TRUE(param == "raster.png" || param == "vector.pbf");
112-
} catch (const std::exception&) {
113-
EXPECT_TRUE(false) << "Unhandled exception.";
114-
}
79+
TEST(ResourceLoading, Success) {
80+
EXPECT_EQ(resourceErrorString(MockFileSource::Success, ""), "");
81+
}
11582

116-
loop.stop();
117-
};
83+
TEST(ResourceLoading, RasterSourceFail) {
84+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "source_raster.json"),
85+
"Failed to load [test/fixtures/resources/source_raster.json]: Failed by the test case");
86+
}
11887

119-
std::unique_ptr<util::Thread<MockMapContext>> context(
120-
std::make_unique<util::Thread<MockMapContext>>(
121-
util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, callback));
88+
TEST(ResourceLoading, VectorSourceFail) {
89+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "source_vector.json"),
90+
"Failed to load [test/fixtures/resources/source_vector.json]: Failed by the test case");
91+
}
12292

123-
loop.run();
93+
TEST(ResourceLoading, SpriteJSONFail) {
94+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "sprite.json"),
95+
"Failed to load [test/fixtures/resources/sprite.json]: Failed by the test case");
96+
}
12497

125-
// Needed because it will make the Map thread
126-
// join and cease logging after this point.
127-
context->invoke(&MockMapContext::cleanup);
128-
context.reset();
98+
TEST(ResourceLoading, SpriteImageFail) {
99+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "sprite.png"),
100+
"Failed to load [test/fixtures/resources/sprite.png]: Failed by the test case");
101+
}
129102

130-
uint32_t match = 0;
131-
std::vector<FixtureLogObserver::LogMessage> logMessages = log->unchecked();
103+
TEST(ResourceLoading, RasterTileFail) {
104+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "raster.png"),
105+
"Failed to load [test/fixtures/resources/raster.png]: Failed by the test case");
106+
}
132107

133-
for (auto& logMessage : logMessages) {
134-
if (std::regex_match(logMessage.msg, std::regex(message))) {
135-
match++;
136-
}
137-
}
108+
TEST(ResourceLoading, VectorTileFail) {
109+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "vector.pbf"),
110+
"Failed to load [test/fixtures/resources/vector.pbf]: Failed by the test case");
111+
}
138112

139-
if (type == MockFileSource::Success) {
140-
EXPECT_EQ(match, 0u);
141-
} else {
142-
EXPECT_GT(match, 0u);
143-
}
113+
TEST(ResourceLoading, GlyphsFail) {
114+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "glyphs.pbf"),
115+
"Failed to load [test/fixtures/resources/glyphs.pbf]: Failed by the test case");
144116
}
145117

146-
} // namespace
118+
TEST(ResourceLoading, RasterSourceCorrupt) {
119+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "source_raster.json"),
120+
"Failed to parse [test/fixtures/resources/source_raster.json]: 0 - Invalid value.");
121+
}
147122

148-
class ResourceLoading : public ::testing::TestWithParam<std::pair<std::string, std::string>> {
149-
};
123+
TEST(ResourceLoading, VectorSourceCorrupt) {
124+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "source_vector.json"),
125+
"Failed to parse [test/fixtures/resources/source_vector.json]: 0 - Invalid value.");
126+
}
150127

151-
TEST_P(ResourceLoading, Success) {
152-
runTestCase(MockFileSource::Success, GetParam().first, std::string());
128+
TEST(ResourceLoading, SpriteJSONCorrupt) {
129+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "sprite.json"),
130+
"Failed to parse JSON: Invalid value. at offset 0");
153131
}
154132

155-
TEST_P(ResourceLoading, RequestFail) {
156-
std::stringstream message;
157-
message << "Failed to load \\[test\\/fixtures\\/resources\\/" << GetParam().first << "\\]\\: Failed by the test case";
133+
TEST(ResourceLoading, SpriteImageCorrupt) {
134+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "sprite.png"),
135+
"Could not parse sprite image");
136+
}
158137

159-
runTestCase(MockFileSource::RequestFail, GetParam().first, message.str());
138+
TEST(ResourceLoading, RasterTileCorrupt) {
139+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "raster.png"),
140+
"Failed to parse [0/0/0]: error parsing raster image");
160141
}
161142

162-
TEST_P(ResourceLoading, RequestWithCorruptedData) {
163-
runTestCase(MockFileSource::RequestWithCorruptedData, GetParam().first, GetParam().second);
143+
TEST(ResourceLoading, VectorTileCorrupt) {
144+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "vector.pbf"),
145+
"Failed to parse [0/0/0]: pbf unknown field type exception");
164146
}
165147

166-
INSTANTIATE_TEST_CASE_P(Style, ResourceLoading,
167-
::testing::Values(
168-
std::make_pair("source_raster.json", "Failed to parse \\[test\\/fixtures\\/resources\\/source_raster.json\\]: 0 - Invalid value."),
169-
std::make_pair("source_vector.json", "Failed to parse \\[test\\/fixtures\\/resources\\/source_vector.json\\]: 0 - Invalid value."),
170-
std::make_pair("sprite.json", "Failed to parse JSON: Invalid value. at offset 0"),
171-
std::make_pair("sprite.png", "Could not parse sprite image"),
172-
std::make_pair("raster.png", "Failed to parse \\[17\\/6553(4|5|6|7)\\/6553(4|5|6|7)\\]\\: error parsing raster image"),
173-
std::make_pair("vector.pbf", "Failed to parse \\[1(5|6)\\/1638(3|4)\\/1638(3|4)\\]\\: pbf unknown field type exception"),
174-
std::make_pair("glyphs.pbf", "Failed to parse \\[test\\/fixtures\\/resources\\/glyphs.pbf\\]: pbf unknown field type exception")));
148+
TEST(ResourceLoading, GlyphsCorrupt) {
149+
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "glyphs.pbf"),
150+
"Failed to parse [test/fixtures/resources/glyphs.pbf]: pbf unknown field type exception");
151+
}

0 commit comments

Comments
 (0)