Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/operations/document_lookup_in.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ auto
lookup_in_request::encode_to(lookup_in_request::encoded_request_type& encoded,
mcbp_context&& context) -> std::error_code
{
if (specs.empty()) {
return errc::common::invalid_argument;
}

for (std::size_t i = 0; i < specs.size(); ++i) {
specs[i].original_index_ = i;

Expand Down
4 changes: 4 additions & 0 deletions core/operations/document_lookup_in_all_replicas.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ struct lookup_in_all_replicas_request {
ec = errc::key_value::document_irretrievable;
}

if (!ec && specs.empty()) {
ec = errc::common::invalid_argument;
}

if (ec) {
return h(response_type{ make_subdocument_error_context(
make_key_value_error_context(ec, id), ec, {}, {}, false) });
Expand Down
4 changes: 4 additions & 0 deletions core/operations/document_lookup_in_any_replica.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ struct lookup_in_any_replica_request {
ec = errc::key_value::document_irretrievable;
}

if (!ec && specs.empty()) {
ec = errc::common::invalid_argument;
}

if (ec) {
return h(response_type{ make_subdocument_error_context(
make_key_value_error_context(ec, id), ec, {}, {}, false) });
Expand Down
3 changes: 3 additions & 0 deletions core/operations/document_mutate_in.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ mutate_in_request::encode_to(mutate_in_request::encoded_request_type& encoded,
!context.supports_feature(protocol::hello_feature::subdoc_create_as_deleted)) {
return errc::common::unsupported_operation;
}
if (specs.empty()) {
return errc::common::invalid_argument;
}
for (std::size_t i = 0; i < specs.size(); ++i) {
auto& entry = specs[i];
entry.original_index_ = i;
Expand Down
56 changes: 56 additions & 0 deletions test/test_integration_subdoc.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,62 @@ TEST_CASE("integration: subdoc any replica reads", "[integration]")
}
}

TEST_CASE("integration: subdoc invalid_argument if empty specs", "[integration]")
{
test::utils::integration_test_guard integration;

SECTION("core API")
{
couchbase::core::document_id id{
integration.ctx.bucket, "_default", "_default", test::utils::uniq_id("empty_specs")
};

couchbase::core::operations::lookup_in_request lookupin_req{ id };
auto lookupin_resp = test::utils::execute(integration.cluster, lookupin_req);
REQUIRE(lookupin_resp.ctx.ec() == couchbase::errc::common::invalid_argument);

couchbase::core::operations::lookup_in_any_replica_request lookupin_any_replica_req{ id };
auto lookupin_any_replica_resp =
test::utils::execute(integration.cluster, lookupin_any_replica_req);
REQUIRE(lookupin_any_replica_resp.ctx.ec() == couchbase::errc::common::invalid_argument);

couchbase::core::operations::lookup_in_all_replicas_request lookup_in_all_replicas_req{ id };
auto lookup_in_all_replicas_resp =
test::utils::execute(integration.cluster, lookup_in_all_replicas_req);
REQUIRE(lookup_in_all_replicas_resp.ctx.ec() == couchbase::errc::common::invalid_argument);

couchbase::core::operations::mutate_in_request mutatein_req{ id };
auto mutatein_resp = test::utils::execute(integration.cluster, mutatein_req);
REQUIRE(mutatein_resp.ctx.ec() == couchbase::errc::common::invalid_argument);
}

SECTION("public API")
{
auto test_ctx = integration.ctx;
auto [e, cluster] =
couchbase::cluster::connect(test_ctx.connection_string, test_ctx.build_options()).get();
REQUIRE_SUCCESS(e.ec());

auto collection = cluster.bucket(test_ctx.bucket).scope("_default").collection("_default");

auto key = test::utils::uniq_id("empty_specs");
auto [lookupin_err, lookupin_resp] = collection.lookup_in(key, {}).get();
REQUIRE(lookupin_err.ec() == couchbase::errc::common::invalid_argument);

auto [lookup_in_any_replica_err, lookup_in_any_replica_resp] =
collection.lookup_in_any_replica(key, {}).get();
REQUIRE(lookup_in_any_replica_err.ec() == couchbase::errc::common::invalid_argument);

auto [lookup_in_all_replicas_err, lookup_in_all_replicas_resp] =
collection.lookup_in_all_replicas(key, {}).get();
REQUIRE(lookup_in_all_replicas_err.ec() == couchbase::errc::common::invalid_argument);
REQUIRE(lookup_in_all_replicas_resp.empty());

auto [mutate_in_err, mutate_in_resp] = collection.mutate_in(key, {}).get();
REQUIRE(mutate_in_err.ec() == couchbase::errc::common::invalid_argument);
}
}

TEST_CASE("integration: public API lookup in per-spec errors", "[integration]")
{
test::utils::integration_test_guard integration;
Expand Down
Loading