Skip to content
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

GODRIVER-2696 Use an options pattern that doesn't require merging structs #1570

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3276282
Update InsertOneOptions.
qingyang-hu Nov 27, 2023
7b6858d
Update FindOptions.
qingyang-hu Nov 27, 2023
7ac2261
Add a generic merging function.
qingyang-hu Dec 27, 2023
6605798
Merge branch 'master' into godriver2696POC
qingyang-hu Dec 28, 2023
0608e50
Merge InsertOneArgs by the generic function.
qingyang-hu Dec 28, 2023
b20327f
Move `Options` to `mongo`.
qingyang-hu Jan 8, 2024
dbbc305
WIP
qingyang-hu Jan 10, 2024
ff03ed5
Merge branch 'master' into godriver2696POC
qingyang-hu Jan 11, 2024
f311172
GODRIVER-2696 Resolve mege conflicts
prestonvasquez Feb 23, 2024
0325efb
GODRIVER-2696 Update Aggregate and BulkWrite
prestonvasquez Feb 28, 2024
a71f378
GODRIVER-2696 Update clientoptions
prestonvasquez Mar 8, 2024
a50e6ee
GODRIVER-2696 Check for nil args in GetURI
prestonvasquez Mar 8, 2024
3d506f0
GODRIVER-2696 Update collection/createCollection/count
prestonvasquez Mar 12, 2024
f53f8d0
GODRIVER-2696 Update up to gridfs
prestonvasquez Mar 13, 2024
0a9fbc6
GODRIVER-2696 Finish converting options
prestonvasquez Mar 14, 2024
faebbbc
Merge branch 'master' into GODRIVER-2696
prestonvasquez Mar 14, 2024
760bc3e
GODRIVER-2696 Clean up comments and add mongoutil tests
prestonvasquez Mar 15, 2024
6e87836
Merge branch 'GODRIVER-2696' of github.com:prestonvasquez/mongo-go-dr…
prestonvasquez Mar 15, 2024
937c941
Merge branch 'master' into GODRIVER-2696
prestonvasquez Mar 19, 2024
b81dbc0
Merge branch 'master' into GODRIVER-2696
prestonvasquez Apr 15, 2024
1edea67
GODRIVER-2696 Fix typos
prestonvasquez Apr 15, 2024
d6497aa
GODRIVER-2696 Resolve merge conflicts
prestonvasquez May 8, 2024
c94c4e6
GODRIVER-2696 Resolve PR issues
prestonvasquez May 9, 2024
49e44f8
GODRIER-2696 Use default revision for skip num
prestonvasquez May 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 11 additions & 1 deletion internal/cmd/testatlas/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/internal/handshake"
"go.mongodb.org/mongo-driver/internal/mongoutil"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
Expand All @@ -39,9 +40,18 @@ func main() {
panic(fmt.Sprintf("error running test with TLS at index %d: %v", idx, err))
}

args, err := mongoutil.NewArgsFromOptions[options.ClientArgs](clientOpts)
if err != nil {
panic(fmt.Sprintf("failed to construct args from options: %v", err))
}

tlsConfigSkipVerify := args.TLSConfig
tlsConfigSkipVerify.InsecureSkipVerify = true

// Run the connectivity test with InsecureSkipVerify to ensure SNI is done correctly even if verification is
// disabled.
clientOpts.TLSConfig.InsecureSkipVerify = true
clientOpts.SetTLSConfig(tlsConfigSkipVerify)

if err := runTest(ctx, clientOpts); err != nil {
panic(fmt.Sprintf("error running test with tlsInsecure at index %d: %v", idx, err))
}
Expand Down
89 changes: 40 additions & 49 deletions internal/integration/client_side_encryption_prose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2469,7 +2469,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
typeStr string
field string
typeBson bsontype.Type
rangeOpts options.RangeOptions
rangeOpts *options.RangeOptions
zero bson.RawValue
six bson.RawValue
thirty bson.RawValue
Expand All @@ -2492,12 +2492,10 @@ func TestClientSideEncryptionProse(t *testing.T) {

tests := []testcase{
{
typeStr: "DecimalNoPrecision",
field: "encryptedDecimalNoPrecision",
typeBson: bson.TypeDecimal128,
rangeOpts: options.RangeOptions{
Sparsity: 1,
},
typeStr: "DecimalNoPrecision",
field: "encryptedDecimalNoPrecision",
typeBson: bson.TypeDecimal128,
rangeOpts: options.Range().SetSparsity(1),
zero: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_0)},
six: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_6)},
thirty: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_30)},
Expand All @@ -2508,25 +2506,22 @@ func TestClientSideEncryptionProse(t *testing.T) {
typeStr: "DecimalPrecision",
field: "encryptedDecimalPrecision",
typeBson: bson.TypeDecimal128,
rangeOpts: options.RangeOptions{
Min: &bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_0)},
Max: &bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_200)},
Sparsity: 1,
Precision: &precision,
},
rangeOpts: options.Range().
SetMin(bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_0)}).
SetMax(bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_200)}).
SetSparsity(1).
SetPrecision(precision),
zero: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_0)},
six: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_6)},
thirty: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_30)},
twoHundred: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_200)},
twoHundredOne: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_201)},
},
{
typeStr: "DoubleNoPrecision",
field: "encryptedDoubleNoPrecision",
typeBson: bson.TypeDouble,
rangeOpts: options.RangeOptions{
Sparsity: 1,
},
typeStr: "DoubleNoPrecision",
field: "encryptedDoubleNoPrecision",
typeBson: bson.TypeDouble,
rangeOpts: options.Range().SetSparsity(1),
zero: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 0)},
six: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 6)},
thirty: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 30)},
Expand All @@ -2537,12 +2532,11 @@ func TestClientSideEncryptionProse(t *testing.T) {
typeStr: "DoublePrecision",
field: "encryptedDoublePrecision",
typeBson: bson.TypeDouble,
rangeOpts: options.RangeOptions{
Min: &bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 0)},
Max: &bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 200)},
Sparsity: 1,
Precision: &precision,
},
rangeOpts: options.Range().
SetMin(bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 0)}).
SetMax(bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 200)}).
SetSparsity(1).
SetPrecision(precision),
zero: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 0)},
six: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 6)},
thirty: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 30)},
Expand All @@ -2553,11 +2547,10 @@ func TestClientSideEncryptionProse(t *testing.T) {
typeStr: "Date",
field: "encryptedDate",
typeBson: bson.TypeDateTime,
rangeOpts: options.RangeOptions{
Min: &bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 0)},
Max: &bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 200)},
Sparsity: 1,
},
rangeOpts: options.Range().
SetMin(bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 0)}).
SetMax(bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 200)}).
SetSparsity(1),
zero: bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 0)},
six: bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 6)},
thirty: bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 30)},
Expand All @@ -2568,11 +2561,10 @@ func TestClientSideEncryptionProse(t *testing.T) {
typeStr: "Int",
field: "encryptedInt",
typeBson: bson.TypeInt32,
rangeOpts: options.RangeOptions{
Min: &bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 0)},
Max: &bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 200)},
Sparsity: 1,
},
rangeOpts: options.Range().
SetMin(bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 0)}).
SetMax(bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 200)}).
SetSparsity(1),
zero: bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 0)},
six: bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 6)},
thirty: bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 30)},
Expand All @@ -2583,11 +2575,10 @@ func TestClientSideEncryptionProse(t *testing.T) {
typeStr: "Long",
field: "encryptedLong",
typeBson: bson.TypeInt64,
rangeOpts: options.RangeOptions{
Min: &bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 0)},
Max: &bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 200)},
Sparsity: 1,
},
rangeOpts: options.Range().
SetMin(bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 0)}).
SetMax(bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 200)}).
SetSparsity(1),
zero: bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 0)},
six: bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 6)},
thirty: bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 30)},
Expand Down Expand Up @@ -2645,7 +2636,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetAlgorithm("RangePreview").
SetKeyID(key1ID).
SetContentionFactor(0).
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options.Range() returns a *RangeOptions, but SetRangeOptions expects a RangeOptions. That creates an awkward mismatch where users will have to immediately dereference pointers to use them.

For example, the current code requires:

options.Encrypt().SetRangeOptions(*options.Range())

but we should make the following work:

options.Encrypt().SetRangeOptions(options.Range())

Either by changing SetRangeOptions to take a *RangeOptions or making options.Range() return a RangeOptions.

// Insert 0.
insertPayloadZero, err := clientEncryption.Encrypt(context.Background(), test.zero, eo)
assert.Nil(mt, err, "error in Encrypt: %v", err)
Expand Down Expand Up @@ -2692,7 +2683,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetAlgorithm("RangePreview").
SetKeyID(key1ID).
SetContentionFactor(0).
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)
insertPayloadSix, err := clientEncryption.Encrypt(context.Background(), test.six, eo)
assert.Nil(mt, err, "error in Encrypt: %v", err)
got, err := clientEncryption.Decrypt(context.Background(), insertPayloadSix)
Expand All @@ -2709,7 +2700,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetKeyID(key1ID).
SetContentionFactor(0).
SetQueryType("rangePreview").
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)

expr := bson.M{
"$and": bson.A{
Expand Down Expand Up @@ -2751,7 +2742,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetKeyID(key1ID).
SetContentionFactor(0).
SetQueryType("rangePreview").
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)

expr := bson.M{
"$and": bson.A{
Expand Down Expand Up @@ -2793,7 +2784,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetKeyID(key1ID).
SetContentionFactor(0).
SetQueryType("rangePreview").
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)

expr := bson.M{
"$and": bson.A{
Expand Down Expand Up @@ -2830,7 +2821,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetKeyID(key1ID).
SetContentionFactor(0).
SetQueryType("rangePreview").
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)

expr := bson.M{
"$and": bson.A{
Expand Down Expand Up @@ -2868,7 +2859,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetAlgorithm("RangePreview").
SetKeyID(key1ID).
SetContentionFactor(0).
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)

_, err := clientEncryption.Encrypt(context.Background(), test.twoHundredOne, eo)
assert.NotNil(mt, err, "expected error, but got none")
Expand All @@ -2882,7 +2873,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetAlgorithm("RangePreview").
SetKeyID(key1ID).
SetContentionFactor(0).
SetRangeOptions(test.rangeOpts)
SetRangeOptions(*test.rangeOpts)

var val bson.RawValue
if test.field == "encryptedInt" {
Expand All @@ -2909,7 +2900,7 @@ func TestClientSideEncryptionProse(t *testing.T) {
SetAlgorithm("RangePreview").
SetKeyID(key1ID).
SetContentionFactor(0).
SetRangeOptions(ro)
SetRangeOptions(*ro)

_, err := clientEncryption.Encrypt(context.Background(), test.six, eo)
assert.NotNil(mt, err, "expected error, but got none")
Expand Down
6 changes: 5 additions & 1 deletion internal/integration/client_side_encryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,11 @@ func TestClientSideEncryptionCustomCrypt(t *testing.T) {
ApplyURI(mtest.ClusterURI()).
SetAutoEncryptionOptions(aeOpts)
cc := &customCrypt{}
clientOpts.Crypt = cc
clientOpts.Opts = append(clientOpts.Opts, func(args *options.ClientArgs) error {
args.Crypt = cc

return nil
})
integtest.AddTestServerAPIVersion(clientOpts)

client, err := mongo.Connect(clientOpts)
Expand Down
8 changes: 4 additions & 4 deletions internal/integration/collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,22 +81,22 @@ func TestCollection(t *testing.T) {
mt.RunOpts("options are converted", convertedOptsOpts, func(mt *mtest.T) {
nilOptsTestCases := []struct {
name string
opts []*options.InsertOneOptions
opts []mongo.Options[options.InsertOneArgs]
expectOptionSet bool
}{
{
"only nil is passed",
[]*options.InsertOneOptions{nil},
[]mongo.Options[options.InsertOneArgs]{nil},
false,
},
{
"non-nil options is passed before nil",
[]*options.InsertOneOptions{options.InsertOne().SetBypassDocumentValidation(true), nil},
[]mongo.Options[options.InsertOneArgs]{options.InsertOne().SetBypassDocumentValidation(true), nil},
true,
},
{
"non-nil options is passed after nil",
[]*options.InsertOneOptions{nil, options.InsertOne().SetBypassDocumentValidation(true)},
[]mongo.Options[options.InsertOneArgs]{nil, options.InsertOne().SetBypassDocumentValidation(true)},
true,
},
}
Expand Down
38 changes: 31 additions & 7 deletions internal/integration/crud_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"go.mongodb.org/mongo-driver/internal/integration/mtest"
"go.mongodb.org/mongo-driver/internal/integration/unified"
"go.mongodb.org/mongo-driver/internal/integtest"
"go.mongodb.org/mongo-driver/internal/mongoutil"
"go.mongodb.org/mongo-driver/internal/require"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
Expand Down Expand Up @@ -132,7 +134,12 @@ func runCommandOnAllServers(commandFn func(client *mongo.Client) error) error {
return commandFn(client)
}

for _, host := range opts.Hosts {
hosts, err := mongoutil.HostsFromURI(mtest.ClusterURI())
if err != nil {
return fmt.Errorf("failed to construct arguments from options: %v", err)
}

for _, host := range hosts {
shardClient, err := mongo.Connect(opts.SetHosts([]string{host}))
if err != nil {
return fmt.Errorf("error creating client for mongos %v: %w", host, err)
Expand All @@ -150,12 +157,12 @@ func runCommandOnAllServers(commandFn func(client *mongo.Client) error) error {

// aggregator is an interface used to run collection and database-level aggregations
type aggregator interface {
Aggregate(context.Context, interface{}, ...*options.AggregateOptions) (*mongo.Cursor, error)
Aggregate(context.Context, interface{}, ...mongo.Options[options.AggregateArgs]) (*mongo.Cursor, error)
}

// watcher is an interface used to create client, db, and collection-level change streams
type watcher interface {
Watch(context.Context, interface{}, ...*options.ChangeStreamOptions) (*mongo.ChangeStream, error)
Watch(context.Context, interface{}, ...mongo.Options[options.ChangeStreamArgs]) (*mongo.ChangeStream, error)
}

func executeAggregate(mt *mtest.T, agg aggregator, sess mongo.Session, args bson.Raw) (*mongo.Cursor, error) {
Expand Down Expand Up @@ -894,7 +901,11 @@ func executeUpdateOne(mt *mtest.T, sess mongo.Session, args bson.Raw) (*mongo.Up
mt.Fatalf("unrecognized updateOne option: %v", key)
}
}
if opts.Upsert == nil {

updateArgs, err := mongoutil.NewArgsFromOptions[options.UpdateArgs](opts)
require.NoError(mt, err, "failed to construct arguments from options")

if updateArgs.Upsert == nil {
opts = opts.SetUpsert(false)
}

Expand Down Expand Up @@ -942,7 +953,11 @@ func executeUpdateMany(mt *mtest.T, sess mongo.Session, args bson.Raw) (*mongo.U
mt.Fatalf("unrecognized updateMany option: %v", key)
}
}
if opts.Upsert == nil {

updateArgs, err := mongoutil.NewArgsFromOptions[options.UpdateArgs](opts)
require.NoError(mt, err, "failed to construct arguments from options")

if updateArgs.Upsert == nil {
opts = opts.SetUpsert(false)
}

Expand Down Expand Up @@ -986,7 +1001,11 @@ func executeReplaceOne(mt *mtest.T, sess mongo.Session, args bson.Raw) (*mongo.U
mt.Fatalf("unrecognized replaceOne option: %v", key)
}
}
if opts.Upsert == nil {

updateArgs, err := mongoutil.NewArgsFromOptions[options.ReplaceArgs](opts)
require.NoError(mt, err, "failed to construct arguments from options")

if updateArgs.Upsert == nil {
opts = opts.SetUpsert(false)
}

Expand Down Expand Up @@ -1416,7 +1435,12 @@ func executeAdminCommand(mt *mtest.T, op *operation) {
assert.Nil(mt, err, "RunCommand error for command %q: %v", op.CommandName, err)
}

func executeAdminCommandWithRetry(mt *mtest.T, client *mongo.Client, cmd interface{}, opts ...*options.RunCmdOptions) {
func executeAdminCommandWithRetry(
mt *mtest.T,
client *mongo.Client,
cmd interface{},
opts ...mongo.Options[options.RunCmdArgs],
) {
mt.Helper()

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
Expand Down