{"id":25776456,"url":"https://github.com/couchbase/CouchbaseMock","last_synced_at":"2025-02-27T06:06:29.976Z","repository":{"id":837616,"uuid":"2007376","full_name":"couchbase/CouchbaseMock","owner":"couchbase","description":"A Java mock for Couchbase","archived":false,"fork":false,"pushed_at":"2023-07-12T20:54:11.000Z","size":2240,"stargazers_count":63,"open_issues_count":30,"forks_count":42,"subscribers_count":23,"default_branch":"master","last_synced_at":"2024-01-19T03:21:45.178Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/couchbase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-07-06T16:00:22.000Z","updated_at":"2023-09-25T12:23:36.000Z","dependencies_parsed_at":"2022-08-16T11:05:21.888Z","dependency_job_id":null,"html_url":"https://github.com/couchbase/CouchbaseMock","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase%2FCouchbaseMock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase%2FCouchbaseMock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase%2FCouchbaseMock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase%2FCouchbaseMock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/couchbase","download_url":"https://codeload.github.com/couchbase/CouchbaseMock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240987435,"owners_count":19889334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-27T06:01:24.464Z","updated_at":"2025-02-27T06:06:29.969Z","avatar_url":"https://github.com/couchbase.png","language":"Java","funding_links":[],"categories":["测试"],"sub_categories":[],"readme":"# CouchbaseMock - The Couchbase Test Server\n\nCouchbaseMock is a test server implementing some of the memcached protocol\nwhich is used by some SDKs (including the C SDK) for basic testing. While it\nis recommended that testing be done against the real server, CouchbaseMock is\nuseful as being self-contained (there is no need to install it to the system)\nand for allowing extra instrumentation.\n\nCouchbaseMock is implemented in Java and is intended to be used by a single\nclient instance. Testing with any real kind of workload has not been done,\nand it is not intended to be high performance or reliable (it does not even\npersist data to the disk). As opposed to [cbgb](https://github.com/couchbaselabs/cbgb), this is\nnot intended to be a full implementation and/or replacement for the server.\n\nThe repository for CouchbaseMock may be found at\n[https://github.com/couchbase/couchbasemock](https://github.com/couchbase/couchbasemock).\nThis is a Maven project.\n\nCouchbaseMock requires Java 8 or later at runtime. Java 9 or later is required\nwhen building the project from source.\n\n## Basic Usage\n\nTypically, the mock is spawned by passing a `--port` argument as the REST port to\nlisten on, and a list of _bucket specifications_ separated by commas. Passing\n`--help` to the CouchbaseMock should show example usage. If no port is passed,\nit will listen on the REST port of 8091 (and will fail if you already have a\nCouchbase Server running).\n\nBy default, the mock will be up and running with the `default` bucket.\n\nOnce the mock has been started, it may be used like a normal Couchbase server,\nwith clients bootstrapping over HTTP using the port specified as `--port`.\n\n```sh\njava -jar CouchbaseMock-1.5.27.jar --port 9000\n```\n\nand then in another console:\n\n```sh\ncbc cat foo -U http://localhost:9000\n```\n\nIf you are using CouchbaseMock in automated testing, the test application\nshould open up a control port, pass that port to the mock using the\n`--harakiri-monitor` argument and set `--port` to 0. The randomly assigned\nHTTP port will be received on the control port once. See the\n_Out of Band Commands_ section below.\n\n## Supported Couchbase Operations\n\n### Memcached (Key-Value)\n\n* GET\n* GETQ\n* GAT\n* GATQ\n* TOUCH\n* SET\n* APPEND\n* PREPEND\n* REPLACE\n* ADD\n* REMOVE\n* INCR/DECR\n* GETL (From 0.6)\n* UNL (From 0.6)\n* OBSERVE (From 0.6)\n* GET\\_REPLICA (From 0.6)\n* STATS\n* VERSION\n* VERBOSITY\n\n### Administrative REST API\n\nThese standard REST API endpoints are supported. See the Couchbase Administration\nmanual for how to use these endpoints. These behave exactly as they would\nagainst a real Couchbase cluster.\n\nThe username and password are hard-coded into the mock as `Administrator` and\n`password` respectively.\n\n* `/pools` (GET)\n* `/pools/default` (GET)\n* `/pools/default/buckets` (GET, POST) - allows for bucket creation\n* `/pools/default/buckets/$bucket` (GET, DELETE) - allows for bucket deletion\n* `/pools/default/buckets/$bucket/ddocs` (GET) - allows for listing design documents\n* `/pools/default/bucketsStreaming/$bucket` (GET) - streaming config URI\n* `/sampleBuckets/install` (POST) - allows loading the `beer-sample` bucket.\n  Note that this endpoint seems to be undocumented.\n\nNote that only SASL-auth buckets may be created. This does not necessarily\nmean that your bucket must have a password. For example:\n\n    curl -XPOST -u Administrator:password \\\n        localhost:8091/pools/default/buckets \\\n        -d bucketType=couchbase \\\n        -d name=newbucket \\\n        -d authType=sasl \\\n        -d ramQuotaMB=200\n\nWill create a bucket without a password.\n\nAdditionally, note that the `ramQuotaMB` must be specified, though other than\nbeing necessary for conforming to server behavior, has no effect.\n\n### Views (Map-Reduce)\n\nThe following rest endpoints are supported. Note that the view query port\n(e.g. the _capi_ port) is the same as the administrative port. This should\nnot matter for conforming clients which determine this information from\nthe cluster configuration endpoint.\n\nBoth `map` and `reduce` functions are supported. Javascript support is provided\nusing Rhino, so view functions which depend on V8-specific functionality\nmay fail.\n\nThe `beer-sample` bucket is available in the mock and may be loaded by passing\nthe `-S` option on the commandline. It may also be loaded in-situ by using\nthe `/sampleBuckets/install` REST API, for example:\n\n    curl -u Administrator:password localhost:8091/sampleBuckets/install \\\n        -X POST \\\n        -H \"Content-Type: application/json\" \\\n        -d '[\"beer-sample\"]'\n\nAccessing views may be done by the following endpoints:\n\n* `/$bucket/_design/$ddoc` (PUT, GET, DELETE) - used to create or remove design\n  documents\n* `/$bucket/_design/$ddoc/_view/$view` - to query a view\n\nThe following view parameters are recognized and have effect\n\n* skip\n* limit\n* reduce\n* group\n* group\\_level\n* startkey\n* startkey\\_docid\n* endkey\n* endkey\\_docid\n* key\n* keys\n* inclusive\\_start (NOTE: not in Couchbase)\n* inclusive\\_end\n* descending\n* debug (returns dummy debug info)\n\nThe `full_set` and `stale` options are ignored.\n\n## Out-of-band Commands\n\nThe _Out-Of-Band (OOB or Control)_ commands are where \"special\" commands can be\nsent to the mock to do certain things which can simulate different conditions.\n\nOOBs are sent over the _Harakiri Port._ The _Harakiri Port_ is a _client_\\-side\nlistening port to which the mock will connect to once started up, and once the\nclient close the connection the mock server will perform a harakiri.\nThe normal \"handshake\" sequence is as follows:\n\nNote that this can be found in [_tests/server.c_](https://github.com/couchbase/libcouchbase/blob/master/tests/server.c) in the libcouchbase distribution\n\n1. The client sets up a listening address (typically on a random port\n-- i.e. passing 0 for `sin_port`).\n2. Call the usual functions, i.e. `socket()`, `bind()`, and `listen()`.\nThen call `getsockname()` to get the newly assigned port number\n3. Invoke the CouchbaseMock JAR passing the newly assigned listening port as the argument to the `--harakiri-monitor` option, so e.g. `--harakiri-monitor=localhost:42464`\n4. Additionally, pass `--port=0` to the JAR so that it will generate a random REST port (this way we don't have port conflicts)\n5. In the client, call _accept()_ on the harakiri port. The mock will connect to it.\n6. Read from the new connection until an ASCII NUL is encountered. The data read will be a C string containing the ASCII representation of the newly assigned REST port.\n7. Once the REST port has been received, you can use it in normal Couchbase/lcb\\_t operation to connect to the mock cluster.\n8. Send/Receive additional OOB commands on the new _harakiri_ connection established between client and mock\n\n## Command Format\n\nThe command format consists of JSON objects delimited by newlines.\nThe JSON object will consist of the following keys.\n\n* _command_: this is the name of the command\n* _payload:_ This is an object which contains the payload for the command\n\nThe response for the command will be delivered at its most basic level will\nbe a JSON object consisting of the following fields\n\n* _status_: This indicates the status of the command, it will be \"ok\" if the command was successful\n* _payload_: (optional) - if there is more than a status to deliver\n\n## HTTP API\n\nThis is a lightweight API following the semantics of the JSON API; only that\nit uses HTTP as the transport.\n\nThe format of each command is `http://localhost:18091/mock/\u003ccommand\u003e?payload\\_param1=payload\\_value1\u0026...`\n\nWhere \u003ccommand\u003e is the value for the JSON *command* field, and the query\nparameters are expanded (URL-Encoded) fields within the *payload*.\n\nNote that all requests (even those which modify data) use the _GET_ method;\nthis is to make it simple to test using a web browser.\n\n## Command Listings\n\nThe following commands are supported by the Mock.\nThe payload for each command should contain dictionary keys corresponding\nto the listed _Name_ of the parameter, and its value should conform to the\nspecified _Type_.\n\n### failover\n\n\nThis command fails over a specific server with a given index (the index is\nobtained from the REST configuration). It may also be passed a bucket for\nwhich the failover should affect (if no bucket is passed, it will be _default_).\nNames in *bold* are *required*\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eidx\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe server index\u003c/td\u003e\n        \u003ctd\u003eJSON Number\u003c/td\u003e\n    \u003c/tr\u003e\n        \u003ctr\u003e\u003ctd\u003ebucket\u003c/td\u003e\n        \u003ctd\u003eThe bucket to affect (`\"default\"`) if unspecified\u003c/td\u003e\n        \u003ctd\u003eJSON String\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n### respawn\n\nThis command does the opposite of _failover_. Call this with the same arguments\nas _failover_ to re-activate the node which was failed over.\n\n### hiccup\n\nSchedules an artificial delay after a _memcached_ server has sent a\nspecific amount of data. This is intended to simulate a scenario where a\nserver hangs or stalls after sending out a partial packet.\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003emsecs\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe duration of the delay in milliseconds\u003c/td\u003e\n        \u003ctd\u003eJSON Number\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eoffset\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eStall after this many bytes have been sent\u003c/td\u003e\n        \u003ctd\u003eJSON Number\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\nSetting both parameters to _0_ disables _hiccup_\n\n### truncate\n\nChops off data from the end of each packet. As a result it means invalid data\nwill be sent to the client (this may also be used in conjunction with failover\nto simulate a node sending partial data and then disconnecting)\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003elimit\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eLimit the next write operation to this many bytes\u003c/td\u003e\n        \u003ctd\u003eJSON Number\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\nSetting the _limit_ to _0_ disables _truncate_\n\n### OpFail\n\nCauses a number of memcached operations to unconditionally fail with a\nspecific error code. This may be used to simulate simple 'OOM' or\n`NOT_MY_VBUCKET` errors.\n\nParamters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003ecode\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe Memcached protocol code to force\u003c/td\u003e\n        \u003ctd\u003eJSON Number; Must also be recognized by the Mock\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003ecount\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe number of times this error code should be sent\n            before normal operation is restored. This can be either\n            a positive number (which indicates that this many operations\n            should fail before restoring to normal operation), 0 (which\n            means that normal behavior be restored immediately) or a\n            negative number, in which case commands will fail indefinitely\n            until a 0 is sent again with this command\u003c/td\u003e\n        \u003ctd\u003eJSON Number\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eservers\u003c/td\u003e\n        \u003ctd\u003eA list of servers to apply this setting to. Servers are specified\n        as indices into the server array. By default, all servers are used\u003c/td\u003e\n        \u003ctd\u003eJSON Number\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n### Time Travel\n\nThis command moves the internal clock in the server. The primary purpose\nfor this is to allow the clients to test TTL without having to \"sleep\".\nNames in *bold* are *required*\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eOffset\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe number of seconds to add to the internal clock\u003c/td\u003e\n        \u003ctd\u003eJSON Number\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\n### SET_CCCP\n\nThis command enables or disables *CCCP* protocol semantics for a group of\nservers.\n\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n       \u003cth\u003eName\u003c/th\u003e\n       \u003cth\u003eMeaning\u003c/th\u003e\n       \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eenabled\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eWhether to enable or disabled CCCP on the selection criteria\u003c/td\u003e\n        \u003ctd\u003eJSON Boolean\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ebucket\u003c/td\u003e\n        \u003ctd\u003eBucket for which CCCP should be enabled/disabled.\n        If this is empty, then this command affects all buckets\u003c/td\u003e\n        \u003ctd\u003eString\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eservers\u003c/td\u003e\n        \u003ctd\u003eAn array of server indices for which the enable/disable setting should\n        apply to. If this is not set, then all servers are modified\u003c/td\u003e\n        \u003ctd\u003eArray of numbers\u003c/td\u003e\n    \u003c/tr\u003e\n \u003c/table\u003e\n\n### SET_ENHANCED_ERRORS\n\nThis command enables or disables *Enhanced Error Messages* semantics for a group of\nservers. See [SDK-RFC-28](https://github.com/couchbaselabs/sdk-rfcs) for details.\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n       \u003cth\u003eName\u003c/th\u003e\n       \u003cth\u003eMeaning\u003c/th\u003e\n       \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eenabled\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eWhether to enable or disabled Enhanced Errors on the selection criteria\u003c/td\u003e\n        \u003ctd\u003eJSON Boolean\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ebucket\u003c/td\u003e\n        \u003ctd\u003eBucket for which Enhanced Errors should be enabled/disabled.\n        If this is empty, then this command affects all buckets\u003c/td\u003e\n        \u003ctd\u003eString\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eservers\u003c/td\u003e\n        \u003ctd\u003eAn array of server indices for which the enable/disable setting should\n        apply to. If this is not set, then all servers are modified\u003c/td\u003e\n        \u003ctd\u003eArray of numbers\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n### SET_COMPRESSION\n\nThis command sets compression mode for the group of servers. See [SDK-RFC-30](https://github.com/couchbaselabs/sdk-rfcs) for details.\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n       \u003cth\u003eName\u003c/th\u003e\n       \u003cth\u003eMeaning\u003c/th\u003e\n       \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003emode\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eOperating mode for the server: \u003ccode\u003e\"off\"\u003c/code\u003e, \u003ccode\u003e\"passive\"\u003c/code\u003e, \u003ccode\u003e\"active\"\u003c/code\u003e (see spec for details).\n        It also has extra mode \u003ccode\u003e\"disabled\"\u003c/code\u003e, which makes mock to behave like it does not know Snappy at all.\u003c/td\u003e\n        \u003ctd\u003eString\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ebucket\u003c/td\u003e\n        \u003ctd\u003eBucket for which Enhanced Errors should be enabled/disabled.\n        If this is empty, then this command affects all buckets\u003c/td\u003e\n        \u003ctd\u003eString\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eservers\u003c/td\u003e\n        \u003ctd\u003eAn array of server indices for which the enable/disable setting should\n        apply to. If this is not set, then all servers are modified\u003c/td\u003e\n        \u003ctd\u003eArray of numbers\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n### GET_MCPORTS\n\nThis is a more convenient way to get the memcached ports without parsing the\nentire vBucket config. This is particularly useful for `libcouchbase`' tests\nwhich at the time of writing don't have access to a simple HTTP implementation\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ebucket\u003c/td\u003e\n        \u003ctd\u003eWhich bucket to use. If unspecified, \u003ci\u003edefault\u003c/i\u003e is used\u003c/td\u003e\n        \u003ctd\u003estring\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\nThe response shall contain in the `payload` field a JSON array of integers\ncontaining port numbers (relative to the Mock's listening addresses) which may\nbe used as memcached ports.\n\n### keyinfo\n\nThis command returns the information about a given key in the mock\nserver. Names in *bold* are *required*\n\nParameters:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003ekey\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe key to access\u003c/td\u003e\n        \u003ctd\u003eJSON String\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eBucket\u003c/td\u003e\n        \u003ctd\u003eThe bucket in which the key resides\u003c/td\u003e\n        \u003ctd\u003eOptional. String. If not specified, \u003cpre\u003e\"default\"\u003c/pre\u003e is used\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\nThe payload contains a JSON object containing the per-node status\nof a given key. The base object is a JSON array (`[]`). Each element in\nthe array is a JSON object containing three fields.\n\nThe nodes are ordered according to the server list received in the vBucket\nconfiguration.\n\nIf the server is neither a replica nor a master for the given key, it is\npresent as `null`.\n\n* Conf:\n    Configuration information about this node in relation to the keys' vBucket.\n    This is a JSON object containing two subfields:\n\n    * Index - the server index in the vBucket map for the given vBucket. If this is\n    a master, the index will be `0`\n    * Type - Either `master` or `replica`\n\n* Cache:\n    This is a JSON object containing the status of the key as it resides in the\n    node's _Cache_. If the item is not present within the node's cache, the\n    object is empty; otherwise it contains these subfields:\n\n    * CAS The CAS value of the key as present within the storage domain\n    * Value the actual value of the key\n\n* Disk:\n    This carries the same semantics as `Cache`, only that it displays information\n    relating to the node's _Disk_ storage domain.\n\n\n## Key Access Commands\n\n### Concepts\n\nStarting with 0.6, the Mock introduces actual storage layers to emulate those of\nan actual cluster. Specifically, a cluster has one or more nodes, where each node\nretains a key in both its volatile memory (_Cache_) and persistent storage\n(_Disk_). While from a user perspective this process tends to be transparent, the\ndistinction makes itself known when operating on things such as views (where\nindices are built from \"persisted\" items only) and the various `OBSERVE` and/or\ndurability/persistence-requirement commands as well as get-from-replica.\n\nNote that _Cache_ and _Disk_ represent abstract concepts in the Mock. At the\ntime of writing, the Mock does not actually write anything to the disk, but\nmerely contains a separate storage domain for \"Disk\".\n\nThus, whenever an item is stored in the mock it may go through the following\nsteps:\n\n1. The item is inserted into the vBucket master's _Cache_\n2. The item is inserted into the vBucket master's _Disk_\n3. For each vBucket replica, the item is placed inside its _Cache_\n4. For each vBucket replica, the item is placed inside its _Disk_\n\n### Common Parameters\n\nThese out-of-band commands allow to modify or retrieve\ninformation on a specific _key_.\n\nThey all accept a set of common parameters\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eName\u003c/th\u003e\n        \u003cth\u003eMeaning\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eKey\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe key to access\u003c/td\u003e\n        \u003ctd\u003eJSON String\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eOnMaster\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eWhether to affect the key on the vBucket master\u003c/td\u003e\n        \u003ctd\u003eJSON Boolean\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eOnReplicas\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eWhich replicas should be affected\u003c/td\u003e\n        \u003ctd\u003eThis can either be a number indicating \u003ci\u003ehow many\u003c/i\u003e\n            replicas to affect; or it can be a list of specific replica indices\n            to affect\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eCAS\u003c/td\u003e\n        \u003ctd\u003eThe new CAS to use\u003c/td\u003e\n        \u003ctd\u003eOptional. Number. If not specified, the existing CAS (if the key\n            already exists) of each key entry in its respective storage partition\n            will be used. Otherwise, a new CAS is generated\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eValue\u003c/td\u003e\n        \u003ctd\u003eThe new value to use\u003c/td\u003e\n        \u003ctd\u003eOptional. String. If not specified the items value will be\n            an empty string\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eBucket\u003c/td\u003e\n        \u003ctd\u003eThe bucket in which the key resides\u003c/td\u003e\n        \u003ctd\u003eOptional. String. If not specified, \u003cpre\u003e\"default\"\u003c/pre\u003e is used\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\nBelow is a list of commands which accept these common parameters\n\n\n### Commands\n\n\n#### persist\n\nThis command will store an item to one or more nodes' _Disk_ storage domain.\nThe nodes affected depend on the `OnMaster` and `OnReplicas` parameters\n\n#### unpersist\n\nRemove an item from the _Disk_ storage domain from the selected nodes\n\n#### cache\n\nStore an item to one or more nodes' _Cache_\n\n#### uncache\n\nRemove an item from one or more nodes' _Cache_\n\n#### endure\n\nFor each affected node, store the item to its _Disk_ *and* _Cache_ stores.\nThis is equivalent to calling `persist` and `cache` on the same item\n\n#### purge\n\nFor each affected node, remove the item from both its _Disk_ and _Cache_\nstores. This is equivalent to calling `uncache` and `unpersist` on the same\nitem\n\n## Retry Verification Commands\n\nThe mock can verify whether a client library is properly retrying commands.\nTo use this feature, your client must have the `XERROR` feature enabled and\nimplemented.\n\nThe usage overview is this:\n\n1. Setup retry verification recording before running your test\n2. Instruct the mock to inject failures (using the `OPFAIL` command), which\n   will trigger the retry. Note that you can inject failures using other means\n   as well (e.g. internally at the client level)\n3. Execute your operations with failure injection enabled (per step 2)\n4. Once the operations are done, request the mock to verify behavior. This will\n   also implicitly undo whatever setup was done in step 1.\n\nYou can set up retry verification using the `START_RETRY_VERIFY` command. This command requires the server index and the bucket name to use for verification.\n\nBecause the precise server index must be known, you will need to determine the vBucket\nfor the key that will be used in the commands.\n\n```python\n# Pseudo code\ntest_key = \"HelloWorld\"\nvbucket = vbucket_map(test_key)\nserver = server_map(vbucket)\n```\n\nIn order to trigger the correct error retry behavior, you will need to use special error return codes which are further defined in the Mock itself. If the client is\nproperly implemented and functioning correctly, it should not have explicit\nknowledge of these error codes - but should be handled dynamically by using the\ncorresponding entry in the error map.\n\nThe error codes are:\n\n* `0x7ff0` - defines a *constant* retry strategy\n* `0x7ff1` - defines a *linear* retry strategy\n* `0x7ff2` - defines an *exponential* retry strategy.\n\nYou should test with all three error codes to verify that the client can correctly\nhandle all three strategies.\n\nThen set up the `OPFAIL` command to be directed towards the correct server:\n\n```python\ncmd = {\n    'command': 'OPFAIL',\n    'payload': {\n        'servers': [server],\n        'bucket': 'default',\n        'count': 100,\n        'code': 0x7ff1\n    }\n}\n```\n\nAnd then set up the `START_RETRY_VERIFY` command.\n\n```python\ncmd = {\n    'command': 'START_RETRY_VERIFY',\n    'payload': {\n        'idx': server,  # Numeric index of server\n        'bucket': 'default'\n    }\n}\n```\n\nNote that `START_RETRY_VERIFY` only tells the server to start recording command logs.\n\nOnce the `OPFAIL` is sent, any command directed to the specified servers will cause\nthe server to return the error code specified. For the purposes of testing, a simple\n`GET` (`0x00`) command should suffice to trigger the error behavior.\n\nThe command should eventually fail on the client side - after multiple internal retries by the client.\n\nOnce the client has failed the command, you should query the mock to determine if\nthe client had behaved as expected. This is done using the `CHECK_RETRY_VERIFY` command.\n\nThe `CHECK_RETRY_VERIFY` command requires the server index (from above), the error, and the opcode of the test operation. If verification succeeded, the command will\nreturn success, and if it failed, it will return an error with some additional\ninformation.\n\nThe format of `CHECK_RETRY_VERIFY` is:\n\n```python\n'command': {\n    'payload': {\n        'idx': server,\n        'bucket': 'default',\n        'errcode': 0x7ff1,\n        'opcode': 0x00\n    }\n}\n```\n\nThe mock uses three basic tests to determine if the retries were done according\nto spec.\n\n1. The first retry should be within `after` (+/- fuzz) ms of the first\n   error response.\n2. The spacing between each interval should be as prescribed (strategy dependent)\n3. The *last* retry should not exceed past (+/- fuzz) ms of the\n   `max-duration` interval from the receipt of the first error.\n\nThe \"fuzz\" is defined as 10ms. Fuzz is required because not all operating\nenvironments (virtual machines, interpreters, clocks, etc.) can guarantee\naccuracy/resolution within 1 ms.\n\n\nIn the following example, conformance to the `constant` strategy is\nverified. We will assume that the clock begins at 0 ms\n\n\nHere is the spec:\n\n```\n{\n    \"strategy\": \"constant\",\n    \"max-duration\": 500,\n    \"interval\": 10,\n    \"after\": 50\n}\n```\n\n* 0ms: Client receives error response\n* 53ms: After waiting ~50ms, the client sends the first retry. This should\n  be within fuzz+`after` of first error response.\n* 60ms: After waiting ~10ms, the client sends the next retry.\n  This should be within fuzz+`interval` of the previous retry attempt.\n* 69ms: Retry\n* 75ms: Retry\n....\n* 484ms: Client sends retry...\n* 497ms: Client sends last retry. Should be within interval+fuzz of\n  +500ms (Time since first error response)\n\n\nVerifying this with linear or exponential retries is similar. Here's an example\nfor linear retry:\n\n```\n{\n    \"strategy\": \"linear\",\n    \"max-duration\": 500,\n    \"interval\": 10,\n    \"after\": 50,\n    \"ceil\": 200\n}\n```\n\n* 0ms: Client receives error response\n* 55ms: Client sends first retry\n* 62ms: Client sends next retry (interval is 10ms)\n* 87ms: Client sends next retry (interval is now 20ms)\n* 109ms: Client sends next retry (interval is now 30ms)\n* 142ms: Client sends next retry (interval is now 40ms)\n* 195ms: Client sends next retry (interval is now 50ms)\n* 256ms: Client sends next retry (interval is now 60ms)\n...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcouchbase%2FCouchbaseMock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcouchbase%2FCouchbaseMock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcouchbase%2FCouchbaseMock/lists"}