Skip to content

Commit 64fa114

Browse files
authored
QuadTreeIndexVolatile method for QueryApi. (#741)
This is a part of prefetch update of VolatileLayerClient. The method is loading tile metadata like QueryApi::QuadTreeIndex(), but for volatile layer. Resolves: OLPEDGE-794 Signed-off-by: Kostiantyn Zvieriev <[email protected]>
1 parent 4b6d325 commit 64fa114

File tree

5 files changed

+333
-1
lines changed

5 files changed

+333
-1
lines changed

olp-cpp-sdk-core/src/client/OlpClient.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "olp/core/client/Condition.h"
2929
#include "olp/core/client/ErrorCode.h"
30+
#include "olp/core/http/HttpStatusCode.h"
3031
#include "olp/core/http/NetworkConstants.h"
3132
#include "olp/core/logging/Log.h"
3233
#include "olp/core/utils/Url.h"
@@ -372,6 +373,11 @@ HttpResponse OlpClient::CallApi(std::string path, std::string method,
372373
OlpClient::RequestBodyType post_body,
373374
std::string content_type,
374375
CancellationContext context) const {
376+
if (!settings_.network_request_handler) {
377+
return HttpResponse(static_cast<int>(olp::http::ErrorCode::OFFLINE_ERROR),
378+
"Network request handler is empty.");
379+
}
380+
375381
const auto& retry_settings = settings_.retry_settings;
376382
auto network_settings =
377383
http::NetworkSettings()

olp-cpp-sdk-dataservice-read/src/generated/api/QueryApi.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ constexpr auto kLogTag = "read::QueryApi";
3838

3939
std::string ConcatStringArray(const std::vector<std::string>& strings,
4040
const std::string& delimiter) {
41+
if (strings.empty()) {
42+
return {};
43+
}
4144
if (strings.size() == 1) {
4245
return strings.front();
4346
}
@@ -122,7 +125,41 @@ QueryApi::QuadTreeIndexResponse QueryApi::QuadTreeIndex(
122125
metadata_uri, "GET", std::move(query_params), std::move(header_params),
123126
{}, nullptr, std::string{}, std::move(context));
124127

125-
OLP_SDK_LOG_TRACE_F(kLogTag, "QuadTreeIndex, uri=%s, status=%d",
128+
OLP_SDK_LOG_DEBUG_F(kLogTag, "QuadTreeIndex, uri=%s, status=%d",
129+
metadata_uri.c_str(), response.status);
130+
if (response.status != olp::http::HttpStatusCode::OK) {
131+
return client::ApiError(response.status, response.response.str());
132+
}
133+
134+
return olp::parser::parse<model::Index>(response.response);
135+
}
136+
137+
QueryApi::QuadTreeIndexResponse QueryApi::QuadTreeIndexVolatile(
138+
const client::OlpClient& client, const std::string& layer_id,
139+
const std::string& quad_key, int32_t depth,
140+
boost::optional<std::vector<std::string>> additional_fields,
141+
boost::optional<std::string> billing_tag,
142+
client::CancellationContext context) {
143+
std::multimap<std::string, std::string> header_params;
144+
header_params.insert(std::make_pair("Accept", "application/json"));
145+
146+
std::multimap<std::string, std::string> query_params;
147+
if (additional_fields) {
148+
query_params.insert(std::make_pair(
149+
"additionalFields", ConcatStringArray(*additional_fields, ",")));
150+
}
151+
if (billing_tag) {
152+
query_params.insert(std::make_pair("billingTag", *billing_tag));
153+
}
154+
155+
std::string metadata_uri = "/layers/" + layer_id + "/quadkeys/" + quad_key +
156+
"/depths/" + std::to_string(depth);
157+
158+
client::HttpResponse response = client.CallApi(
159+
metadata_uri, "GET", std::move(query_params), std::move(header_params),
160+
{}, nullptr, std::string{}, std::move(context));
161+
162+
OLP_SDK_LOG_DEBUG_F(kLogTag, "QuadTreeIndex, uri=%s, status=%d",
126163
metadata_uri.c_str(), response.status);
127164
if (response.status != olp::http::HttpStatusCode::OK) {
128165
return client::ApiError(response.status, response.response.str());

olp-cpp-sdk-dataservice-read/src/generated/api/QueryApi.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,41 @@ class QueryApi {
112112
boost::optional<std::vector<std::string>> additional_fields,
113113
boost::optional<std::string> billing_tag,
114114
client::CancellationContext context);
115+
116+
/**
117+
* @brief Gets index metadata
118+
* Gets metadata synchronously for the requested index. Only available for
119+
* layers where the partitioning scheme is &#x60;heretile&#x60;.
120+
*
121+
* @param layer_id The ID of the layer specified in the request.
122+
* Content of this parameter must refer to a valid layer already configured
123+
* in the catalog configuration. Exactly one layer ID must be
124+
* provided.
125+
* @param quad_key The geometric area specified by an index in the request,
126+
* represented as a HERE tile
127+
* @param depth The recursion depth
128+
* of the response. If set to 0, the response includes only data for the
129+
* quad_key specified in the request. In this way, depth describes the maximum
130+
* length of the subQuadKeys in the response. The maximum allowed value for
131+
* the depth parameter is 4.
132+
* @param additional_fields Additional fields - &#x60;dataSize&#x60;,
133+
* &#x60;checksum&#x60;, &#x60;compressedDataSize&#x60;
134+
* @param billing_tag Billing Tag is an optional free-form tag used to
135+
* group billing records together. If supplied, it must be between 4 - 16
136+
* characters and contain only alphanumeric ASCII characters [A-Za-z0-9].
137+
* Grouping billing records by billing tag will be available in a future
138+
* release.
139+
* @param context A CancellationContext instance which can be used to cancel
140+
* call of this method.
141+
* @param The result of this operation as a client::ApiResponse object with \c
142+
* model::Index as a result
143+
**/
144+
static QuadTreeIndexResponse QuadTreeIndexVolatile(
145+
const client::OlpClient& client, const std::string& layer_id,
146+
const std::string& quad_key, int32_t depth,
147+
boost::optional<std::vector<std::string>> additional_fields,
148+
boost::optional<std::string> billing_tag,
149+
client::CancellationContext context);
115150
};
116151

117152
} // namespace read

olp-cpp-sdk-dataservice-read/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ set(OLP_SDK_DATASERVICE_READ_TEST_SOURCES
2323
ParserTest.cpp
2424
PartitionsRepositoryTest.cpp
2525
PrefetchRepositoryTest.cpp
26+
QueryApiTest.cpp
2627
SerializerTest.cpp
2728
StreamApiTest.cpp
2829
StreamLayerClientImplTest.cpp
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
/*
2+
* Copyright (C) 2020 HERE Europe B.V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
#include <gmock/gmock-matchers.h>
21+
#include <gmock/gmock.h>
22+
#include <matchers/NetworkUrlMatchers.h>
23+
#include <mocks/NetworkMock.h>
24+
#include <olp/core/client/OlpClient.h>
25+
#include <olp/core/client/OlpClientFactory.h>
26+
#include <olp/core/client/OlpClientSettingsFactory.h>
27+
#include "generated/api/QueryApi.h"
28+
29+
namespace {
30+
constexpr auto kLayerid = "test-layer";
31+
constexpr auto kQuadKey = "23618401";
32+
constexpr auto kNodeBaseUrl =
33+
"https://some.node.base.url/stream/v2/catalogs/"
34+
"hrn:here:data::olp-here-test:hereos-internal-test-v2";
35+
constexpr auto kUrlQuadTreeIndexVolatile =
36+
R"(https://some.node.base.url/stream/v2/catalogs/hrn:here:data::olp-here-test:hereos-internal-test-v2/layers/test-layer/quadkeys/23618401/depths/2)";
37+
38+
constexpr auto kUrlQuadTreeIndexVolatileAllInputs =
39+
R"(https://some.node.base.url/stream/v2/catalogs/hrn:here:data::olp-here-test:hereos-internal-test-v2/layers/test-layer/quadkeys/23618401/depths/2?additionalFields=checksum%2CdataSize&billingTag=OlpCppSdkTest)";
40+
41+
constexpr auto kHttpResponseEmpty = R"jsonString()jsonString";
42+
constexpr auto kHttpResponseQuadTreeIndexVolatile =
43+
R"jsonString({ "parentQuads": [ { "additionalMetadata": "string", "checksum": "string", "compressedDataSize": 0, "dataHandle": "675911FF6236B7C7604BF8B105F1BB58", "dataSize": 0, "crc": "c3f276d7", "partition": "73982", "version": 0 } ], "subQuads": [ { "additionalMetadata": "string", "checksum": "291f66029c232400e3403cd6e9cfd36e", "compressedDataSize": 200, "dataHandle": "1b2ca68f-d4a0-4379-8120-cd025640510c", "dataSize": 1024, "crc": "c3f276d7", "subQuadKey": "string", "version": 1 } ] })jsonString";
44+
45+
using namespace ::testing;
46+
using namespace olp;
47+
using namespace olp::client;
48+
using namespace olp::dataservice::read;
49+
using namespace olp::tests::common;
50+
51+
class QueryApiTest : public Test {
52+
protected:
53+
void SetUp() override {
54+
network_mock_ = std::make_shared<NetworkMock>();
55+
56+
settings_ = std::make_shared<OlpClientSettings>();
57+
settings_->network_request_handler = network_mock_;
58+
59+
client_ = OlpClientFactory::Create(*settings_);
60+
client_->SetBaseUrl(kNodeBaseUrl);
61+
}
62+
void TearDown() override { network_mock_.reset(); }
63+
64+
protected:
65+
std::shared_ptr<OlpClientSettings> settings_;
66+
std::shared_ptr<OlpClient> client_;
67+
std::shared_ptr<NetworkMock> network_mock_;
68+
};
69+
70+
TEST_F(QueryApiTest, QuadTreeIndexVolatile) {
71+
{
72+
SCOPED_TRACE("Request metadata for tile.");
73+
EXPECT_CALL(
74+
*network_mock_,
75+
Send(AllOf(IsGetRequest(kUrlQuadTreeIndexVolatile)), _, _, _, _))
76+
.WillOnce(ReturnHttpResponse(
77+
http::NetworkResponse().WithStatus(http::HttpStatusCode::OK),
78+
kHttpResponseQuadTreeIndexVolatile));
79+
80+
int32_t depth = 2;
81+
auto index_response =
82+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
83+
*client_, kLayerid, kQuadKey, depth, boost::none, boost::none,
84+
olp::client::CancellationContext{});
85+
86+
ASSERT_TRUE(index_response.IsSuccessful());
87+
auto result = index_response.GetResult();
88+
ASSERT_EQ(1u, result.GetSubQuads().size());
89+
ASSERT_EQ(1u, result.GetParentQuads().size());
90+
}
91+
{
92+
SCOPED_TRACE("Request with billing tag + additional fields.");
93+
EXPECT_CALL(*network_mock_,
94+
Send(AllOf(IsGetRequest(kUrlQuadTreeIndexVolatileAllInputs)), _,
95+
_, _, _))
96+
.WillOnce(ReturnHttpResponse(
97+
http::NetworkResponse().WithStatus(http::HttpStatusCode::OK),
98+
kHttpResponseQuadTreeIndexVolatile));
99+
100+
int32_t depth = 2;
101+
std::string billing_tag = "OlpCppSdkTest";
102+
std::vector<std::string> additional_fields = {"checksum", "dataSize"};
103+
auto index_response =
104+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
105+
*client_, kLayerid, kQuadKey, depth, additional_fields, billing_tag,
106+
olp::client::CancellationContext{});
107+
108+
ASSERT_TRUE(index_response.IsSuccessful());
109+
auto result = index_response.GetResult();
110+
ASSERT_EQ(1u, result.GetSubQuads().size());
111+
ASSERT_EQ(1u, result.GetParentQuads().size());
112+
}
113+
// negative tests
114+
{
115+
SCOPED_TRACE("Requested quead not found.");
116+
EXPECT_CALL(
117+
*network_mock_,
118+
Send(AllOf(IsGetRequest(kUrlQuadTreeIndexVolatile)), _, _, _, _))
119+
.WillOnce(ReturnHttpResponse(
120+
http::NetworkResponse().WithStatus(http::HttpStatusCode::NOT_FOUND),
121+
kHttpResponseEmpty));
122+
123+
int32_t depth = 2;
124+
auto index_response =
125+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
126+
*client_, kLayerid, kQuadKey, depth, boost::none, boost::none,
127+
olp::client::CancellationContext{});
128+
129+
ASSERT_FALSE(index_response.IsSuccessful());
130+
auto error = index_response.GetError();
131+
ASSERT_EQ(http::HttpStatusCode::NOT_FOUND, error.GetHttpStatusCode());
132+
ASSERT_EQ(kHttpResponseEmpty, error.GetMessage());
133+
}
134+
{
135+
SCOPED_TRACE("Not configured olp client");
136+
auto client = OlpClient();
137+
int32_t depth = 2;
138+
auto index_response =
139+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
140+
client, kLayerid, kQuadKey, depth, boost::none, boost::none,
141+
olp::client::CancellationContext{});
142+
143+
ASSERT_FALSE(index_response.IsSuccessful());
144+
auto error = index_response.GetError();
145+
ASSERT_EQ(static_cast<int>(olp::http::ErrorCode::OFFLINE_ERROR), error.GetHttpStatusCode());
146+
}
147+
{
148+
SCOPED_TRACE("Invalid layer id");
149+
EXPECT_CALL(*network_mock_, Send(_, _, _, _, _))
150+
.WillOnce(ReturnHttpResponse(http::NetworkResponse().WithStatus(
151+
http::HttpStatusCode::BAD_REQUEST),
152+
kHttpResponseEmpty));
153+
int32_t depth = 2;
154+
auto index_response =
155+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
156+
*client_, {}, kQuadKey, depth, boost::none, boost::none,
157+
olp::client::CancellationContext{});
158+
159+
ASSERT_FALSE(index_response.IsSuccessful());
160+
auto error = index_response.GetError();
161+
ASSERT_EQ(http::HttpStatusCode::BAD_REQUEST, error.GetHttpStatusCode());
162+
ASSERT_EQ(kHttpResponseEmpty, error.GetMessage());
163+
}
164+
{
165+
SCOPED_TRACE("Invalid quad key.");
166+
EXPECT_CALL(*network_mock_, Send(_, _, _, _, _))
167+
.WillOnce(ReturnHttpResponse(http::NetworkResponse().WithStatus(
168+
http::HttpStatusCode::BAD_REQUEST),
169+
kHttpResponseEmpty));
170+
int32_t depth = 2;
171+
auto index_response =
172+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
173+
*client_, kLayerid, {}, depth, boost::none, boost::none,
174+
olp::client::CancellationContext{});
175+
176+
ASSERT_FALSE(index_response.IsSuccessful());
177+
auto error = index_response.GetError();
178+
ASSERT_EQ(http::HttpStatusCode::BAD_REQUEST, error.GetHttpStatusCode());
179+
ASSERT_EQ(kHttpResponseEmpty, error.GetMessage());
180+
}
181+
{
182+
SCOPED_TRACE("Invalid depth.");
183+
EXPECT_CALL(*network_mock_, Send(_, _, _, _, _))
184+
.WillOnce(ReturnHttpResponse(http::NetworkResponse().WithStatus(
185+
http::HttpStatusCode::BAD_REQUEST),
186+
kHttpResponseEmpty));
187+
int32_t depth = -1;
188+
auto index_response =
189+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
190+
*client_, kLayerid, kQuadKey, depth, boost::none, boost::none,
191+
olp::client::CancellationContext{});
192+
193+
ASSERT_FALSE(index_response.IsSuccessful());
194+
auto error = index_response.GetError();
195+
ASSERT_EQ(http::HttpStatusCode::BAD_REQUEST, error.GetHttpStatusCode());
196+
ASSERT_EQ(kHttpResponseEmpty, error.GetMessage());
197+
}
198+
{
199+
SCOPED_TRACE("Empty additional fields.");
200+
EXPECT_CALL(*network_mock_, Send(_, _, _, _, _))
201+
.WillOnce(ReturnHttpResponse(http::NetworkResponse().WithStatus(
202+
http::HttpStatusCode::BAD_REQUEST),
203+
kHttpResponseEmpty));
204+
205+
int32_t depth = 2;
206+
std::vector<std::string> empty_fields;
207+
auto index_response =
208+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
209+
*client_, kLayerid, kQuadKey, depth, empty_fields, boost::none,
210+
olp::client::CancellationContext{});
211+
212+
ASSERT_FALSE(index_response.IsSuccessful());
213+
auto error = index_response.GetError();
214+
ASSERT_EQ(http::HttpStatusCode::BAD_REQUEST, error.GetHttpStatusCode());
215+
ASSERT_EQ(kHttpResponseEmpty, error.GetMessage());
216+
}
217+
{
218+
SCOPED_TRACE("Empty billing tag.");
219+
EXPECT_CALL(*network_mock_, Send(_, _, _, _, _))
220+
.WillOnce(ReturnHttpResponse(http::NetworkResponse().WithStatus(
221+
http::HttpStatusCode::BAD_REQUEST),
222+
kHttpResponseEmpty));
223+
224+
int32_t depth = 2;
225+
std::string empty_tag;
226+
auto index_response =
227+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
228+
*client_, kLayerid, kQuadKey, depth, boost::none, empty_tag,
229+
olp::client::CancellationContext{});
230+
231+
ASSERT_FALSE(index_response.IsSuccessful());
232+
auto error = index_response.GetError();
233+
ASSERT_EQ(http::HttpStatusCode::BAD_REQUEST, error.GetHttpStatusCode());
234+
ASSERT_EQ(kHttpResponseEmpty, error.GetMessage());
235+
}
236+
{
237+
SCOPED_TRACE("Cancelled CancellationContext");
238+
239+
auto context = olp::client::CancellationContext();
240+
context.CancelOperation();
241+
int32_t depth = 2;
242+
auto index_response =
243+
olp::dataservice::read::QueryApi::QuadTreeIndexVolatile(
244+
*client_, kLayerid, kQuadKey, depth, boost::none, boost::none,
245+
context);
246+
247+
ASSERT_FALSE(index_response.IsSuccessful());
248+
auto error = index_response.GetError();
249+
ASSERT_EQ(olp::client::ErrorCode::Cancelled, error.GetErrorCode());
250+
}
251+
}
252+
253+
} // namespace

0 commit comments

Comments
 (0)