-
Notifications
You must be signed in to change notification settings - Fork 920
GODRIVER-3663 Expose atClusterTime parameter in snapshot sessions #2271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 7 commits
20b8ae2
718b6e1
2b86427
b510475
05bedd2
268366b
a4b00c5
956bb6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -169,51 +169,62 @@ func (t *T) Run(name string, callback func(mt *T)) { | |
| t.RunOpts(name, NewOptions(), callback) | ||
| } | ||
|
|
||
| // RunOpts creates a new T instance for a sub-test with the given options. If the current environment does not satisfy | ||
| // constraints specified in the options, the new sub-test will be skipped automatically. If the test is not skipped, | ||
| // the callback will be run with the new T instance. RunOpts creates a new collection with the given name which is | ||
| // available to the callback through the T.Coll variable and is dropped after the callback returns. | ||
| func (t *T) RunOpts(name string, opts *Options, callback func(mt *T)) { | ||
| t.T.Run(name, func(wrapped *testing.T) { | ||
| sub := newT(wrapped, t.baseOpts, opts) | ||
| // Setup initializes the test client and collection for this T instance. This is | ||
| // automatically called by RunOpts but can be called manually when using New() | ||
| // directly. | ||
| func (t *T) Setup() { | ||
| // add any mock responses for this test | ||
| if t.clientType == Mock && len(t.mockResponses) > 0 { | ||
| t.AddMockResponses(t.mockResponses...) | ||
| } | ||
|
|
||
| // add any mock responses for this test | ||
| if sub.clientType == Mock && len(sub.mockResponses) > 0 { | ||
| sub.AddMockResponses(sub.mockResponses...) | ||
| } | ||
| if t.createClient == nil || *t.createClient { | ||
| t.createTestClient() | ||
| } | ||
|
|
||
| if sub.createClient == nil || *sub.createClient { | ||
| sub.createTestClient() | ||
| } | ||
| // create a collection for this test | ||
| if t.Client != nil { | ||
| t.createTestCollection() | ||
| } | ||
|
|
||
| // create a collection for this test | ||
| if sub.Client != nil { | ||
| sub.createTestCollection() | ||
| } | ||
| // clear any events that may have happened during setup | ||
| t.ClearEvents() | ||
| } | ||
|
|
||
| // defer dropping all collections if the test is using a client | ||
| defer func() { | ||
| if sub.Client == nil { | ||
| return | ||
| } | ||
| // Teardown cleans up test resources and asserts that all sessions and | ||
| // connections are closed. When using New() directly, this should be called via | ||
| // defer after Setup(). | ||
| func (t *T) Teardown() { | ||
| if t.Client == nil { | ||
| return | ||
| } | ||
|
|
||
| // store number of sessions and connections checked out here but assert that they're equal to 0 after | ||
| // cleaning up test resources to make sure resources are always cleared | ||
| sessions := sub.Client.NumberSessionsInProgress() | ||
| conns := sub.NumberConnectionsCheckedOut() | ||
| // store number of sessions and connections checked out here but assert that they're equal to 0 after | ||
| // cleaning up test resources to make sure resources are always cleared | ||
| sessions := t.Client.NumberSessionsInProgress() | ||
| conns := t.NumberConnectionsCheckedOut() | ||
|
|
||
| if sub.clientType != Mock { | ||
| sub.ClearFailPoints() | ||
| sub.ClearCollections() | ||
| } | ||
| if t.clientType != Mock { | ||
| t.ClearFailPoints() | ||
| t.ClearCollections() | ||
| } | ||
|
|
||
| _ = sub.Client.Disconnect(context.Background()) | ||
| assert.Equal(sub, 0, sessions, "%v sessions checked out", sessions) | ||
| assert.Equal(sub, 0, conns, "%v connections checked out", conns) | ||
| }() | ||
| _ = t.Client.Disconnect(context.Background()) | ||
| assert.Equal(t, 0, sessions, "%v sessions checked out", sessions) | ||
| assert.Equal(t, 0, conns, "%v connections checked out", conns) | ||
| } | ||
|
|
||
| // clear any events that may have happened during setup and run the test | ||
| sub.ClearEvents() | ||
| // RunOpts creates a new T instance for a sub-test with the given options. If | ||
| // the current environment does not satisfy constraints specified in the | ||
| // options, the new sub-test will be skipped automatically. If the test is not | ||
| // skipped, the callback will be run with the new T instance. RunOpts creates a | ||
| // new collection with the given name which is available to the callback through | ||
| // the T.Coll variable and is dropped after the callback returns. | ||
| func (t *T) RunOpts(name string, opts *Options, callback func(mt *T)) { | ||
| t.T.Run(name, func(wrapped *testing.T) { | ||
| sub := newT(wrapped, t.baseOpts, opts) | ||
| sub.Setup() | ||
| defer sub.Teardown() | ||
|
||
| callback(sub) | ||
| }) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -508,7 +508,6 @@ func TestSessionsProse(t *testing.T) { | |
|
|
||
| limitedSessMsg := "expected session count to be less than the number of operations: %v" | ||
| assert.True(mt, limitedSessionUse, limitedSessMsg, len(ops)) | ||
|
|
||
| }) | ||
prestonvasquez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| mt.ResetClient(options.Client()) | ||
|
|
@@ -584,6 +583,81 @@ func TestSessionsProse(t *testing.T) { | |
| }) | ||
| } | ||
|
|
||
| func TestSessionsProse_21_SettingSnapshotTimeWithoutSnapshot(t *testing.T) { | ||
| // 21. Having snapshotTime set and snapshot set to false is not allowed. | ||
| mtOpts := mtest. | ||
| NewOptions(). | ||
| MinServerVersion("5.0"). | ||
| Topologies(mtest.ReplicaSet, mtest.Sharded) | ||
|
|
||
| mt := mtest.New(t, mtOpts) | ||
|
|
||
| mt.Setup() | ||
|
Comment on lines
+593
to
+595
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: Consider combining these two calls into a new function to make it easier to use, like E.g. func TestBlah(...) {
mt := mtest.Setup(t, mtOpts)
// ...
}package mtest
func Setup(...) *T {
mt := mtest.New(...)
mt.setup()
// ...
return mt
}
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest deferring to GODRIVER-3721 / GODRIVER-3656, which should end up removing Setup entirely.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. Consider this resolved. |
||
| defer mt.Teardown() | ||
|
|
||
| // Start a session by calling startSession with snapshot = false and | ||
| // snapshotTime = new Timestamp(1). | ||
| sessOpts := options.Session().SetSnapshot(false).SetSnapshotTime(bson.Timestamp{T: 1}) | ||
|
|
||
| _, err := mt.Client.StartSession(sessOpts) | ||
| require.Error(t, err) | ||
| require.Contains(t, err.Error(), "snapshotTime cannot be set when snapshot is false") | ||
| } | ||
|
|
||
| func TestSessionsProse_22_SnapshotTimeGetterReturnsErrorForNonSnapshotSessions(t *testing.T) { | ||
| // 22. Retrieving `snapshotTime` on a non-snapshot session raises an error | ||
| t.Skip("Skipping test for prose 22; Go driver does not have a getter that raises an error.") | ||
| } | ||
prestonvasquez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| func TestSessionsProse_23_EnsureSnapshotTimeIsImmutable(t *testing.T) { | ||
| // 23. Ensure `snapshotTime` is Read-Only | ||
|
|
||
| mtOpts := mtest. | ||
| NewOptions(). | ||
| MinServerVersion("5.0"). | ||
| Topologies(mtest.ReplicaSet, mtest.Sharded) | ||
|
|
||
| mt := mtest.New(t, mtOpts) | ||
|
|
||
| mt.Run("multiple ClientSession calls isolation", func(mt *mtest.T) { | ||
| sess, err := mt.Client.StartSession(options.Session().SetSnapshot(false)) | ||
prestonvasquez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| require.NoError(mt, err) | ||
| defer sess.EndSession(context.Background()) | ||
|
|
||
| // Verify initial state | ||
| require.Empty(mt, sess.ClientSession().SnapshotTime) | ||
prestonvasquez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Attempt mutation through one ClientSession() call | ||
| client1 := sess.ClientSession() | ||
| client1.SnapshotTime = bson.Timestamp{T: 1} | ||
|
|
||
| // Second ClientSession() call should return independent copy | ||
| require.Empty(mt, sess.ClientSession().SnapshotTime) | ||
| }) | ||
|
|
||
| mt.Run("snapshotTime copy is immutable", func(mt *mtest.T) { | ||
| originalTS := bson.Timestamp{T: 100, I: 5} | ||
| sess, err := mt.Client.StartSession( | ||
| options.Session().SetSnapshot(true).SetSnapshotTime(originalTS), | ||
| ) | ||
| require.NoError(mt, err) | ||
| defer sess.EndSession(context.Background()) | ||
|
|
||
| // Verify initial state | ||
| cs := sess.ClientSession() | ||
| require.True(mt, cs.SnapshotTimeSet) | ||
| require.Equal(mt, originalTS, cs.SnapshotTime) | ||
|
|
||
| // Mutate the copy and verify it doesn't affect the session. | ||
| cs.SnapshotTime = bson.Timestamp{T: 999, I: 888} | ||
| cs.SnapshotTimeSet = false | ||
|
|
||
| cs2 := sess.ClientSession() | ||
| require.True(mt, cs2.SnapshotTimeSet) | ||
| require.Equal(mt, originalTS, cs2.SnapshotTime) | ||
| }) | ||
| } | ||
|
|
||
| type sessionFunction struct { | ||
| name string | ||
| target string | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't possible now.