Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

MB-13648: Subdoc API SUBDOC_EXISTS support

Add support for the SUBDOC_EXISTS command. This is essentially the
same as SUBDOC_GET, except it doesn't return the content of the
sub-document, only a status code.

Change-Id: I22728cf51addd6aa0ec109b8e082a1fcea997caf
Reviewed-on: http://review.couchbase.org/50067
Tested-by: buildbot <build@couchbase.com>
Reviewed-by: Trond Norbye <trond.norbye@gmail.com>
  • Loading branch information...
commit 3bb6cef19593e77794753d24721a8972b2d2b864 1 parent 2198c75
@daverigby daverigby authored trondn committed
View
4 daemon/memcached.c
@@ -5249,7 +5249,8 @@ static void setup_bin_packet_handlers(void) {
validators[PROTOCOL_BINARY_CMD_GET_ADJUSTED_TIME] = get_adjusted_time_validator;
validators[PROTOCOL_BINARY_CMD_SET_DRIFT_COUNTER_STATE] = set_drift_counter_state_validator;
- validators[PROTOCOL_BINARY_CMD_SUBDOC_GET] = subdoc_get_validator;
+ validators[PROTOCOL_BINARY_CMD_SUBDOC_GET] = subdoc_get_exists_validator;
+ validators[PROTOCOL_BINARY_CMD_SUBDOC_EXISTS] = subdoc_get_exists_validator;
validators[PROTOCOL_BINARY_CMD_SETQ] = set_replace_validator;
validators[PROTOCOL_BINARY_CMD_SET] = set_replace_validator;
@@ -5332,6 +5333,7 @@ static void setup_bin_packet_handlers(void) {
executors[PROTOCOL_BINARY_CMD_AUDIT_CONFIG_RELOAD] = audit_config_reload_executor;
executors[PROTOCOL_BINARY_CMD_SUBDOC_GET] = subdoc_get_executor;
+ executors[PROTOCOL_BINARY_CMD_SUBDOC_EXISTS] = subdoc_exists_executor;
}
View
1  daemon/rbac.json
@@ -133,6 +133,7 @@
"START_PERSISTENCE",
"STAT",
"STOP_PERSISTENCE",
+ "SUBDOC_EXISTS",
"SUBDOC_GET",
"TOUCH",
"UNLOCK_KEY",
View
54 daemon/subdocument.cc
@@ -30,11 +30,42 @@ struct sized_buffer {
size_t len;
};
+/* Convert integers to types, to allow type traits for different
+ * protocol_binary_commands, etc.
+ */
+template <protocol_binary_command C>
+struct Cmd2Type
+{
+ enum { value = C };
+};
+
+/* Traits of each of the sub-document commands. These are used to build up
+ * the individual implementations using generic building blocks:
+ *
+ * optype: The subjson API optype for this command.
+ * response_has_value: Does the command response include a value?
+ */
+template <typename T>
+struct cmd_traits;
+
+template <>
+struct cmd_traits<Cmd2Type<PROTOCOL_BINARY_CMD_SUBDOC_GET> > {
+ static const subdoc_OPTYPE optype = SUBDOC_CMD_GET;
+ static const bool response_has_value = true;
+};
+
+template <>
+struct cmd_traits<Cmd2Type<PROTOCOL_BINARY_CMD_SUBDOC_EXISTS> > {
+ static const subdoc_OPTYPE optype = SUBDOC_CMD_EXISTS;
+ static const bool response_has_value = false;
+};
+
/*
* Subdocument command validators
*/
-int subdoc_get_validator(void* packet) {
+template<protocol_binary_command CMD>
+static int subdoc_validator(void* packet) {
const protocol_binary_request_subdocument *req =
reinterpret_cast<protocol_binary_request_subdocument*>(packet);
const protocol_binary_request_header* header = &req->message.header;
@@ -60,6 +91,10 @@ int subdoc_get_validator(void* packet) {
return 0;
}
+int subdoc_get_exists_validator(void* packet) {
+ return subdoc_validator<PROTOCOL_BINARY_CMD_SUBDOC_GET>(packet);
+}
+
/******************************************************************************
* Subdocument executors
*****************************************************************************/
@@ -376,7 +411,7 @@ static bool subdoc_operate(conn* c, const char* path, size_t pathlen,
// Prepare the specified sub-document command.
subdoc_OPERATION* op = c->thread->subdoc_op;
subdoc_op_clear(op);
- SUBDOC_OP_SETCODE(op, SUBDOC_CMD_GET);
+ SUBDOC_OP_SETCODE(op, cmd_traits<Cmd2Type<CMD>>::optype);
SUBDOC_OP_SETDOC(op, doc.buf, doc.len);
// ... and execute it.
@@ -433,8 +468,10 @@ void subdoc_response(conn* c) {
const char* value = NULL;
size_t vallen = 0;
- value = c->thread->subdoc_op->match.loc_match.at;
- vallen = c->thread->subdoc_op->match.loc_match.length;
+ if (cmd_traits<Cmd2Type<CMD>>::response_has_value) {
+ value = c->thread->subdoc_op->match.loc_match.at;
+ vallen = c->thread->subdoc_op->match.loc_match.length;
+ }
if (add_bin_header(c, 0, /*extlen*/0, /*keylen*/0, vallen,
PROTOCOL_BINARY_RAW_BYTES) == -1) {
@@ -443,11 +480,16 @@ void subdoc_response(conn* c) {
}
rsp->message.header.response.cas = htonll(c->cas);
- add_iov(c, value, vallen);
-
+ if (cmd_traits<Cmd2Type<CMD>>::response_has_value) {
+ add_iov(c, value, vallen);
+ }
conn_set_state(c, conn_mwrite);
}
void subdoc_get_executor(conn *c, void* packet) {
return subdoc_executor<PROTOCOL_BINARY_CMD_SUBDOC_GET>(c, packet);
}
+
+void subdoc_exists_executor(conn *c, void* packet) {
+ return subdoc_executor<PROTOCOL_BINARY_CMD_SUBDOC_EXISTS>(c, packet);
+}
View
7 daemon/subdocument.h
@@ -32,11 +32,12 @@ extern "C" {
/* Maximum sub-document path length */
const size_t SUBDOC_PATH_MAX_LENGTH = 1024;
-/* Validate a subdocument get command. returns 0 if valid, else -1. */
-int subdoc_get_validator(void* packet);
+/* Subdocument validator functions. Returns 0 if valid, else -1. */
+int subdoc_get_exists_validator(void* packet);
-/* Execute a subdocument get command. */
+/* Subdocument executor functions. */
void subdoc_get_executor(conn *c, void *packet);
+void subdoc_exists_executor(conn *c, void *packet);
#if defined(__cplusplus)
} // extern "C"
View
16 tests/testapp.c
@@ -1384,6 +1384,12 @@ void validate_response_header(protocol_binary_response_no_extras *response,
cb_assert(header->response.bodylen != 0);
cb_assert(header->response.cas != 0);
break;
+ case PROTOCOL_BINARY_CMD_SUBDOC_EXISTS:
+ cb_assert(header->response.keylen == 0);
+ cb_assert(header->response.extlen == 0);
+ cb_assert(header->response.bodylen == 0);
+ cb_assert(header->response.cas != 0);
+ break;
default:
/* Undefined command code */
break;
@@ -4247,6 +4253,16 @@ struct testcase testcases[] = {
TESTCASE_PLAIN_AND_SSL("subdoc_get_dict_nested_compressed", test_subdoc_get_dict_nested_compressed),
TESTCASE_PLAIN_AND_SSL("subdoc_get_dict_deep", test_subdoc_get_dict_deep),
TESTCASE_PLAIN_AND_SSL("subdoc_get_array_deep", test_subdoc_get_array_deep),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_binary_raw", test_subdoc_exists_binary_raw),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_binary_compressed", test_subdoc_exists_binary_compressed),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_array_simple_raw", test_subdoc_exists_array_simple_raw),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_array_simple_compressed", test_subdoc_exists_array_simple_compressed),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_dict_simple_raw", test_subdoc_exists_dict_simple_raw),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_dict_simple_compressed", test_subdoc_exists_dict_simple_compressed),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_dict_nested_raw", test_subdoc_exists_dict_nested_raw),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_dict_nested_compressed", test_subdoc_exists_dict_nested_compressed),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_dict_deep", test_subdoc_exists_dict_deep),
+ TESTCASE_PLAIN_AND_SSL("subdoc_exists_array_deep", test_subdoc_exists_array_deep),
TESTCASE_PLAIN(NULL, NULL)
};
View
193 tests/testapp_subdoc.cc
@@ -147,13 +147,22 @@ static void expect_subdoc_cmd(const SubdocCmd& cmd,
cmd.cmd, expected_status);
// TODO: Check extras for subdoc command and mutation / seqno (if enabled).
- if (!expected_value.empty()) {
- const protocol_binary_response_header* header = &receive.response.message.header;
- const char* val_ptr = receive.bytes + sizeof(*header) +
- header->response.extlen;
- const size_t vallen = header->response.bodylen + header->response.extlen;
+
+ const protocol_binary_response_header* header = &receive.response.message.header;
+ const char* val_ptr = receive.bytes + sizeof(*header) +
+ header->response.extlen;
+ const size_t vallen = header->response.bodylen + header->response.extlen;
+
+ if (!expected_value.empty() &&
+ (cmd.cmd != PROTOCOL_BINARY_CMD_SUBDOC_EXISTS)) {
const std::string val(val_ptr, val_ptr + vallen);
check_equal(val, expected_value);
+ } else {
+ // Expect zero length on success (on error the error message string is
+ // returned).
+ if (header->response.status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
+ cb_assert(vallen == 0);
+ }
}
}
@@ -183,12 +192,13 @@ static void store_object(const std::string& key, const std::string& value,
}
// Non JSON document, optionally compressed. Subdoc commands should fail.
-static enum test_return test_subdoc_get_binary(bool compress) {
+static enum test_return test_subdoc_get_binary(bool compress,
+ protocol_binary_command cmd) {
const char not_JSON[] = "not; json";
store_object("binary", not_JSON);
// a). Check that access fails with DOC_NOTJSON
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "binary", "[0]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "binary", "[0]"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_DOC_NOTJSON, "");
delete_object("binary");
@@ -197,58 +207,70 @@ static enum test_return test_subdoc_get_binary(bool compress) {
}
enum test_return test_subdoc_get_binary_raw() {
- return test_subdoc_get_binary(/*compress*/false);
+ return test_subdoc_get_binary(/*compress*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
}
enum test_return test_subdoc_get_binary_compressed() {
- return test_subdoc_get_binary(/*compress*/true);
+ return test_subdoc_get_binary(/*compress*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
+}
+
+enum test_return test_subdoc_exists_binary_raw() {
+ return test_subdoc_get_binary(/*compress*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
+enum test_return test_subdoc_exists_binary_compressed() {
+ return test_subdoc_get_binary(/*compress*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
}
-// JSON document consisting of a toplevel array.
-static enum test_return test_subdoc_get_array_simple(bool compressed) {
+// retrieve from a JSON document consisting of a toplevel array.
+static enum test_return
+test_subdoc_fetch_array_simple(bool compressed, protocol_binary_command cmd) {
+
+ cb_assert((cmd == PROTOCOL_BINARY_CMD_SUBDOC_GET) ||
+ (cmd == PROTOCOL_BINARY_CMD_SUBDOC_EXISTS));
const char array[] = "[ 0, \"one\", 2.0 ]";
store_object("array", array, /*JSON*/true, compressed);
// a). Check successful access to each array element.
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[0]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[0]"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "0");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[1]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[1]"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "\"one\"");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[2]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[2]"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "2.0");
// b). Check successful access to last element (using -1).
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[-1]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[-1]"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "2.0");
// c). Check -2 treated as invalid index (only -1 permitted).
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[-2]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[-2]"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_EINVAL, "");
// d). Check failure accessing out-of-range index.
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[3]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[3]"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_ENOENT, "");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[9999]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[9999]"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_ENOENT, "");
// e). Check failure accessing array as dict.
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array",
- "missing_key"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "missing_key"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH, "");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array",
- "[2].nothing_here"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", "[2].nothing_here"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH, "");
// f). Check path longer than SUBDOC_PATH_MAX_LENGTH is invalid.
std::string too_long_path(1024 + 1, '.');
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array",
- too_long_path),
+ expect_subdoc_cmd(SubdocCmd(cmd, "array", too_long_path),
PROTOCOL_BINARY_RESPONSE_EINVAL, "");
// g). Check that incorrect flags (i.e. non-zero) is invalid.
- SubdocCmd bad_flags(PROTOCOL_BINARY_CMD_SUBDOC_GET, "array", "[0]");
+ SubdocCmd bad_flags(cmd, "array", "[0]");
bad_flags.flags = SUBDOC_FLAG_MKDIR_P;
expect_subdoc_cmd(bad_flags, PROTOCOL_BINARY_RESPONSE_EINVAL, "");
@@ -258,15 +280,29 @@ static enum test_return test_subdoc_get_array_simple(bool compressed) {
}
enum test_return test_subdoc_get_array_simple_raw() {
- return test_subdoc_get_array_simple(/*compressed*/false);
+ return test_subdoc_fetch_array_simple(/*compressed*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
}
enum test_return test_subdoc_get_array_simple_compressed() {
- return test_subdoc_get_array_simple(/*compressed*/true);
+ return test_subdoc_fetch_array_simple(/*compressed*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
}
+enum test_return test_subdoc_exists_array_simple_raw() {
+ return test_subdoc_fetch_array_simple(/*compressed*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
+enum test_return test_subdoc_exists_array_simple_compressed() {
+ return test_subdoc_fetch_array_simple(/*compressed*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
// JSON document containing toplevel dict.
-static enum test_return test_subdoc_get_dict_simple(bool compressed) {
+static enum test_return test_subdoc_fetch_dict_simple(bool compressed,
+ protocol_binary_command cmd) {
+
+ cb_assert((cmd == PROTOCOL_BINARY_CMD_SUBDOC_GET) ||
+ (cmd == PROTOCOL_BINARY_CMD_SUBDOC_EXISTS));
const char dict[] = "{ \"int\": 1,"
" \"string\": \"two\","
@@ -275,26 +311,25 @@ static enum test_return test_subdoc_get_dict_simple(bool compressed) {
store_object("dict", dict, /*JSON*/true, compressed);
// a). Check successful access to each dict element.
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict", "int"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "int"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "1");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict", "string"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "string"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "\"two\"");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict", "true"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "true"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "true");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict", "false"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "false"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "false");
// b). Check failure accessing non-existent keys.
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict", "missing_key"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "missing_key"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_ENOENT, "");
// c). Check failure accessing object incorrectly (wrong type).
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict", "[0]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "[0]"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH, "");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict", "[-1]"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "[-1]"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH, "");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict",
- "int.nothing_here"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict", "int.nothing_here"),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_MISMATCH, "");
delete_object("dict");
@@ -303,15 +338,29 @@ static enum test_return test_subdoc_get_dict_simple(bool compressed) {
}
enum test_return test_subdoc_get_dict_simple_raw() {
- return test_subdoc_get_dict_simple(/*compressed*/false);
+ return test_subdoc_fetch_dict_simple(/*compressed*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
}
enum test_return test_subdoc_get_dict_simple_compressed() {
- return test_subdoc_get_dict_simple(/*compressed*/true);
+ return test_subdoc_fetch_dict_simple(/*compressed*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
}
+enum test_return test_subdoc_exists_dict_simple_raw() {
+ return test_subdoc_fetch_dict_simple(/*compressed*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
+enum test_return test_subdoc_exists_dict_simple_compressed() {
+ return test_subdoc_fetch_dict_simple(/*compressed*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
// JSON document containing nested dictionary.
-static enum test_return test_subdoc_get_dict_nested(bool compressed) {
+static enum test_return test_subdoc_fetch_dict_nested(bool compressed,
+ protocol_binary_command cmd) {
+
+ cb_assert((cmd == PROTOCOL_BINARY_CMD_SUBDOC_GET) ||
+ (cmd == PROTOCOL_BINARY_CMD_SUBDOC_EXISTS));
// Getting a bit complex to do raw (with all the quote escaping so use
// cJSON API.
@@ -341,33 +390,27 @@ static enum test_return test_subdoc_get_dict_nested(bool compressed) {
cJSON_Free(dict_str);
// a). Check successful access to individual nested components.
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict2",
- "name.title"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict2", "name.title"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "\"Mr\"");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict2",
- "name.first"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict2", "name.first"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "\"Joseph\"");
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict2",
- "name.last"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict2", "name.last"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "\"Bloggs\"");
// b). Check successful access to a whole sub-dictionary.
char* name_str = cJSON_PrintUnformatted(name);
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict2",
- "name"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict2", "name"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, name_str);
cJSON_Free(name_str);
// c). Check successful access to a whole sub-array.
char* orders_str = cJSON_PrintUnformatted(orders);
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict2",
- "orders"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict2", "orders"),
PROTOCOL_BINARY_RESPONSE_SUCCESS, orders_str);
cJSON_Free(orders_str);
// d). Check access to dict in array.
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "dict2",
- "orders[0].date"),
+ expect_subdoc_cmd(SubdocCmd(cmd, "dict2", "orders[0].date"),
PROTOCOL_BINARY_RESPONSE_SUCCESS,
"\"2020-04-04T18:17:04Z\"");
@@ -377,10 +420,20 @@ static enum test_return test_subdoc_get_dict_nested(bool compressed) {
}
enum test_return test_subdoc_get_dict_nested_raw() {
- return test_subdoc_get_dict_nested(/*compressed*/false);
+ return test_subdoc_fetch_dict_nested(/*compressed*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
}
enum test_return test_subdoc_get_dict_nested_compressed() {
- return test_subdoc_get_dict_nested(/*compressed*/true);
+ return test_subdoc_fetch_dict_nested(/*compressed*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_GET);
+}
+enum test_return test_subdoc_exists_dict_nested_raw() {
+ return test_subdoc_fetch_dict_nested(/*compressed*/false,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
+enum test_return test_subdoc_exists_dict_nested_compressed() {
+ return test_subdoc_fetch_dict_nested(/*compressed*/true,
+ PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
}
// Creates a nested dictionary with the specified number of levels.
@@ -399,7 +452,8 @@ static cJSON* make_nested_dict(int nlevels) {
}
// Deeply nested JSON dictionary; verify limits on how deep documents can be.
-enum test_return test_subdoc_get_dict_deep() {
+static enum test_return
+test_subdoc_fetch_dict_deep(protocol_binary_command cmd) {
// Maximum depth for a document (and path) is 32. Create documents
// that large and one bigger to test with.
@@ -416,8 +470,7 @@ enum test_return test_subdoc_get_dict_deep() {
for (int depth = 2; depth < MAX_SUBDOC_PATH_COMPONENTS; depth++) {
valid_max_path += std::string(".") + std::to_string(depth);
}
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "max_dict",
- valid_max_path),
+ expect_subdoc_cmd(SubdocCmd(cmd, "max_dict", valid_max_path),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "{}");
delete_object("max_dict");
@@ -432,8 +485,7 @@ enum test_return test_subdoc_get_dict_deep() {
for (int depth = 2; depth < MAX_SUBDOC_PATH_COMPONENTS + 1; depth++) {
too_long_path += std::string(".") + std::to_string(depth);
}
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "too_deep_dict",
- too_long_path),
+ expect_subdoc_cmd(SubdocCmd(cmd, "too_deep_dict", too_long_path),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_E2BIG, "");
delete_object("too_deep_dict");
@@ -441,6 +493,13 @@ enum test_return test_subdoc_get_dict_deep() {
return TEST_PASS;
}
+enum test_return test_subdoc_get_dict_deep() {
+ return test_subdoc_fetch_dict_deep(PROTOCOL_BINARY_CMD_SUBDOC_GET);
+}
+enum test_return test_subdoc_exists_dict_deep() {
+ return test_subdoc_fetch_dict_deep(PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
+
// Creates a nested array with the specified number of levels.
// Caller is responsible for calling cJSON_Free() on the result when finished
//with.
@@ -456,7 +515,8 @@ static cJSON* make_nested_array(int nlevels) {
}
// Deeply nested JSON array; verify limits on how deep documents can be.
-enum test_return test_subdoc_get_array_deep() {
+static enum test_return
+test_subdoc_fetch_array_deep(protocol_binary_command cmd) {
// Maximum depth for a document (and path) is 32. Create documents
// that large and one bigger to test with.
@@ -474,8 +534,7 @@ enum test_return test_subdoc_get_array_deep() {
for (int depth = 1; depth < MAX_SUBDOC_PATH_COMPONENTS; depth++) {
valid_max_path += "[0]";
}
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "max_array",
- valid_max_path),
+ expect_subdoc_cmd(SubdocCmd(cmd, "max_array", valid_max_path),
PROTOCOL_BINARY_RESPONSE_SUCCESS, "[]");
delete_object("max_array");
@@ -489,10 +548,16 @@ enum test_return test_subdoc_get_array_deep() {
for (int depth = 1; depth < MAX_SUBDOC_PATH_COMPONENTS + 1; depth++) {
too_long_path += "[0]";
}
- expect_subdoc_cmd(SubdocCmd(PROTOCOL_BINARY_CMD_SUBDOC_GET, "too_deep_array",
- too_long_path),
+ expect_subdoc_cmd(SubdocCmd(cmd, "too_deep_array", too_long_path),
PROTOCOL_BINARY_RESPONSE_SUBDOC_PATH_E2BIG, "");
delete_object("too_deep_array");
return TEST_PASS;
}
+
+enum test_return test_subdoc_get_array_deep() {
+ return test_subdoc_fetch_array_deep(PROTOCOL_BINARY_CMD_SUBDOC_GET);
+}
+enum test_return test_subdoc_exists_array_deep() {
+ return test_subdoc_fetch_array_deep(PROTOCOL_BINARY_CMD_SUBDOC_EXISTS);
+}
View
11 tests/testapp_subdoc.h
@@ -38,6 +38,17 @@ enum test_return test_subdoc_get_dict_nested_compressed();
enum test_return test_subdoc_get_dict_deep();
enum test_return test_subdoc_get_array_deep();
+enum test_return test_subdoc_exists_binary_raw();
+enum test_return test_subdoc_exists_binary_compressed();
+enum test_return test_subdoc_exists_array_simple_raw();
+enum test_return test_subdoc_exists_array_simple_compressed();
+enum test_return test_subdoc_exists_dict_simple_raw();
+enum test_return test_subdoc_exists_dict_simple_compressed();
+enum test_return test_subdoc_exists_dict_nested_raw();
+enum test_return test_subdoc_exists_dict_nested_compressed();
+enum test_return test_subdoc_exists_dict_deep();
+enum test_return test_subdoc_exists_array_deep();
+
#if defined(__cplusplus)
} // extern "C"
#endif
Please sign in to comment.
Something went wrong with that request. Please try again.