diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index b1cf174bd..2d11d16b1 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -199,6 +199,15 @@ Layer* Style::getLayer(const std::string& id) const { Layer* Style::addLayer(std::unique_ptr layer, optional before) { // TODO: verify source + // Guard against duplicate layer ids + auto it = std::find_if(layers.begin(), layers.end(), [&](const auto& existing) { + return existing->getID() == layer->getID(); + }); + + if (it != layers.end()) { + throw std::runtime_error(std::string{"Layer "} + layer->getID() + " already exists"); + } + if (SymbolLayer* symbolLayer = layer->as()) { if (!symbolLayer->impl->spriteAtlas) { symbolLayer->impl->spriteAtlas = spriteAtlas.get(); diff --git a/test/style/style_layer.test.cpp b/test/style/style_layer.test.cpp index f6dcc684c..8356f3acc 100644 --- a/test/style/style_layer.test.cpp +++ b/test/style/style_layer.test.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include #include @@ -15,6 +17,10 @@ #include #include #include +#include +#include + +#include using namespace mbgl; using namespace mbgl::style; @@ -268,3 +274,25 @@ TEST(Layer, Observer) { layer->setLineCap(lineCap); EXPECT_FALSE(layoutPropertyChanged); } + +TEST(Layer, DuplicateLayer) { + util::RunLoop loop; + + //Setup style + StubFileSource fileSource; + Style style { fileSource, 1.0 }; + style.setJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); + + //Add initial layer + style.addLayer(std::make_unique("line", "unusedsource")); + + //Try to add duplicate + try { + style.addLayer(std::make_unique("line", "unusedsource")); + FAIL() << "Should not have been allowed to add a duplicate layer id"; + } catch (const std::runtime_error e) { + //Expected + ASSERT_STREQ("Layer line already exists", e.what()); + } +} +