Commit ab5246d8 authored by Jeremy Mikola's avatar Jeremy Mikola

PHPLIB-307: Retryable writes test runner

Spec tests synced with mongodb/specifications@83a0e6b56bfd73b471c1b740190dbbb7c52ffa92
parent d444ddea
<?php
namespace MongoDB\Tests\SpecTests;
use MongoDB\BulkWriteResult;
use MongoDB\Client;
use MongoDB\Collection;
use MongoDB\Database;
use MongoDB\DeleteResult;
use MongoDB\InsertManyResult;
use MongoDB\InsertOneResult;
use MongoDB\UpdateResult;
use MongoDB\Driver\Server;
use MongoDB\Driver\WriteResult;
use MongoDB\Driver\Exception\BulkWriteException;
use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Operation\FindOneAndReplace;
use MongoDB\Tests\FunctionalTestCase as BaseFunctionalTestCase;
use PHPUnit\Framework\SkippedTest;
use ArrayIterator;
use IteratorIterator;
use LogicException;
use MultipleIterator;
use UnexpectedValueException;
/**
* Base class for spec test runners.
*
* @see https://github.com/mongodb/specifications
*/
abstract class FunctionalTestCase extends BaseFunctionalTestCase
{
const TOPOLOGY_SINGLE = 'single';
const TOPOLOGY_REPLICASET = 'replicaset';
const TOPOLOGY_SHARDED = 'sharded';
private $client;
private $collection;
private $configuredFailPoints = [];
private $outcomeCollection;
public function setUp()
{
parent::setUp();
$this->configuredFailPoints = [];
}
public function tearDown()
{
$this->disableFailPoints();
parent::tearDown();
}
/**
* Assert an operation's outcome.
*
* @param array $operation
* @param array $outcome
*/
protected function assertOperation(array $operation, array $outcome)
{
$result = null;
$exception = null;
$expectedError = array_key_exists('error', $outcome) ? $outcome['error'] : false;
try {
$result = $this->executeOperation($operation);
$this->assertFalse($expectedError);
} catch (RuntimeException $e) {
$exception = $e;
$this->assertTrue($expectedError);
}
// Extract incomplete result for failed bulkWrite and insertMany ops
if ($exception instanceof BulkWriteException) {
$result = $exception->getWriteResult();
}
// TODO: Remove this once ext-mongodb is bumped to 1.6.0 (see: PHPC-1373)
if ($expectedError && !($exception instanceof BulkWriteException) &&
in_array($operation['name'], ['bulkWrite', 'insertMany']) &&
array_key_exists('result', $outcome)) {
$this->markTestSkipped('WriteResult is inaccessible for bulk write error');
}
if (array_key_exists('result', $outcome)) {
$this->assertOperationResult($operation, $outcome['result'], $result);
}
}
/**
* Asserts the result of an operation.
*
* @param array $operation
* @param mixed $expectedResult
* @param mixed $actualResult
* @throws LogicException if the operation is unsupported
*/
protected function assertOperationResult(array $operation, $expectedResult, $actualResult)
{
switch ($operation['name']) {
case 'aggregate':
/* Returning a cursor for the $out collection is optional per
* the CRUD specification and is not implemented in the library
* since we have no concept of lazy cursors. We will not assert
* the result here; however, assertOutcomeCollectionData() will
* assert the output collection's contents later.
*/
if ( ! \MongoDB\is_last_pipeline_operator_out($operation['arguments']['pipeline'])) {
$this->assertSameDocuments($expectedResult, $actualResult);
}
break;
case 'bulkWrite':
$this->assertInternalType('array', $expectedResult);
$this->assertThat($actualResult, $this->logicalOr(
$this->isInstanceOf(BulkWriteResult::class),
$this->isInstanceOf(WriteResult::class)
));
if (isset($expectedResult['deletedCount'])) {
$this->assertSame($expectedResult['deletedCount'], $actualResult->getDeletedCount());
}
if (isset($expectedResult['insertedCount'])) {
$this->assertSame($expectedResult['insertedCount'], $actualResult->getInsertedCount());
}
// insertedIds are not available after BulkWriteException (see: PHPLIB-428)
if (isset($expectedResult['insertedIds']) && $actualResult instanceof BulkWriteResult) {
$this->assertSameDocument(
['insertedIds' => $expectedResult['insertedIds']],
['insertedIds' => $actualResult->getInsertedIds()]
);
}
if (isset($expectedResult['matchedCount'])) {
$this->assertSame($expectedResult['matchedCount'], $actualResult->getMatchedCount());
}
if (isset($expectedResult['modifiedCount'])) {
$this->assertSame($expectedResult['modifiedCount'], $actualResult->getModifiedCount());
}
if (isset($expectedResult['upsertedCount'])) {
$this->assertSame($expectedResult['upsertedCount'], $actualResult->getUpsertedCount());
}
if (isset($expectedResult['upsertedIds'])) {
$this->assertSameDocument(
['upsertedIds' => $expectedResult['upsertedIds']],
['upsertedIds' => $actualResult->getUpsertedIds()]
);
}
break;
case 'count':
case 'countDocuments':
case 'estimatedDocumentCount':
$this->assertSame($expectedResult, $actualResult);
break;
case 'distinct':
$this->assertSameDocument(
['values' => $expectedResult],
['values' => $actualResult]
);
break;
case 'find':
$this->assertSameDocuments($expectedResult, $actualResult);
break;
case 'deleteMany':
case 'deleteOne':
$this->assertInternalType('array', $expectedResult);
$this->assertInstanceOf(DeleteResult::class, $actualResult);
if (isset($expectedResult['deletedCount'])) {
$this->assertSame($expectedResult['deletedCount'], $actualResult->getDeletedCount());
}
break;
case 'findOneAndDelete':
case 'findOneAndReplace':
case 'findOneAndUpdate':
$this->assertSameDocument(
['result' => $expectedResult],
['result' => $actualResult]
);
break;
case 'insertMany':
$this->assertInternalType('array', $expectedResult);
$this->assertThat($actualResult, $this->logicalOr(
$this->isInstanceOf(InsertManyResult::class),
$this->isInstanceOf(WriteResult::class)
));
if (isset($expectedResult['insertedCount'])) {
$this->assertSame($expectedResult['insertedCount'], $actualResult->getInsertedCount());
}
// insertedIds are not available after BulkWriteException (see: PHPLIB-428)
if (isset($expectedResult['insertedIds']) && $actualResult instanceof BulkWriteResult) {
$this->assertSameDocument(
['insertedIds' => $expectedResult['insertedIds']],
['insertedIds' => $actualResult->getInsertedIds()]
);
}
break;
case 'insertOne':
$this->assertInternalType('array', $expectedResult);
$this->assertInstanceOf(InsertOneResult::class, $actualResult);
if (isset($expectedResult['insertedCount'])) {
$this->assertSame($expectedResult['insertedCount'], $actualResult->getInsertedCount());
}
if (isset($expectedResult['insertedId'])) {
$this->assertSameDocument(
['insertedId' => $expectedResult['insertedId']],
['insertedId' => $actualResult->getInsertedId()]
);
}
break;
case 'replaceOne':
case 'updateMany':
case 'updateOne':
$this->assertInternalType('array', $expectedResult);
$this->assertInstanceOf(UpdateResult::class, $actualResult);
if (isset($expectedResult['matchedCount'])) {
$this->assertSame($expectedResult['matchedCount'], $actualResult->getMatchedCount());
}
if (isset($expectedResult['modifiedCount'])) {
$this->assertSame($expectedResult['modifiedCount'], $actualResult->getModifiedCount());
}
if (isset($expectedResult['upsertedCount'])) {
$this->assertSame($expectedResult['upsertedCount'], $actualResult->getUpsertedCount());
}
if (array_key_exists('upsertedId', $expectedResult)) {
$this->assertSameDocument(
['upsertedId' => $expectedResult['upsertedId']],
['upsertedId' => $actualResult->getUpsertedId()]
);
}
break;
default:
throw new LogicException('Unsupported operation: ' . $operation['name']);
}
}
/**
* Assert data within the outcome collection.
*
* @param array $expectedDocuments
*/
protected function assertOutcomeCollectionData(array $expectedDocuments)
{
$mi = new MultipleIterator(MultipleIterator::MIT_NEED_ANY);
$mi->attachIterator(new ArrayIterator($expectedDocuments));
$mi->attachIterator(new IteratorIterator($this->outcomeCollection->find()));
foreach ($mi as $documents) {
list($expectedDocument, $actualDocument) = $documents;
$this->assertSameDocument($expectedDocument, $actualDocument);
}
}
/**
* Checks server version and topology requirements.
*
* @param array $runOn
* @throws SkippedTest if the server requirements are not met
*/
protected function checkServerRequirements(array $runOn)
{
foreach ($runOn as $req) {
$minServerVersion = isset($req['minServerVersion']) ? $req['minServerVersion'] : null;
$maxServerVersion = isset($req['maxServerVersion']) ? $req['maxServerVersion'] : null;
$topologies = isset($req['topology']) ? $req['topology'] : null;
if ($this->isServerRequirementSatisifed($minServerVersion, $maxServerVersion, $topologies)) {
return;
}
}
$serverVersion = $this->getServerVersion();
$topology = $this->getTopology();
$this->markTestSkipped(sprintf('Server version "%s" and topology "%s" do not meet test requirements: %s', $serverVersion, $topology, json_encode($runOn)));
}
/**
* Configure a fail point for the test.
*
* The fail point will automatically be disabled during tearDown() to avoid
* affecting a subsequent test.
*
* @param array $failPointCommand
*/
protected function configureFailPoint(array $failPointCommand)
{
$database = new Database($this->manager, 'admin');
$cursor = $database->command($failPointCommand);
$result = $cursor->toArray()[0];
$this->assertCommandSucceeded($result);
// Record the fail point so it can be disabled during tearDown()
$this->configuredFailPoints[] = $failPointCommand['configureFailPoint'];
}
/**
* Initialize data fixtures in test subject.
*
* @param array $documents
*/
protected function initDataFixtures(array $documents)
{
if (empty($documents)) {
return;
}
$this->collection->insertMany($documents);
}
/**
* Initialize outcome collection.
*
* @param array $test
*/
protected function initOutcomeCollection(array $test)
{
$outcomeCollectionName = isset($test['outcome']['collection']['name'])
? $test['outcome']['collection']['name']
: $this->collection->getCollectionName();
// Outcome collection need not use client under test
$this->outcomeCollection = new Collection($this->manager, $this->getDatabaseName(), $outcomeCollectionName);
// Avoid a redundant drop if the test subject and outcome are the same
if ($this->collection->getNamespace() !== $this->outcomeCollection->getNamespace()) {
$this->outcomeCollection->drop();
}
}
/**
* Initialize client and collection objects.
*
* @param array $test
* @throws LogicException if an option is unsupported
*/
protected function initTestSubjects(array $test)
{
if (isset($test['useMultipleMongoses']) && $this->isShardedCluster()) {
throw new LogicException('"useMultipleMongoses" is not supported');
}
$clientOptions = isset($test['clientOptions']) ? $test['clientOptions'] : [];
$this->client = new Client($this->getUri(), $clientOptions);
$this->collection = $this->client->selectCollection($this->getDatabaseName(), $this->getCollectionName());
$this->collection->drop();
}
/**
* Disables any fail points that were configured earlier in the test.
*
* This tracks fail points set via configureFailPoint() and should be called
* during tearDown().
*/
private function disableFailPoints()
{
$database = new Database($this->manager, 'admin');
foreach ($this->configuredFailPoints as $failPoint) {
$database->command(['configureFailPoint' => $failPoint, 'mode' => 'off']);
}
}
/**
* Executes an "operation" block.
*
* @param array $operation
* @return mixed
* @throws LogicException if the operation is unsupported
*/
private function executeOperation(array $operation)
{
switch ($operation['name']) {
case 'aggregate':
return $this->collection->aggregate(
$operation['arguments']['pipeline'],
array_diff_key($operation['arguments'], ['pipeline' => 1])
);
case 'bulkWrite':
return $this->collection->bulkWrite(
array_map([$this, 'prepareBulkWriteRequest'], $operation['arguments']['requests']),
isset($operation['arguments']['options']) ? $operation['arguments']['options'] : []
);
case 'count':
case 'countDocuments':
case 'find':
return $this->collection->{$operation['name']}(
isset($operation['arguments']['filter']) ? $operation['arguments']['filter'] : [],
array_diff_key($operation['arguments'], ['filter' => 1])
);
case 'estimatedDocumentCount':
return $this->collection->estimatedDocumentCount($operation['arguments']);
case 'deleteMany':
case 'deleteOne':
case 'findOneAndDelete':
return $this->collection->{$operation['name']}(
$operation['arguments']['filter'],
array_diff_key($operation['arguments'], ['filter' => 1])
);
case 'distinct':
return $this->collection->distinct(
$operation['arguments']['fieldName'],
isset($operation['arguments']['filter']) ? $operation['arguments']['filter'] : [],
array_diff_key($operation['arguments'], ['fieldName' => 1, 'filter' => 1])
);
case 'findOneAndReplace':
$operation['arguments'] = $this->prepareFindAndModifyArguments($operation['arguments']);
// Fall through
case 'replaceOne':
return $this->collection->{$operation['name']}(
$operation['arguments']['filter'],
$operation['arguments']['replacement'],
array_diff_key($operation['arguments'], ['filter' => 1, 'replacement' => 1])
);
case 'findOneAndUpdate':
$operation['arguments'] = $this->prepareFindAndModifyArguments($operation['arguments']);
// Fall through
case 'updateMany':
case 'updateOne':
return $this->collection->{$operation['name']}(
$operation['arguments']['filter'],
$operation['arguments']['update'],
array_diff_key($operation['arguments'], ['filter' => 1, 'update' => 1])
);
case 'insertMany':
return $this->collection->insertMany(
$operation['arguments']['documents'],
isset($operation['arguments']['options']) ? $operation['arguments']['options'] : []
);
case 'insertOne':
return $this->collection->insertOne(
$operation['arguments']['document'],
array_diff_key($operation['arguments'], ['document' => 1])
);
default:
throw new LogicException('Unsupported operation: ' . $operation['name']);
}
}
/**
* Return the corresponding topology constants for the current topology.
*
* @return string
* @throws UnexpectedValueException if topology is neither single nor RS nor sharded
*/
private function getTopology()
{
$topologyTypeMap = [
Server::TYPE_STANDALONE => self::TOPOLOGY_SINGLE,
Server::TYPE_RS_PRIMARY => self::TOPOLOGY_REPLICASET,
Server::TYPE_MONGOS => self::TOPOLOGY_SHARDED,
];
$primaryType = $this->getPrimaryServer()->getType();
if (isset($topologyTypeMap[$primaryType])) {
return $topologyTypeMap[$primaryType];
}
throw new UnexpectedValueException('Toplogy is neither single nor RS nor sharded');
}
/**
* Checks if server version and topology requirements are satifised.
*
* @param string|null $minServerVersion
* @param string|null $maxServerVersion
* @param array|null $topologies
* @return boolean
*/
private function isServerRequirementSatisifed($minServerVersion, $maxServerVersion, array $topologies = null)
{
$serverVersion = $this->getServerVersion();
if (isset($minServerVersion) && version_compare($serverVersion, $minServerVersion, '<')) {
return false;
}
if (isset($maxServerVersion) && version_compare($serverVersion, $maxServerVersion, '>')) {
return false;
}
$topology = $this->getTopology();
if (isset($topologies) && ! in_array($topology, $topologies)) {
return false;
}
return true;
}
/**
* Prepares a request element for a bulkWrite operation.
*
* @param array $request
* @return array
*/
private function prepareBulkWriteRequest(array $request)
{
switch ($request['name']) {
case 'deleteMany':
case 'deleteOne':
return [ $request['name'] => [
$request['arguments']['filter'],
array_diff_key($request['arguments'], ['filter' => 1]),
]];
case 'insertOne':
return [ 'insertOne' => [ $request['arguments']['document'] ]];
case 'replaceOne':
return [ 'replaceOne' => [
$request['arguments']['filter'],
$request['arguments']['replacement'],
array_diff_key($request['arguments'], ['filter' => 1, 'replacement' => 1]),
]];
case 'updateMany':
case 'updateOne':
return [ $request['name'] => [
$request['arguments']['filter'],
$request['arguments']['update'],
array_diff_key($request['arguments'], ['filter' => 1, 'update' => 1]),
]];
default:
throw new LogicException('Unsupported bulk write request: ' . $request['name']);
}
}
/**
* Prepares arguments for findOneAndReplace and findOneAndUpdate operations.
*
* @param array $arguments
* @return array
*/
private function prepareFindAndModifyArguments(array $arguments)
{
if (isset($arguments['returnDocument'])) {
$arguments['returnDocument'] = ('after' === strtolower($arguments['returnDocument']))
? FindOneAndReplace::RETURN_DOCUMENT_AFTER
: FindOneAndReplace::RETURN_DOCUMENT_BEFORE;
}
return $arguments;
}
}
<?php
namespace MongoDB\Tests\SpecTests;
/**
* Retryable writes spec tests.
*
* @see https://github.com/mongodb/specifications/tree/master/source/retryable-writes
*/
class RetryableWritesSpecTest extends FunctionalTestCase
{
/**
* Execute an individual test case from the specification.
*
* @dataProvider provideTests
* @param string $name Test name
* @param array $test Individual "tests[]" document
* @param array $runOn Top-level "runOn" document
* @param array $data Top-level "data" array to initialize collection
*/
public function testRetryableWrites($name, array $test, array $runOn = null, array $data)
{
$this->setName($name);
if (isset($runOn)) {
$this->checkServerRequirements($runOn);
}
// TODO: Remove this once retryWrites=true by default (see: PHPC-1324)
$test['clientOptions']['retryWrites'] = true;
$this->initTestSubjects($test);
$this->initOutcomeCollection($test);
$this->initDataFixtures($data);
if (isset($test['failPoint'])) {
$this->configureFailPoint($test['failPoint']);
}
$this->assertOperation($test['operation'], $test['outcome']);
if (isset($test['outcome']['collection']['data'])) {
$this->assertOutcomeCollectionData($test['outcome']['collection']['data']);
}
}
public function provideTests()
{
$testArgs = [];
foreach (glob(__DIR__ . '/retryable-writes/*.json') as $filename) {
$json = json_decode(file_get_contents($filename), true);
$group = basename($filename, '.json');
$runOn = isset($json['runOn']) ? $json['runOn'] : null;
$data = isset($json['data']) ? $json['data'] : [];
foreach ($json['tests'] as $test) {
$name = $group . ': ' . $test['description'];
$testArgs[] = [$name, $test, $runOn, $data];
}
}
return $testArgs;
}
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "BulkWrite succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"update"
],
"errorCode": 189
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 1,
"insertedCount": 1,
"insertedIds": {
"1": 3
},
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 2,
"x": 23
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "BulkWrite succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 1,
"insertedCount": 1,
"insertedIds": {
"1": 3
},
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 2,
"x": 23
},
{
"_id": 3,
"x": 33
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
}
],
"tests": [
{
"description": "First command is retried",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 1,
"insertedCount": 1,
"insertedIds": {
"0": 2
},
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 2,
"x": 23
}
]
}
}
},
{
"description": "All commands are retried",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 7
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 4,
"x": 44
},
"update": {
"$inc": {
"x": 1
}
},
"upsert": true
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 5,
"x": 55
}
}
},
{
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 3
},
"replacement": {
"_id": 3,
"x": 333
}
}
},
{
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 1,
"insertedCount": 3,
"insertedIds": {
"0": 2,
"2": 3,
"4": 5
},
"matchedCount": 2,
"modifiedCount": 2,
"upsertedCount": 1,
"upsertedIds": {
"3": 4
}
},
"collection": {
"data": [
{
"_id": 2,
"x": 23
},
{
"_id": 3,
"x": 333
},
{
"_id": 4,
"x": 45
},
{
"_id": 5,
"x": 55
}
]
}
}
},
{
"description": "Both commands are retried after their first statement fails",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 0,
"insertedCount": 1,
"insertedIds": {
"0": 2
},
"matchedCount": 2,
"modifiedCount": 2,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 23
}
]
}
}
},
{
"description": "Second command is retried after its second statement fails",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"skip": 2
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 0,
"insertedCount": 1,
"insertedIds": {
"0": 2
},
"matchedCount": 2,
"modifiedCount": 2,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 23
}
]
}
}
},
{
"description": "BulkWrite with unordered execution",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
}
],
"options": {
"ordered": false
}
}
},
"outcome": {
"result": {
"deletedCount": 0,
"insertedCount": 2,
"insertedIds": {
"0": 2,
"1": 3
},
"matchedCount": 0,
"modifiedCount": 0,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "First insertOne is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"error": true,
"result": {
"deletedCount": 0,
"insertedCount": 0,
"insertedIds": {},
"matchedCount": 0,
"modifiedCount": 0,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
}
]
}
}
},
{
"description": "Second updateOne is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"skip": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"error": true,
"result": {
"deletedCount": 0,
"insertedCount": 1,
"insertedIds": {
"0": 2
},
"matchedCount": 0,
"modifiedCount": 0,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "Third updateOne is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"skip": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
},
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 2
},
"update": {
"$inc": {
"x": 1
}
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"error": true,
"result": {
"deletedCount": 0,
"insertedCount": 1,
"insertedIds": {
"1": 2
},
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "Single-document write following deleteMany is retried",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "deleteMany",
"arguments": {
"filter": {
"x": 11
}
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 1,
"insertedCount": 1,
"insertedIds": {
"1": 2
},
"matchedCount": 0,
"modifiedCount": 0,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "Single-document write following updateMany is retried",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "updateMany",
"arguments": {
"filter": {
"x": 11
},
"update": {
"$inc": {
"x": 1
}
}
}
},
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 2,
"x": 22
}
}
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"deletedCount": 0,
"insertedCount": 1,
"insertedIds": {
"1": 2
},
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0,
"upsertedIds": {}
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset",
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "DeleteMany ignores retryWrites",
"useMultipleMongoses": true,
"operation": {
"name": "deleteMany",
"arguments": {
"filter": {}
}
},
"outcome": {
"result": {
"deletedCount": 2
},
"collection": {
"data": []
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "DeleteOne succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"delete"
],
"errorCode": 189
}
},
"operation": {
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
},
"outcome": {
"result": {
"deletedCount": 1
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "DeleteOne succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"delete"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
},
"outcome": {
"result": {
"deletedCount": 1
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "DeleteOne is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
},
"outcome": {
"result": {
"deletedCount": 1
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "DeleteOne is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
},
"outcome": {
"result": {
"deletedCount": 1
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "DeleteOne is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "deleteOne",
"arguments": {
"filter": {
"_id": 1
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "FindOneAndDelete succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"findAndModify"
],
"errorCode": 189
}
},
"operation": {
"name": "findOneAndDelete",
"arguments": {
"filter": {
"x": {
"$gte": 11
}
},
"sort": {
"x": 1
}
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndDelete succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"findAndModify"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "findOneAndDelete",
"arguments": {
"filter": {
"x": {
"$gte": 11
}
},
"sort": {
"x": 1
}
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "FindOneAndDelete is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "findOneAndDelete",
"arguments": {
"filter": {
"x": {
"$gte": 11
}
},
"sort": {
"x": 1
}
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndDelete is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "findOneAndDelete",
"arguments": {
"filter": {
"x": {
"$gte": 11
}
},
"sort": {
"x": 1
}
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndDelete is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "findOneAndDelete",
"arguments": {
"filter": {
"x": {
"$gte": 11
}
},
"sort": {
"x": 1
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "FindOneAndReplace succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"findAndModify"
],
"errorCode": 189
}
},
"operation": {
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndReplace succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"findAndModify"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "FindOneAndReplace is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndReplace is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndReplace is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "findOneAndReplace",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
},
"returnDocument": "Before"
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "FindOneAndUpdate succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"findAndModify"
],
"errorCode": 189
}
},
"operation": {
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndUpdate succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"findAndModify"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "FindOneAndUpdate is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndUpdate is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
},
"returnDocument": "Before"
}
},
"outcome": {
"result": {
"_id": 1,
"x": 11
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "FindOneAndUpdate is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "findOneAndUpdate",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
}
],
"tests": [
{
"description": "InsertMany succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 189
}
},
"operation": {
"name": "insertMany",
"arguments": {
"documents": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"insertedIds": {
"0": 2,
"1": 3
}
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertMany succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "insertMany",
"arguments": {
"documents": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"insertedIds": {
"0": 2,
"1": 3
}
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
}
],
"tests": [
{
"description": "InsertMany succeeds after one network error",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "insertMany",
"arguments": {
"documents": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"result": {
"insertedIds": {
"0": 2,
"1": 3
}
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertMany with unordered execution",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "insertMany",
"arguments": {
"documents": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"options": {
"ordered": false
}
}
},
"outcome": {
"result": {
"insertedIds": {
"0": 2,
"1": 3
}
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertMany fails after multiple network errors",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": "alwaysOn",
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "insertMany",
"arguments": {
"documents": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
},
{
"_id": 4,
"x": 44
}
],
"options": {
"ordered": true
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "InsertOne succeeds after connection failure",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"closeConnection": true
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after NotMaster",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 10107,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after NotMasterOrSecondary",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 13436,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after NotMasterNoSlaveOk",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 13435,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after InterruptedDueToStepDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 11602,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after InterruptedAtShutdown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 11600,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 189,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 91,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after HostNotFound",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 7,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after HostUnreachable",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 6,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after SocketException",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 9001,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after NetworkTimeout",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 89,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne fails after Interrupted",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"errorCode": 11601,
"closeConnection": false
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "InsertOne succeeds after WriteConcernError InterruptedAtShutdown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 11600,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after WriteConcernError InterruptedDueToStepDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 11602,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after WriteConcernError PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 189,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne fails after multiple retryable writeConcernErrors",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 2
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne fails after WriteConcernError Interrupted",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 11601,
"errmsg": "operation was interrupted"
}
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne fails after WriteConcernError WriteConcernFailed",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"insert"
],
"writeConcernError": {
"code": 64,
"codeName": "WriteConcernFailed",
"errmsg": "waiting for replication timed out",
"errInfo": {
"wtimeout": true
}
}
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "InsertOne is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"result": {
"insertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "InsertOne is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "insertOne",
"arguments": {
"document": {
"_id": 3,
"x": 33
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "ReplaceOne succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"update"
],
"errorCode": 189
}
},
"operation": {
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "ReplaceOne succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"update"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "ReplaceOne is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "ReplaceOne is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 111
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "ReplaceOne is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"_id": 1,
"x": 111
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset",
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "UpdateMany ignores retryWrites",
"useMultipleMongoses": true,
"operation": {
"name": "updateMany",
"arguments": {
"filter": {},
"update": {
"$inc": {
"x": 1
}
}
}
},
"outcome": {
"result": {
"matchedCount": 2,
"modifiedCount": 2,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 23
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "4.0",
"topology": [
"replicaset"
]
},
{
"minServerVersion": "4.1.7",
"topology": [
"sharded"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "UpdateOne succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"update"
],
"errorCode": 189
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "UpdateOne succeeds after WriteConcernError ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"update"
],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
{
"runOn": [
{
"minServerVersion": "3.6",
"topology": [
"replicaset"
]
}
],
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
],
"tests": [
{
"description": "UpdateOne is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "UpdateOne is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
"outcome": {
"result": {
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
},
"collection": {
"data": [
{
"_id": 1,
"x": 12
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "UpdateOne is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"$inc": {
"x": 1
}
}
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
},
{
"description": "UpdateOne with upsert is committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 3,
"x": 33
},
"update": {
"$inc": {
"x": 1
}
},
"upsert": true
}
},
"outcome": {
"result": {
"matchedCount": 0,
"modifiedCount": 0,
"upsertedCount": 1,
"upsertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 34
}
]
}
}
},
{
"description": "UpdateOne with upsert is not committed on first attempt",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 1
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 3,
"x": 33
},
"update": {
"$inc": {
"x": 1
}
},
"upsert": true
}
},
"outcome": {
"result": {
"matchedCount": 0,
"modifiedCount": 0,
"upsertedCount": 1,
"upsertedId": 3
},
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 34
}
]
}
}
},
{
"description": "UpdateOne with upsert is never committed",
"failPoint": {
"configureFailPoint": "onPrimaryTransactionalWrite",
"mode": {
"times": 2
},
"data": {
"failBeforeCommitExceptionCode": 1
}
},
"operation": {
"name": "updateOne",
"arguments": {
"filter": {
"_id": 3,
"x": 33
},
"update": {
"$inc": {
"x": 1
}
},
"upsert": true
}
},
"outcome": {
"error": true,
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
}
]
}
}
}
]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment