From c3f85ae2b6f270912281ec69c3846070a2f7efe6 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:31:52 +0200
Subject: [PATCH 01/15] POC Exposing SnapshotTime
---
src/MongoDB.Driver/ClientSessionHandle.cs | 2 +
src/MongoDB.Driver/ClientSessionOptions.cs | 9 +-
.../Core/Bindings/CoreSession.cs | 1 +
.../Core/Bindings/CoreSessionOptions.cs | 14 ++-
.../Core/Operations/ReadConcernHelper.cs | 2 +-
src/MongoDB.Driver/IClientSession.cs | 5 +
src/MongoDB.Driver/MongoClient.cs | 2 +
.../AtClusterTimeTests.cs | 112 ++++++++++++++++++
8 files changed, 144 insertions(+), 3 deletions(-)
create mode 100644 tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
diff --git a/src/MongoDB.Driver/ClientSessionHandle.cs b/src/MongoDB.Driver/ClientSessionHandle.cs
index 144e6a94991..084c4db740b 100644
--- a/src/MongoDB.Driver/ClientSessionHandle.cs
+++ b/src/MongoDB.Driver/ClientSessionHandle.cs
@@ -89,6 +89,8 @@ public IServerSession ServerSession
}
}
+ public BsonTimestamp SnapshotTime => _coreSession.SnapshotTime;
+
///
public ICoreSessionHandle WrappedCoreSession => _coreSession;
diff --git a/src/MongoDB.Driver/ClientSessionOptions.cs b/src/MongoDB.Driver/ClientSessionOptions.cs
index f4b7f80ccac..e670b274116 100644
--- a/src/MongoDB.Driver/ClientSessionOptions.cs
+++ b/src/MongoDB.Driver/ClientSessionOptions.cs
@@ -14,6 +14,7 @@
*/
using System;
+using MongoDB.Bson;
using MongoDB.Driver.Core.Bindings;
namespace MongoDB.Driver
@@ -46,6 +47,11 @@ public class ClientSessionOptions
///
public bool Snapshot { get; set;}
+ ///
+ /// //TODO
+ ///
+ public BsonTimestamp SnapshotTime { get; set; }
+
// internal methods
internal CoreSessionOptions ToCore(bool isImplicit = false)
{
@@ -55,7 +61,8 @@ internal CoreSessionOptions ToCore(bool isImplicit = false)
isCausallyConsistent: isCausallyConsistent,
isImplicit: isImplicit,
isSnapshot: Snapshot,
- defaultTransactionOptions: DefaultTransactionOptions);
+ defaultTransactionOptions: DefaultTransactionOptions,
+ snapshotTime: SnapshotTime);
}
}
}
diff --git a/src/MongoDB.Driver/Core/Bindings/CoreSession.cs b/src/MongoDB.Driver/Core/Bindings/CoreSession.cs
index 954c639e244..d3366cdc188 100644
--- a/src/MongoDB.Driver/Core/Bindings/CoreSession.cs
+++ b/src/MongoDB.Driver/Core/Bindings/CoreSession.cs
@@ -71,6 +71,7 @@ private CoreSession(
{
_cluster = Ensure.IsNotNull(cluster, nameof(cluster));
_options = Ensure.IsNotNull(options, nameof(options));
+ _snapshotTime = options.SnapshotTime;
}
// public properties
diff --git a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
index d5697312fcf..6c8e97948cf 100644
--- a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
+++ b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
@@ -13,8 +13,11 @@
* limitations under the License.
*/
+using MongoDB.Bson;
+
namespace MongoDB.Driver.Core.Bindings
{
+ //TODO Why is this class public?
///
/// Core session options.
///
@@ -25,6 +28,7 @@ public class CoreSessionOptions
private readonly bool _isCausallyConsistent;
private readonly bool _isImplicit;
private readonly bool _isSnapshot;
+ private readonly BsonTimestamp _snapshotTime;
// constructors
///
@@ -34,16 +38,19 @@ public class CoreSessionOptions
/// if set to true this session is an implicit session.
/// if set to true this session is a snapshot session.
/// The default transaction options.
+ /// //TODO
public CoreSessionOptions(
bool isCausallyConsistent = false,
bool isImplicit = false,
TransactionOptions defaultTransactionOptions = null,
- bool isSnapshot = false)
+ bool isSnapshot = false,
+ BsonTimestamp snapshotTime = null)
{
_isCausallyConsistent = isCausallyConsistent;
_isImplicit = isImplicit;
_isSnapshot = isSnapshot;
_defaultTransactionOptions = defaultTransactionOptions;
+ _snapshotTime = snapshotTime;
}
// public properties
@@ -78,5 +85,10 @@ public CoreSessionOptions(
/// true if this session is a snapshot session; otherwise, false.
///
public bool IsSnapshot => _isSnapshot;
+
+ ///
+ /// //TODO
+ ///
+ public BsonTimestamp SnapshotTime => _snapshotTime;
}
}
diff --git a/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs b/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs
index 4938b357df4..914c1967735 100644
--- a/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs
+++ b/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs
@@ -40,7 +40,7 @@ public static BsonDocument GetReadConcernForSnapshotSession(ICoreSession session
Feature.SnapshotReads.ThrowIfNotSupported(connectionDescription.MaxWireVersion);
var readConcernDocument = ReadConcern.Snapshot.ToBsonDocument();
- if (session.SnapshotTime != null)
+ if (session.SnapshotTime != null) // For the first read within a snapshot session, SnapshotTime will be null
{
readConcernDocument.Add("atClusterTime", session.SnapshotTime);
}
diff --git a/src/MongoDB.Driver/IClientSession.cs b/src/MongoDB.Driver/IClientSession.cs
index a0809fcae3c..26d46cd5967 100644
--- a/src/MongoDB.Driver/IClientSession.cs
+++ b/src/MongoDB.Driver/IClientSession.cs
@@ -83,6 +83,11 @@ public interface IClientSession : IDisposable
///
IServerSession ServerSession { get; }
+ ///
+ /// //TODO
+ ///
+ BsonTimestamp SnapshotTime { get; }
+
///
/// Gets the wrapped core session (intended for internal use only).
///
diff --git a/src/MongoDB.Driver/MongoClient.cs b/src/MongoDB.Driver/MongoClient.cs
index 4b70bfdfd16..bac494e1b9a 100644
--- a/src/MongoDB.Driver/MongoClient.cs
+++ b/src/MongoDB.Driver/MongoClient.cs
@@ -627,6 +627,8 @@ private IClientSessionHandle StartSession(ClientSessionOptions options)
throw new NotSupportedException("Combining both causal consistency and snapshot options is not supported.");
}
+ //TODO Throw an exception if SnapshotTime is set and Snapshot is not true.
+
options ??= new ClientSessionOptions();
if (_settings.Timeout.HasValue && options.DefaultTransactionOptions?.Timeout == null)
{
diff --git a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
new file mode 100644
index 00000000000..8ed9d197968
--- /dev/null
+++ b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
@@ -0,0 +1,112 @@
+/* Copyright 2010-present MongoDB Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System.Collections.Generic;
+using MongoDB.Bson;
+using MongoDB.Bson.Serialization.Attributes;
+using Xunit;
+
+namespace MongoDB.Driver.Tests;
+
+public class AtClusterTimeTests
+{
+ [Fact]
+ public void AtClusterTime_should_work()
+ {
+ const string collectionName = "atClusterTimeTests";
+ const string databaseName = "testDb";
+
+ using var client = DriverTestConfiguration.Client;
+ var database = client.GetDatabase(databaseName);
+ database.DropCollection(collectionName);
+ var collection = database.GetCollection(collectionName);
+
+ var obj1 = new TestObject { Name = "obj1" };
+ collection.InsertOne(obj1);
+
+ BsonTimestamp clusterTime1;
+
+ var filterDefinition = Builders.Filter.Empty;
+ var sortDefinition = Builders.Sort.Ascending(o => o.Name);
+
+ var sessionOptions1 = new ClientSessionOptions
+ {
+ Snapshot = true
+ };
+
+ using (var session1 = client.StartSession(sessionOptions1))
+ {
+ var results = collection.Find(session1, filterDefinition).Sort(sortDefinition).ToList();
+ AssertOneObj(results);
+
+ clusterTime1 = session1.SnapshotTime;
+ Assert.NotEqual(null, clusterTime1);
+ }
+
+ var obj2 = new TestObject { Name = "obj2" };
+ collection.InsertOne(obj2);
+
+ var sessionOptions2 = new ClientSessionOptions
+ {
+ Snapshot = true,
+ SnapshotTime = clusterTime1
+ };
+
+ //Snapshot read session at clusterTime1 should not see obj2
+ using (var session2 = client.StartSession(sessionOptions2))
+ {
+ var results = collection.Find(session2, filterDefinition).Sort(sortDefinition).ToList();
+ AssertOneObj(results);
+
+ var clusterTime2 = session2.SnapshotTime;
+ Assert.Equal(clusterTime2, clusterTime1);
+ }
+
+ var sessionOptions3 = new ClientSessionOptions
+ {
+ Snapshot = true,
+ };
+
+ //Snapshot read session without cluster time should see obj2
+ using (var session3 = client.StartSession(sessionOptions3))
+ {
+ var results = collection.Find(session3, filterDefinition).Sort(sortDefinition).ToList();
+ AssertTwoObjs(results);
+
+ var clusterTime3 = session3.WrappedCoreSession.SnapshotTime;
+ Assert.NotEqual(clusterTime3, clusterTime1);
+ }
+
+ void AssertOneObj(List objs)
+ {
+ Assert.Equal(1, objs.Count);
+ Assert.Equal("obj1", objs[0].Name);
+ }
+
+ void AssertTwoObjs(List objs)
+ {
+ Assert.Equal(2, objs.Count);
+ Assert.Equal("obj1", objs[0].Name);
+ Assert.Equal("obj2", objs[1].Name);
+ }
+ }
+
+ private class TestObject
+ {
+ [BsonId]
+ public ObjectId Id { get; set; }
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
From e30d62c0ddbfea9ed8561606f0ef9e665f266f43 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:40:37 +0200
Subject: [PATCH 02/15] Small corrections
---
src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs | 1 -
src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
index 6c8e97948cf..828ba94f1a4 100644
--- a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
+++ b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
@@ -17,7 +17,6 @@
namespace MongoDB.Driver.Core.Bindings
{
- //TODO Why is this class public?
///
/// Core session options.
///
diff --git a/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs b/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs
index 914c1967735..4938b357df4 100644
--- a/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs
+++ b/src/MongoDB.Driver/Core/Operations/ReadConcernHelper.cs
@@ -40,7 +40,7 @@ public static BsonDocument GetReadConcernForSnapshotSession(ICoreSession session
Feature.SnapshotReads.ThrowIfNotSupported(connectionDescription.MaxWireVersion);
var readConcernDocument = ReadConcern.Snapshot.ToBsonDocument();
- if (session.SnapshotTime != null) // For the first read within a snapshot session, SnapshotTime will be null
+ if (session.SnapshotTime != null)
{
readConcernDocument.Add("atClusterTime", session.SnapshotTime);
}
From fcbefd9abac8c1ed175fc80f6a73a452411ad106 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:46:23 +0200
Subject: [PATCH 03/15] Small fix
---
src/MongoDB.Driver/IClientSession.cs | 14 +++++++++-----
tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs | 4 ++--
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/MongoDB.Driver/IClientSession.cs b/src/MongoDB.Driver/IClientSession.cs
index 26d46cd5967..ed28891abd1 100644
--- a/src/MongoDB.Driver/IClientSession.cs
+++ b/src/MongoDB.Driver/IClientSession.cs
@@ -21,6 +21,15 @@
namespace MongoDB.Driver
{
+ public static class ClientSessionExtensions
+ {
+ //TODO This will need to be moved somewhere else
+ public static BsonTimestamp GetSnapshotTime(this IClientSessionHandle session)
+ {
+ return ((ClientSessionHandle)session).SnapshotTime;
+ }
+ }
+
///
/// The interface for a client session.
///
@@ -83,11 +92,6 @@ public interface IClientSession : IDisposable
///
IServerSession ServerSession { get; }
- ///
- /// //TODO
- ///
- BsonTimestamp SnapshotTime { get; }
-
///
/// Gets the wrapped core session (intended for internal use only).
///
diff --git a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
index 8ed9d197968..d5a8eb78b91 100644
--- a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
+++ b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
@@ -51,7 +51,7 @@ public void AtClusterTime_should_work()
var results = collection.Find(session1, filterDefinition).Sort(sortDefinition).ToList();
AssertOneObj(results);
- clusterTime1 = session1.SnapshotTime;
+ clusterTime1 = session1.GetSnapshotTime();
Assert.NotEqual(null, clusterTime1);
}
@@ -70,7 +70,7 @@ public void AtClusterTime_should_work()
var results = collection.Find(session2, filterDefinition).Sort(sortDefinition).ToList();
AssertOneObj(results);
- var clusterTime2 = session2.SnapshotTime;
+ var clusterTime2 = session2.GetSnapshotTime();
Assert.Equal(clusterTime2, clusterTime1);
}
From 117276b6dad8af39cff5612f6b54f119a7e8f7b2 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:49:30 +0200
Subject: [PATCH 04/15] Added comments
---
src/MongoDB.Driver/IClientSession.cs | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/MongoDB.Driver/IClientSession.cs b/src/MongoDB.Driver/IClientSession.cs
index ed28891abd1..7e17f1331ac 100644
--- a/src/MongoDB.Driver/IClientSession.cs
+++ b/src/MongoDB.Driver/IClientSession.cs
@@ -21,9 +21,17 @@
namespace MongoDB.Driver
{
+ ///
+ /// //TODO
+ ///
public static class ClientSessionExtensions
{
//TODO This will need to be moved somewhere else
+ ///
+ /// //TODO
+ ///
+ ///
+ ///
public static BsonTimestamp GetSnapshotTime(this IClientSessionHandle session)
{
return ((ClientSessionHandle)session).SnapshotTime;
From 5d358db5942043d3c74ad1089add1bb98d6d9384 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:57:17 +0200
Subject: [PATCH 05/15] Small fix
---
tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
index d5a8eb78b91..7c56a109a66 100644
--- a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
+++ b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
@@ -16,6 +16,8 @@
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
+using MongoDB.Driver.Core.Clusters;
+using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
using Xunit;
namespace MongoDB.Driver.Tests;
@@ -25,6 +27,7 @@ public class AtClusterTimeTests
[Fact]
public void AtClusterTime_should_work()
{
+ RequireServer.Check().ClusterType(ClusterType.ReplicaSet);
const string collectionName = "atClusterTimeTests";
const string databaseName = "testDb";
From 375a7891ef43cb521180a01bb824fc358fc12711 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 11:30:49 +0200
Subject: [PATCH 06/15] Small fix
---
tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
index 7c56a109a66..eea9d16204d 100644
--- a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
+++ b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
@@ -17,6 +17,7 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver.Core.Clusters;
+using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
using Xunit;
@@ -27,7 +28,7 @@ public class AtClusterTimeTests
[Fact]
public void AtClusterTime_should_work()
{
- RequireServer.Check().ClusterType(ClusterType.ReplicaSet);
+ RequireServer.Check().ClusterType(ClusterType.ReplicaSet).Supports(Feature.SnapshotReads);
const string collectionName = "atClusterTimeTests";
const string databaseName = "testDb";
From ed34398e454702268e13ef51b7199d6650ffae9c Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 11:43:39 +0200
Subject: [PATCH 07/15] Added missing category
---
tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
index eea9d16204d..a2811242d07 100644
--- a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
+++ b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
@@ -23,6 +23,7 @@
namespace MongoDB.Driver.Tests;
+[Trait("Category", "Integration")]
public class AtClusterTimeTests
{
[Fact]
From 605a2a51f610f3d9714bd9ad9a7c0474c85007cc Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 16:39:54 +0200
Subject: [PATCH 08/15] Added constructor
---
.../Core/Bindings/CoreSessionOptions.cs | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
index 828ba94f1a4..0ee0a1ac0b7 100644
--- a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
+++ b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
@@ -52,6 +52,22 @@ public CoreSessionOptions(
_snapshotTime = snapshotTime;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true this session is causally consistent]
+ /// if set to true this session is an implicit session.
+ /// if set to true this session is a snapshot session.
+ /// The default transaction options.
+ public CoreSessionOptions(
+ bool isCausallyConsistent,
+ bool isImplicit,
+ TransactionOptions defaultTransactionOptions,
+ bool isSnapshot)
+ : this(isCausallyConsistent, isImplicit, defaultTransactionOptions, isSnapshot, null)
+ {
+ }
+
// public properties
///
/// Gets the default transaction options.
From e234fbbb4dc07d41217cd93a23f11dc570a211f0 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 18 Sep 2025 18:15:49 +0200
Subject: [PATCH 09/15] Fixed tests
---
.../AtClusterTimeTests.cs | 151 ++++++++++++++----
1 file changed, 121 insertions(+), 30 deletions(-)
diff --git a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
index a2811242d07..209056c7863 100644
--- a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
+++ b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
@@ -18,34 +18,26 @@
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver.Core.Clusters;
using MongoDB.Driver.Core.Misc;
-using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
+using MongoDB.Driver.TestHelpers;
using Xunit;
namespace MongoDB.Driver.Tests;
-[Trait("Category", "Integration")]
-public class AtClusterTimeTests
+public class AtClusterTimeTests : IntegrationTest
{
- [Fact]
- public void AtClusterTime_should_work()
+ public AtClusterTimeTests(ClassFixture fixture)
+ : base(fixture, server => server.Supports(Feature.SnapshotReads).ClusterType(ClusterType.ReplicaSet))
{
- RequireServer.Check().ClusterType(ClusterType.ReplicaSet).Supports(Feature.SnapshotReads);
- const string collectionName = "atClusterTimeTests";
- const string databaseName = "testDb";
-
- using var client = DriverTestConfiguration.Client;
- var database = client.GetDatabase(databaseName);
- database.DropCollection(collectionName);
- var collection = database.GetCollection(collectionName);
+ }
- var obj1 = new TestObject { Name = "obj1" };
- collection.InsertOne(obj1);
+ [Fact]
+ public void MainTest()
+ {
+ var client = Fixture.Client;
+ var collection = Fixture.Collection;
BsonTimestamp clusterTime1;
- var filterDefinition = Builders.Filter.Empty;
- var sortDefinition = Builders.Sort.Ascending(o => o.Name);
-
var sessionOptions1 = new ClientSessionOptions
{
Snapshot = true
@@ -53,7 +45,7 @@ public void AtClusterTime_should_work()
using (var session1 = client.StartSession(sessionOptions1))
{
- var results = collection.Find(session1, filterDefinition).Sort(sortDefinition).ToList();
+ var results = GetTestObjects(collection, session1);
AssertOneObj(results);
clusterTime1 = session1.GetSnapshotTime();
@@ -72,7 +64,7 @@ public void AtClusterTime_should_work()
//Snapshot read session at clusterTime1 should not see obj2
using (var session2 = client.StartSession(sessionOptions2))
{
- var results = collection.Find(session2, filterDefinition).Sort(sortDefinition).ToList();
+ var results = GetTestObjects(collection, session2);
AssertOneObj(results);
var clusterTime2 = session2.GetSnapshotTime();
@@ -87,28 +79,127 @@ public void AtClusterTime_should_work()
//Snapshot read session without cluster time should see obj2
using (var session3 = client.StartSession(sessionOptions3))
{
- var results = collection.Find(session3, filterDefinition).Sort(sortDefinition).ToList();
+ var results = GetTestObjects(collection, session3);
AssertTwoObjs(results);
- var clusterTime3 = session3.WrappedCoreSession.SnapshotTime;
+ var clusterTime3 = session3.GetSnapshotTime();
Assert.NotEqual(clusterTime3, clusterTime1);
}
+ }
- void AssertOneObj(List objs)
+ [Fact]
+ public void IncreasedTimestamp()
+ {
+ var client = Fixture.Client;
+ var collection = Fixture.Collection;
+
+ BsonTimestamp clusterTime1;
+
+ var sessionOptions1 = new ClientSessionOptions
+ {
+ Snapshot = true
+ };
+
+ using (var session1 = client.StartSession(sessionOptions1))
{
- Assert.Equal(1, objs.Count);
- Assert.Equal("obj1", objs[0].Name);
+ var results = GetTestObjects(collection, session1);
+ AssertOneObj(results);
+
+ clusterTime1 = session1.GetSnapshotTime();
+ Assert.NotEqual(null, clusterTime1);
}
- void AssertTwoObjs(List objs)
+ var obj2 = new TestObject { Name = "obj2" };
+ collection.InsertOne(obj2);
+
+ var modifiedClusterTime = new BsonTimestamp(clusterTime1.Value + 1);
+ var sessionOptions2 = new ClientSessionOptions
{
- Assert.Equal(2, objs.Count);
- Assert.Equal("obj1", objs[0].Name);
- Assert.Equal("obj2", objs[1].Name);
+ Snapshot = true,
+ SnapshotTime = modifiedClusterTime
+ };
+
+ //Snapshot read session at clusterTime1+1 should see obj2
+ using (var session2 = client.StartSession(sessionOptions2))
+ {
+ var results = GetTestObjects(collection, session2);
+ AssertTwoObjs(results);
+
+ var clusterTime2 = session2.GetSnapshotTime();
+ Assert.Equal(modifiedClusterTime, clusterTime2);
}
}
- private class TestObject
+ [Fact]
+ public void DecreasedTimestamp()
+ {
+ var client = Fixture.Client;
+ var collection = Fixture.Collection;
+
+ BsonTimestamp clusterTime1;
+
+ var sessionOptions1 = new ClientSessionOptions
+ {
+ Snapshot = true
+ };
+
+ using (var session1 = client.StartSession(sessionOptions1))
+ {
+ var results = GetTestObjects(collection, session1);
+ AssertOneObj(results);
+
+ clusterTime1 = session1.GetSnapshotTime();
+ Assert.NotEqual(null, clusterTime1);
+ }
+
+ var obj2 = new TestObject { Name = "obj2" };
+ collection.InsertOne(obj2);
+
+ var modifiedClusterTime = new BsonTimestamp(clusterTime1.Value - 1);
+ var sessionOptions2 = new ClientSessionOptions
+ {
+ Snapshot = true,
+ SnapshotTime = modifiedClusterTime
+ };
+
+ //Snapshot read session at clusterTime1-1 should not see obj2
+ using (var session2 = client.StartSession(sessionOptions2))
+ {
+ var results = GetTestObjects(collection, session2);
+ Assert.Equal(0, results.Count);
+
+ var clusterTime2 = session2.GetSnapshotTime();
+ Assert.Equal(modifiedClusterTime, clusterTime2);
+ }
+ }
+
+ List GetTestObjects(IMongoCollection collection, IClientSessionHandle session)
+ {
+ var filterDefinition = Builders.Filter.Empty;
+ var sortDefinition = Builders.Sort.Ascending(o => o.Name);
+ return collection.Find(session, filterDefinition).Sort(sortDefinition).ToList();
+ }
+
+ void AssertOneObj(List objs)
+ {
+ Assert.Equal(1, objs.Count);
+ Assert.Equal("obj1", objs[0].Name);
+ }
+
+ void AssertTwoObjs(List objs)
+ {
+ Assert.Equal(2, objs.Count);
+ Assert.Equal("obj1", objs[0].Name);
+ Assert.Equal("obj2", objs[1].Name);
+ }
+
+ public class ClassFixture : MongoCollectionFixture
+ {
+ public override bool InitializeDataBeforeEachTestCase => true;
+ protected override IEnumerable InitialData => [new() { Name = "obj1" }] ;
+ }
+
+ public class TestObject
{
[BsonId]
public ObjectId Id { get; set; }
From 7d320319ef74764f2b19ac4d49f4c70098d48509 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Wed, 24 Sep 2025 17:52:39 +0200
Subject: [PATCH 10/15] Added comment.
---
src/MongoDB.Driver/ClientSessionOptions.cs | 3 ++-
.../Core/Bindings/CoreSessionOptions.cs | 2 +-
.../UnifiedGetSnapshotOperation.cs | 21 +++++++++++++++++++
3 files changed, 24 insertions(+), 2 deletions(-)
create mode 100644 tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedGetSnapshotOperation.cs
diff --git a/src/MongoDB.Driver/ClientSessionOptions.cs b/src/MongoDB.Driver/ClientSessionOptions.cs
index e670b274116..3ff667ada60 100644
--- a/src/MongoDB.Driver/ClientSessionOptions.cs
+++ b/src/MongoDB.Driver/ClientSessionOptions.cs
@@ -48,7 +48,8 @@ public class ClientSessionOptions
public bool Snapshot { get; set;}
///
- /// //TODO
+ /// Gets or sets the snapshot time. If set, Snapshot must be true.
+ /// The snapshot time
///
public BsonTimestamp SnapshotTime { get; set; }
diff --git a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
index 0ee0a1ac0b7..d0bc03f2fe6 100644
--- a/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
+++ b/src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs
@@ -37,7 +37,7 @@ public class CoreSessionOptions
/// if set to true this session is an implicit session.
/// if set to true this session is a snapshot session.
/// The default transaction options.
- /// //TODO
+ /// The snapshot time. If this is set, isSnapshot must be true.
public CoreSessionOptions(
bool isCausallyConsistent = false,
bool isImplicit = false,
diff --git a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedGetSnapshotOperation.cs b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedGetSnapshotOperation.cs
new file mode 100644
index 00000000000..8f2c9748068
--- /dev/null
+++ b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedGetSnapshotOperation.cs
@@ -0,0 +1,21 @@
+/* Copyright 2010-present MongoDB Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace MongoDB.Driver.Tests.UnifiedTestOperations;
+
+public class UnifiedGetSnapshotOperation
+{
+
+}
\ No newline at end of file
From ee85c62c7be228b6c3b55c97983faca1ebe5781a Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 25 Sep 2025 09:54:03 +0200
Subject: [PATCH 11/15] Added test infrastructure
---
.../sessions/tests/snapshot-sessions.json | 141 ++++++++++++++++++
.../sessions/tests/snapshot-sessions.yml | 68 +++++++++
.../UnifiedTestOperations/UnifiedEntityMap.cs | 3 +
.../UnifiedGetSnapshotOperation.cs | 52 ++++++-
.../UnifiedTestOperationFactory.cs | 1 +
5 files changed, 263 insertions(+), 2 deletions(-)
diff --git a/specifications/sessions/tests/snapshot-sessions.json b/specifications/sessions/tests/snapshot-sessions.json
index 260f8b6f489..89460ab6559 100644
--- a/specifications/sessions/tests/snapshot-sessions.json
+++ b/specifications/sessions/tests/snapshot-sessions.json
@@ -988,6 +988,147 @@
}
}
]
+ },
+ {
+ "description": "Find operation with snapshot and snapshot time",
+ "operations": [
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "session": "session0",
+ "filter": {}
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ },
+ {
+ "_id": 2,
+ "x": 11
+ }
+ ]
+ },
+ {
+ "name": "getSnapshotTime",
+ "object": "session0",
+ "saveResultAsEntity": "savedSnapshotTime"
+ },
+ {
+ "name": "insertOne",
+ "object": "collection0",
+ "arguments": {
+ "document": {
+ "_id": 3,
+ "x": 33
+ }
+ }
+ },
+ {
+ "name": "createEntities",
+ "object": "testRunner",
+ "arguments": {
+ "entities": [
+ {
+ "session": {
+ "id": "session2",
+ "client": "client0",
+ "sessionOptions": {
+ "snapshot": true,
+ "snapshotTime": "savedSnapshotTime"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "filter": {}
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ },
+ {
+ "_id": 2,
+ "x": 11
+ }
+ ]
+ },
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "filter": {}
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ },
+ {
+ "_id": 2,
+ "x": 11
+ },
+ {
+ "_id": 3,
+ "x": 33
+ }
+ ]
+ }
+ ],
+ "expectEvents": [
+ {
+ "client": "client0",
+ "events": [
+ {
+ "commandStartedEvent": {
+ "command": {
+ "find": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$exists": false
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "find": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "find": "collection0",
+ "readConcern": {
+ "$$exists": false
+ }
+ },
+ "databaseName": "database0"
+ }
+ }
+ ]
+ }
+ ]
}
]
}
diff --git a/specifications/sessions/tests/snapshot-sessions.yml b/specifications/sessions/tests/snapshot-sessions.yml
index bcf0f7eec6b..f842e44bdb6 100644
--- a/specifications/sessions/tests/snapshot-sessions.yml
+++ b/specifications/sessions/tests/snapshot-sessions.yml
@@ -480,3 +480,71 @@ tests:
isError: true
isClientError: true
errorContains: Transactions are not supported in snapshot sessions
+
+- description: Find operation with snapshot and snapshot time
+ operations:
+ - name: find
+ object: collection0
+ arguments:
+ session: session0
+ filter: {}
+ expectResult:
+ - { _id: 1, x: 11 }
+ - { _id: 2, x: 11 }
+ - name: getSnapshotTime
+ object: session0
+ saveResultAsEntity: &savedSnapshotTime savedSnapshotTime
+ - name: insertOne
+ object: collection0
+ arguments:
+ document: { _id: 3, x: 33 }
+ - name: createEntities
+ object: testRunner
+ arguments:
+ entities:
+ - session:
+ id: session2
+ client: client0
+ sessionOptions:
+ snapshot: true
+ snapshotTime: *savedSnapshotTime
+ - name: find
+ object: collection0
+ arguments:
+ session: session2
+ filter: {}
+ expectResult:
+ - { _id: 1, x: 11 }
+ - { _id: 2, x: 11 }
+ - name: find
+ object: collection0
+ arguments:
+ filter: {}
+ expectResult:
+ - { _id: 1, x: 11 }
+ - { _id: 2, x: 11 }
+ - { _id: 3, x: 33 }
+ expectEvents:
+ - client: client0
+ events:
+ - commandStartedEvent:
+ command:
+ find: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime:
+ "$$exists": false
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ find: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ find: collection0
+ readConcern:
+ "$$exists": false
+ databaseName: database0
diff --git a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEntityMap.cs b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEntityMap.cs
index e5ea553ff15..cea7cc56391 100644
--- a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEntityMap.cs
+++ b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedEntityMap.cs
@@ -1056,6 +1056,9 @@ private IClientSessionHandle CreateSession(BsonDocument entity, Dictionary GetSnapshotTime();
+
+ //TODO Do we necessarily need an async version of this...?
+ public Task ExecuteAsync(CancellationToken cancellationToken) => Task.FromResult(GetSnapshotTime());
+
+ private OperationResult GetSnapshotTime()
+ {
+ try
+ {
+ return OperationResult.FromResult(_session.GetSnapshotTime());
+ }
+ catch (Exception exception)
+ {
+ return OperationResult.FromException(exception);
+ }
+ }
+}
+
+public class UnifiedGetSnapshotOperationBuilder
{
-
+ private readonly UnifiedEntityMap _entityMap;
+
+ public UnifiedGetSnapshotOperationBuilder(UnifiedEntityMap entityMap)
+ {
+ _entityMap = entityMap;
+ }
+
+ public UnifiedGetSnapshotOperation Build(string targetSessionId, BsonDocument arguments)
+ {
+ if (arguments != null)
+ {
+ throw new FormatException("GetSnapshotTime is not expected to contain arguments.");
+ }
+
+ var session = _entityMap.Sessions[targetSessionId];
+ return new UnifiedGetSnapshotOperation(session);
+ }
}
\ No newline at end of file
diff --git a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedTestOperationFactory.cs b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedTestOperationFactory.cs
index 32e6ec08f3d..099ae07359f 100644
--- a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedTestOperationFactory.cs
+++ b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedTestOperationFactory.cs
@@ -133,6 +133,7 @@ public IUnifiedTestOperation CreateOperation(string operationName, string target
"abortTransaction" => new UnifiedAbortTransactionOperationBuilder(_entityMap).Build(targetEntityId, operationArguments),
"commitTransaction" => new UnifiedCommitTransactionOperationBuilder(_entityMap).Build(targetEntityId, operationArguments),
"endSession" => new UnifiedEndSessionOperationBuilder(_entityMap).Build(targetEntityId, operationArguments),
+ "getSnapshotTime" => new UnifiedGetSnapshotOperationBuilder(_entityMap).Build(targetEntityId, operationArguments),
"startTransaction" => new UnifiedStartTransactionOperationBuilder(_entityMap).Build(targetEntityId, operationArguments),
"withTransaction" => new UnifiedWithTransactionOperationBuilder(_entityMap).Build(targetEntityId, operationArguments),
_ => throw new FormatException($"Invalid method name: '{operationName}'."),
From f647078859fef7d6f3dce863fad03a0cc7380a11 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 25 Sep 2025 10:32:40 +0200
Subject: [PATCH 12/15] Added prose test
---
.../sessions/tests/snapshot-sessions.json | 32 +++++++++++++++++++
.../sessions/tests/snapshot-sessions.yml | 21 ++++++++++--
src/MongoDB.Driver/MongoClient.cs | 14 +++++---
.../sessions/SessionsProseTests.cs | 18 +++++++++++
4 files changed, 79 insertions(+), 6 deletions(-)
diff --git a/specifications/sessions/tests/snapshot-sessions.json b/specifications/sessions/tests/snapshot-sessions.json
index 89460ab6559..48aecc16ecc 100644
--- a/specifications/sessions/tests/snapshot-sessions.json
+++ b/specifications/sessions/tests/snapshot-sessions.json
@@ -1061,6 +1061,24 @@
}
]
},
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "filter": {}
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ },
+ {
+ "_id": 2,
+ "x": 11
+ }
+ ]
+ },
{
"name": "find",
"object": "collection0",
@@ -1115,6 +1133,20 @@
"databaseName": "database0"
}
},
+ {
+ "commandStartedEvent": {
+ "command": {
+ "find": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
{
"commandStartedEvent": {
"command": {
diff --git a/specifications/sessions/tests/snapshot-sessions.yml b/specifications/sessions/tests/snapshot-sessions.yml
index f842e44bdb6..74c6f928313 100644
--- a/specifications/sessions/tests/snapshot-sessions.yml
+++ b/specifications/sessions/tests/snapshot-sessions.yml
@@ -378,7 +378,7 @@ tests:
fieldName: x
filter: {}
session: session0
- expectResult: [ 11 ]
+ expectResult: [ 11 ]
expectEvents:
- client: client0
events:
@@ -508,6 +508,16 @@ tests:
sessionOptions:
snapshot: true
snapshotTime: *savedSnapshotTime
+ - name: find
+ object: collection0
+ arguments:
+ session: session2
+ filter: {}
+ expectResult:
+ - { _id: 1, x: 11 }
+ - { _id: 2, x: 11 }
+ ## Calling find again to verify that atClusterTime/snapshotTime has not been modified after the first query
+ ## as it would happen if snapshotTime had not been specified
- name: find
object: collection0
arguments:
@@ -540,7 +550,14 @@ tests:
find: collection0
readConcern:
level: snapshot
- atClusterTime: { $$matchesEntity: savedSnapshotTime }
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ find: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
databaseName: database0
- commandStartedEvent:
command:
diff --git a/src/MongoDB.Driver/MongoClient.cs b/src/MongoDB.Driver/MongoClient.cs
index bac494e1b9a..833991d511c 100644
--- a/src/MongoDB.Driver/MongoClient.cs
+++ b/src/MongoDB.Driver/MongoClient.cs
@@ -622,12 +622,18 @@ private RenderArgs GetRenderArgs()
private IClientSessionHandle StartSession(ClientSessionOptions options)
{
- if (options != null && options.Snapshot && options.CausalConsistency == true)
+ if (options != null)
{
- throw new NotSupportedException("Combining both causal consistency and snapshot options is not supported.");
- }
+ if (options.SnapshotTime != null && !options.Snapshot)
+ {
+ throw new NotSupportedException("Specifying a snapshot time requires snapshot to be true.");
+ }
- //TODO Throw an exception if SnapshotTime is set and Snapshot is not true.
+ if (options.Snapshot && options.CausalConsistency == true)
+ {
+ throw new NotSupportedException("Combining both causal consistency and snapshot options is not supported.");
+ }
+ }
options ??= new ClientSessionOptions();
if (_settings.Timeout.HasValue && options.DefaultTransactionOptions?.Timeout == null)
diff --git a/tests/MongoDB.Driver.Tests/Specifications/sessions/SessionsProseTests.cs b/tests/MongoDB.Driver.Tests/Specifications/sessions/SessionsProseTests.cs
index 649e2ae2df9..40244a88523 100644
--- a/tests/MongoDB.Driver.Tests/Specifications/sessions/SessionsProseTests.cs
+++ b/tests/MongoDB.Driver.Tests/Specifications/sessions/SessionsProseTests.cs
@@ -357,6 +357,24 @@ public void Ensure_cluster_times_are_not_gossiped_on_SDAM_commands()
commandStartedEvents[0].Command["$clusterTime"].Should().Be(clusterTime);
}
+ [Fact]
+ public void If_SnapshotTime_is_set_Snapshot_must_be_true()
+ {
+ RequireServer.Check();
+
+ var sessionOptions = new ClientSessionOptions
+ {
+ Snapshot = false,
+ SnapshotTime = new BsonTimestamp(1, 1)
+ };
+
+ var mongoClient = DriverTestConfiguration.Client;
+
+ var exception = Record.Exception(() => mongoClient.StartSession(sessionOptions));
+ exception.Should().BeOfType();
+ }
+
+
private sealed class MongocryptdContext : IDisposable
{
public IMongoClient MongoClient { get; }
From 01faa2798af4aa43eb346944bfc8bab932f9c1bf Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 25 Sep 2025 10:40:51 +0200
Subject: [PATCH 13/15] Added distinct test
---
.../sessions/tests/snapshot-sessions.json | 146 ++++++++++++++++++
.../sessions/tests/snapshot-sessions.yml | 80 ++++++++++
.../AtClusterTimeTests.cs | 2 +-
3 files changed, 227 insertions(+), 1 deletion(-)
diff --git a/specifications/sessions/tests/snapshot-sessions.json b/specifications/sessions/tests/snapshot-sessions.json
index 48aecc16ecc..b35a535d0fc 100644
--- a/specifications/sessions/tests/snapshot-sessions.json
+++ b/specifications/sessions/tests/snapshot-sessions.json
@@ -1161,6 +1161,152 @@
]
}
]
+ },
+ {
+ "description": "Distinct operation with snapshot and snapshot time",
+ "operations": [
+ {
+ "name": "distinct",
+ "object": "collection0",
+ "arguments": {
+ "session": "session0",
+ "filter": {},
+ "fieldName": "x"
+ },
+ "expectResult": [
+ 11
+ ]
+ },
+ {
+ "name": "getSnapshotTime",
+ "object": "session0",
+ "saveResultAsEntity": "savedSnapshotTime"
+ },
+ {
+ "name": "insertOne",
+ "object": "collection0",
+ "arguments": {
+ "document": {
+ "_id": 3,
+ "x": 33
+ }
+ }
+ },
+ {
+ "name": "createEntities",
+ "object": "testRunner",
+ "arguments": {
+ "entities": [
+ {
+ "session": {
+ "id": "session2",
+ "client": "client0",
+ "sessionOptions": {
+ "snapshot": true,
+ "snapshotTime": "savedSnapshotTime"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "distinct",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "filter": {},
+ "fieldName": "x"
+ },
+ "expectResult": [
+ 11
+ ]
+ },
+ {
+ "name": "distinct",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "filter": {},
+ "fieldName": "x"
+ },
+ "expectResult": [
+ 11
+ ]
+ },
+ {
+ "name": "distinct",
+ "object": "collection0",
+ "arguments": {
+ "filter": {},
+ "fieldName": "x"
+ },
+ "expectResult": [
+ 11,
+ 33
+ ]
+ }
+ ],
+ "expectEvents": [
+ {
+ "client": "client0",
+ "events": [
+ {
+ "commandStartedEvent": {
+ "command": {
+ "distinct": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$exists": false
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "distinct": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "distinct": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "distinct": "collection0",
+ "readConcern": {
+ "$$exists": false
+ }
+ },
+ "databaseName": "database0"
+ }
+ }
+ ]
+ }
+ ]
}
]
}
diff --git a/specifications/sessions/tests/snapshot-sessions.yml b/specifications/sessions/tests/snapshot-sessions.yml
index 74c6f928313..22689ca3085 100644
--- a/specifications/sessions/tests/snapshot-sessions.yml
+++ b/specifications/sessions/tests/snapshot-sessions.yml
@@ -565,3 +565,83 @@ tests:
readConcern:
"$$exists": false
databaseName: database0
+
+- description: Distinct operation with snapshot and snapshot time
+ operations:
+ - name: distinct
+ object: collection0
+ arguments:
+ session: session0
+ filter: {}
+ fieldName: x
+ expectResult: [11]
+ - name: getSnapshotTime
+ object: session0
+ saveResultAsEntity: &savedSnapshotTime savedSnapshotTime
+ - name: insertOne
+ object: collection0
+ arguments:
+ document: { _id: 3, x: 33 }
+ - name: createEntities
+ object: testRunner
+ arguments:
+ entities:
+ - session:
+ id: session2
+ client: client0
+ sessionOptions:
+ snapshot: true
+ snapshotTime: *savedSnapshotTime
+ - name: distinct
+ object: collection0
+ arguments:
+ session: session2
+ filter: {}
+ fieldName: x
+ expectResult: [11]
+ ## Calling find again to verify that atClusterTime/snapshotTime has not been modified after the first query
+ ## as it would happen if snapshotTime had not been specified
+ - name: distinct
+ object: collection0
+ arguments:
+ session: session2
+ filter: {}
+ fieldName: x
+ expectResult: [11]
+ - name: distinct
+ object: collection0
+ arguments:
+ filter: {}
+ fieldName: x
+ expectResult: [11, 33]
+ expectEvents:
+ - client: client0
+ events:
+ - commandStartedEvent:
+ command:
+ distinct: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime:
+ "$$exists": false
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ distinct: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ distinct: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ distinct: collection0
+ readConcern:
+ "$$exists": false
+ databaseName: database0
\ No newline at end of file
diff --git a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
index 209056c7863..a97e96343bf 100644
--- a/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
+++ b/tests/MongoDB.Driver.Tests/AtClusterTimeTests.cs
@@ -22,7 +22,7 @@
using Xunit;
namespace MongoDB.Driver.Tests;
-
+//TODO This file will need to be deleted, but it's useful for testing at the moment
public class AtClusterTimeTests : IntegrationTest
{
public AtClusterTimeTests(ClassFixture fixture)
From a4d782bc9348a4db36d95052b607cdd2803e2dfe Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 25 Sep 2025 11:06:17 +0200
Subject: [PATCH 14/15] Added tests
---
.../sessions/tests/snapshot-sessions.json | 485 ++++++++++++++++++
.../sessions/tests/snapshot-sessions.yml | 247 ++++++++-
2 files changed, 731 insertions(+), 1 deletion(-)
diff --git a/specifications/sessions/tests/snapshot-sessions.json b/specifications/sessions/tests/snapshot-sessions.json
index b35a535d0fc..a831852e71e 100644
--- a/specifications/sessions/tests/snapshot-sessions.json
+++ b/specifications/sessions/tests/snapshot-sessions.json
@@ -1307,6 +1307,491 @@
]
}
]
+ },
+ {
+ "description": "Aggregate operation with snapshot and snapshot time",
+ "operations": [
+ {
+ "name": "aggregate",
+ "object": "collection0",
+ "arguments": {
+ "session": "session0",
+ "pipeline": [
+ {
+ "$match": {
+ "_id": 1
+ }
+ }
+ ]
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ }
+ ]
+ },
+ {
+ "name": "getSnapshotTime",
+ "object": "session0",
+ "saveResultAsEntity": "savedSnapshotTime"
+ },
+ {
+ "name": "findOneAndUpdate",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "_id": 1
+ },
+ "update": {
+ "$inc": {
+ "x": 1
+ }
+ },
+ "returnDocument": "After"
+ },
+ "expectResult": {
+ "_id": 1,
+ "x": 12
+ }
+ },
+ {
+ "name": "createEntities",
+ "object": "testRunner",
+ "arguments": {
+ "entities": [
+ {
+ "session": {
+ "id": "session2",
+ "client": "client0",
+ "sessionOptions": {
+ "snapshot": true,
+ "snapshotTime": "savedSnapshotTime"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "aggregate",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "pipeline": [
+ {
+ "$match": {
+ "_id": 1
+ }
+ }
+ ]
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ }
+ ]
+ },
+ {
+ "name": "aggregate",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "pipeline": [
+ {
+ "$match": {
+ "_id": 1
+ }
+ }
+ ]
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ }
+ ]
+ },
+ {
+ "name": "aggregate",
+ "object": "collection0",
+ "arguments": {
+ "pipeline": [
+ {
+ "$match": {
+ "_id": 1
+ }
+ }
+ ]
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 12
+ }
+ ]
+ }
+ ],
+ "expectEvents": [
+ {
+ "client": "client0",
+ "events": [
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$exists": false
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "$$exists": false
+ }
+ },
+ "databaseName": "database0"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "description": "countDocuments operation with snapshot and snapshot time",
+ "operations": [
+ {
+ "name": "countDocuments",
+ "object": "collection0",
+ "arguments": {
+ "session": "session0",
+ "filter": {}
+ },
+ "expectResult": 2
+ },
+ {
+ "name": "getSnapshotTime",
+ "object": "session0",
+ "saveResultAsEntity": "savedSnapshotTime"
+ },
+ {
+ "name": "insertOne",
+ "object": "collection0",
+ "arguments": {
+ "document": {
+ "_id": 3,
+ "x": 33
+ }
+ }
+ },
+ {
+ "name": "createEntities",
+ "object": "testRunner",
+ "arguments": {
+ "entities": [
+ {
+ "session": {
+ "id": "session2",
+ "client": "client0",
+ "sessionOptions": {
+ "snapshot": true,
+ "snapshotTime": "savedSnapshotTime"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "countDocuments",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "filter": {}
+ },
+ "expectResult": 2
+ },
+ {
+ "name": "countDocuments",
+ "object": "collection0",
+ "arguments": {
+ "session": "session2",
+ "filter": {}
+ },
+ "expectResult": 2
+ },
+ {
+ "name": "countDocuments",
+ "object": "collection0",
+ "arguments": {
+ "filter": {}
+ },
+ "expectResult": 3
+ }
+ ],
+ "expectEvents": [
+ {
+ "client": "client0",
+ "events": [
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$exists": false
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$matchesEntity": "savedSnapshotTime"
+ }
+ }
+ },
+ "databaseName": "database0"
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "$$exists": false
+ }
+ },
+ "databaseName": "database0"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "description": "Mixed operation with snapshot and snapshotTime",
+ "operations": [
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "session": "session0",
+ "filter": {
+ "_id": 1
+ }
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ }
+ ]
+ },
+ {
+ "name": "getSnapshotTime",
+ "object": "session0",
+ "saveResultAsEntity": "savedSnapshotTime"
+ },
+ {
+ "name": "findOneAndUpdate",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "_id": 1
+ },
+ "update": {
+ "$inc": {
+ "x": 1
+ }
+ },
+ "returnDocument": "After"
+ },
+ "expectResult": {
+ "_id": 1,
+ "x": 12
+ }
+ },
+ {
+ "name": "createEntities",
+ "object": "testRunner",
+ "arguments": {
+ "entities": [
+ {
+ "session": {
+ "id": "session2",
+ "client": "client0",
+ "sessionOptions": {
+ "snapshot": true,
+ "snapshotTime": "savedSnapshotTime"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "find",
+ "object": "collection0",
+ "arguments": {
+ "filter": {
+ "_id": 1
+ }
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 12
+ }
+ ]
+ },
+ {
+ "name": "aggregate",
+ "object": "collection0",
+ "arguments": {
+ "pipeline": [
+ {
+ "$match": {
+ "_id": 1
+ }
+ }
+ ],
+ "session": "session0"
+ },
+ "expectResult": [
+ {
+ "_id": 1,
+ "x": 11
+ }
+ ]
+ },
+ {
+ "name": "distinct",
+ "object": "collection0",
+ "arguments": {
+ "fieldName": "x",
+ "filter": {},
+ "session": "session0"
+ },
+ "expectResult": [
+ 11
+ ]
+ }
+ ],
+ "expectEvents": [
+ {
+ "client": "client0",
+ "events": [
+ {
+ "commandStartedEvent": {
+ "command": {
+ "find": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$exists": false
+ }
+ }
+ }
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "find": "collection0",
+ "readConcern": {
+ "$$exists": false
+ }
+ }
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "aggregate": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$exists": true
+ }
+ }
+ }
+ }
+ },
+ {
+ "commandStartedEvent": {
+ "command": {
+ "distinct": "collection0",
+ "readConcern": {
+ "level": "snapshot",
+ "atClusterTime": {
+ "$$exists": true
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
}
]
}
diff --git a/specifications/sessions/tests/snapshot-sessions.yml b/specifications/sessions/tests/snapshot-sessions.yml
index 22689ca3085..15ec3fa047c 100644
--- a/specifications/sessions/tests/snapshot-sessions.yml
+++ b/specifications/sessions/tests/snapshot-sessions.yml
@@ -309,6 +309,7 @@ tests:
atClusterTime:
"$$exists": true
+## This test seems to be wrong
- description: countDocuments operation with snapshot
operations:
- name: countDocuments
@@ -644,4 +645,248 @@ tests:
distinct: collection0
readConcern:
"$$exists": false
- databaseName: database0
\ No newline at end of file
+ databaseName: database0
+
+- description: Aggregate operation with snapshot and snapshot time
+ operations:
+ - name: aggregate
+ object: collection0
+ arguments:
+ session: session0
+ pipeline:
+ - "$match": { _id: 1 }
+ expectResult:
+ - { _id: 1, x: 11 }
+ - name: getSnapshotTime
+ object: session0
+ saveResultAsEntity: &savedSnapshotTime savedSnapshotTime
+ - name: findOneAndUpdate
+ object: collection0
+ arguments:
+ filter: { _id: 1 }
+ update: { $inc: { x: 1 } }
+ returnDocument: After
+ expectResult: { _id: 1, x: 12 }
+ - name: createEntities
+ object: testRunner
+ arguments:
+ entities:
+ - session:
+ id: session2
+ client: client0
+ sessionOptions:
+ snapshot: true
+ snapshotTime: *savedSnapshotTime
+ - name: aggregate
+ object: collection0
+ arguments:
+ session: session2
+ pipeline:
+ - "$match": { _id: 1 }
+ expectResult:
+ - { _id: 1, x: 11 }
+ ## Calling find again to verify that atClusterTime/snapshotTime has not been modified after the first query
+ ## as it would happen if snapshotTime had not been specified
+ - name: aggregate
+ object: collection0
+ arguments:
+ session: session2
+ pipeline:
+ - "$match": { _id: 1 }
+ expectResult:
+ - { _id: 1, x: 11 }
+ - name: aggregate
+ object: collection0
+ arguments:
+ pipeline:
+ - "$match": { _id: 1 }
+ expectResult:
+ - { _id: 1, x: 12 }
+ expectEvents:
+ - client: client0
+ events:
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime:
+ "$$exists": false
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ "$$exists": false
+ databaseName: database0
+
+- description: countDocuments operation with snapshot and snapshot time
+ operations:
+ - name: countDocuments
+ object: collection0
+ arguments:
+ session: session0
+ filter: {}
+ expectResult: 2
+ - name: getSnapshotTime
+ object: session0
+ saveResultAsEntity: &savedSnapshotTime savedSnapshotTime
+ - name: insertOne
+ object: collection0
+ arguments:
+ document: { _id: 3, x: 33 }
+ - name: createEntities
+ object: testRunner
+ arguments:
+ entities:
+ - session:
+ id: session2
+ client: client0
+ sessionOptions:
+ snapshot: true
+ snapshotTime: *savedSnapshotTime
+ - name: countDocuments
+ object: collection0
+ arguments:
+ session: session2
+ filter: {}
+ expectResult: 2
+ ## Calling find again to verify that atClusterTime/snapshotTime has not been modified after the first query
+ ## as it would happen if snapshotTime had not been specified
+ - name: countDocuments
+ object: collection0
+ arguments:
+ session: session2
+ filter: {}
+ expectResult: 2
+ - name: countDocuments
+ object: collection0
+ arguments:
+ filter: {}
+ expectResult: 3
+ expectEvents:
+ - client: client0
+ events:
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime:
+ "$$exists": false
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
+ databaseName: database0
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ "$$exists": false
+ databaseName: database0
+
+- description: Mixed operation with snapshot and snapshotTime
+ operations:
+ - name: find
+ object: collection0
+ arguments:
+ session: session0
+ filter: { _id: 1 }
+ expectResult:
+ - { _id: 1, x: 11 }
+ - name: getSnapshotTime
+ object: session0
+ saveResultAsEntity: &savedSnapshotTime savedSnapshotTime
+ - name: findOneAndUpdate
+ object: collection0
+ arguments:
+ filter: { _id: 1 }
+ update: { $inc: { x: 1 } }
+ returnDocument: After
+ expectResult: { _id: 1, x: 12 }
+ - name: createEntities
+ object: testRunner
+ arguments:
+ entities:
+ - session:
+ id: session2
+ client: client0
+ sessionOptions:
+ snapshot: true
+ snapshotTime: *savedSnapshotTime
+ - name: find
+ object: collection0
+ arguments:
+ filter: { _id: 1 }
+ expectResult:
+ - { _id: 1, x: 12 }
+ - name: aggregate
+ object: collection0
+ arguments:
+ pipeline:
+ - "$match":
+ _id: 1
+ session: session0
+ expectResult:
+ - { _id: 1, x: 11 }
+ - name: distinct
+ object: collection0
+ arguments:
+ fieldName: x
+ filter: {}
+ session: session0
+ expectResult: [ 11 ]
+ expectEvents:
+ - client: client0
+ events:
+ - commandStartedEvent:
+ command:
+ find: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime:
+ "$$exists": false
+ - commandStartedEvent:
+ command:
+ find: collection0
+ readConcern:
+ "$$exists": false
+ - commandStartedEvent:
+ command:
+ aggregate: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime:
+ "$$exists": true
+ - commandStartedEvent:
+ command:
+ distinct: collection0
+ readConcern:
+ level: snapshot
+ atClusterTime:
+ "$$exists": true
\ No newline at end of file
From 9270a5ffd706bd88ef171b2dfeb4eb982878ea66 Mon Sep 17 00:00:00 2001
From: Ferdinando Papale <4850119+papafe@users.noreply.github.com>
Date: Thu, 25 Sep 2025 11:10:13 +0200
Subject: [PATCH 15/15] Corrected tests
---
specifications/sessions/tests/snapshot-sessions.json | 8 ++++----
specifications/sessions/tests/snapshot-sessions.yml | 10 ++++------
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/specifications/sessions/tests/snapshot-sessions.json b/specifications/sessions/tests/snapshot-sessions.json
index a831852e71e..8f806ea7595 100644
--- a/specifications/sessions/tests/snapshot-sessions.json
+++ b/specifications/sessions/tests/snapshot-sessions.json
@@ -1714,7 +1714,7 @@
}
}
],
- "session": "session0"
+ "session": "session2"
},
"expectResult": [
{
@@ -1729,7 +1729,7 @@
"arguments": {
"fieldName": "x",
"filter": {},
- "session": "session0"
+ "session": "session2"
},
"expectResult": [
11
@@ -1770,7 +1770,7 @@
"readConcern": {
"level": "snapshot",
"atClusterTime": {
- "$$exists": true
+ "$$matchesEntity": "savedSnapshotTime"
}
}
}
@@ -1783,7 +1783,7 @@
"readConcern": {
"level": "snapshot",
"atClusterTime": {
- "$$exists": true
+ "$$matchesEntity": "savedSnapshotTime"
}
}
}
diff --git a/specifications/sessions/tests/snapshot-sessions.yml b/specifications/sessions/tests/snapshot-sessions.yml
index 15ec3fa047c..48cf415b4aa 100644
--- a/specifications/sessions/tests/snapshot-sessions.yml
+++ b/specifications/sessions/tests/snapshot-sessions.yml
@@ -851,7 +851,7 @@ tests:
pipeline:
- "$match":
_id: 1
- session: session0
+ session: session2
expectResult:
- { _id: 1, x: 11 }
- name: distinct
@@ -859,7 +859,7 @@ tests:
arguments:
fieldName: x
filter: {}
- session: session0
+ session: session2
expectResult: [ 11 ]
expectEvents:
- client: client0
@@ -881,12 +881,10 @@ tests:
aggregate: collection0
readConcern:
level: snapshot
- atClusterTime:
- "$$exists": true
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
- commandStartedEvent:
command:
distinct: collection0
readConcern:
level: snapshot
- atClusterTime:
- "$$exists": true
\ No newline at end of file
+ atClusterTime: { $$matchesEntity: *savedSnapshotTime }
\ No newline at end of file