...

Source file src/go.mongodb.org/mongo-driver/mongo/integration/mtest/options.go

Documentation: go.mongodb.org/mongo-driver/mongo/integration/mtest

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package mtest
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  
    13  	"go.mongodb.org/mongo-driver/bson"
    14  	"go.mongodb.org/mongo-driver/mongo/options"
    15  )
    16  
    17  // TopologyKind describes the topology that a test is run on.
    18  type TopologyKind string
    19  
    20  // These constants specify valid values for TopologyKind
    21  const (
    22  	ReplicaSet   TopologyKind = "replicaset"
    23  	Sharded      TopologyKind = "sharded"
    24  	Single       TopologyKind = "single"
    25  	LoadBalanced TopologyKind = "load-balanced"
    26  	// ShardedReplicaSet is a special case of sharded that requires each shard to be a replica set rather than a
    27  	// standalone server.
    28  	ShardedReplicaSet TopologyKind = "sharded-replicaset"
    29  )
    30  
    31  // ClientType specifies the type of Client that should be created for a test.
    32  type ClientType int
    33  
    34  // These constants specify valid values for ClientType
    35  const (
    36  	// Default specifies a client to the connection string in the MONGODB_URI env variable with command monitoring
    37  	// enabled.
    38  	Default ClientType = iota
    39  	// Pinned specifies a client that is pinned to a single mongos in a sharded cluster.
    40  	Pinned
    41  	// Mock specifies a client that communicates with a mock deployment.
    42  	Mock
    43  	// Proxy specifies a client that proxies messages to the server and also stores parsed copies. The proxied
    44  	// messages can be retrieved via T.GetProxiedMessages or T.GetRawProxiedMessages.
    45  	Proxy
    46  )
    47  
    48  var (
    49  	falseBool = false
    50  )
    51  
    52  // RunOnBlock describes a constraint for a test.
    53  type RunOnBlock struct {
    54  	MinServerVersion string                   `bson:"minServerVersion"`
    55  	MaxServerVersion string                   `bson:"maxServerVersion"`
    56  	Topology         []TopologyKind           `bson:"topology"`
    57  	Serverless       string                   `bson:"serverless"`
    58  	ServerParameters map[string]bson.RawValue `bson:"serverParameters"`
    59  	Auth             *bool                    `bson:"auth"`
    60  	AuthEnabled      *bool                    `bson:"authEnabled"`
    61  	CSFLE            *bool                    `bson:"csfle"`
    62  }
    63  
    64  // UnmarshalBSON implements custom BSON unmarshalling behavior for RunOnBlock because some test formats use the
    65  // "topology" key while the unified test format uses "topologies".
    66  func (r *RunOnBlock) UnmarshalBSON(data []byte) error {
    67  	var temp struct {
    68  		MinServerVersion string                   `bson:"minServerVersion"`
    69  		MaxServerVersion string                   `bson:"maxServerVersion"`
    70  		Topology         []TopologyKind           `bson:"topology"`
    71  		Topologies       []TopologyKind           `bson:"topologies"`
    72  		Serverless       string                   `bson:"serverless"`
    73  		ServerParameters map[string]bson.RawValue `bson:"serverParameters"`
    74  		Auth             *bool                    `bson:"auth"`
    75  		AuthEnabled      *bool                    `bson:"authEnabled"`
    76  		CSFLE            *bool                    `bson:"csfle"`
    77  		Extra            map[string]interface{}   `bson:",inline"`
    78  	}
    79  	if err := bson.Unmarshal(data, &temp); err != nil {
    80  		return fmt.Errorf("error unmarshalling to temporary RunOnBlock object: %w", err)
    81  	}
    82  	if len(temp.Extra) > 0 {
    83  		return fmt.Errorf("unrecognized fields for RunOnBlock: %v", temp.Extra)
    84  	}
    85  
    86  	r.MinServerVersion = temp.MinServerVersion
    87  	r.MaxServerVersion = temp.MaxServerVersion
    88  	r.Serverless = temp.Serverless
    89  	r.ServerParameters = temp.ServerParameters
    90  	r.Auth = temp.Auth
    91  	r.AuthEnabled = temp.AuthEnabled
    92  	r.CSFLE = temp.CSFLE
    93  
    94  	if temp.Topology != nil {
    95  		r.Topology = temp.Topology
    96  	}
    97  	if temp.Topologies != nil {
    98  		if r.Topology != nil {
    99  			return errors.New("both 'topology' and 'topologies' keys cannot be specified for a RunOnBlock")
   100  		}
   101  
   102  		r.Topology = temp.Topologies
   103  	}
   104  	return nil
   105  }
   106  
   107  // optionFunc is a function type that configures a T instance.
   108  type optionFunc func(*T)
   109  
   110  // Options is the type used to configure a new T instance.
   111  type Options struct {
   112  	optFuncs []optionFunc
   113  }
   114  
   115  // NewOptions creates an empty Options instance.
   116  func NewOptions() *Options {
   117  	return &Options{}
   118  }
   119  
   120  // CollectionCreateOptions sets the options to pass to Database.CreateCollection() when creating a collection for a test.
   121  func (op *Options) CollectionCreateOptions(opts *options.CreateCollectionOptions) *Options {
   122  	op.optFuncs = append(op.optFuncs, func(t *T) {
   123  		t.collCreateOpts = opts
   124  	})
   125  	return op
   126  }
   127  
   128  // CollectionOptions sets the options to use when creating a collection for a test.
   129  func (op *Options) CollectionOptions(opts *options.CollectionOptions) *Options {
   130  	op.optFuncs = append(op.optFuncs, func(t *T) {
   131  		t.collOpts = opts
   132  	})
   133  	return op
   134  }
   135  
   136  // ClientOptions sets the options to use when creating a client for a test.
   137  func (op *Options) ClientOptions(opts *options.ClientOptions) *Options {
   138  	op.optFuncs = append(op.optFuncs, func(t *T) {
   139  		t.clientOpts = opts
   140  	})
   141  	return op
   142  }
   143  
   144  // CreateClient specifies whether or not a client should be created for a test. This should be set to false when running
   145  // a test that only runs other tests.
   146  func (op *Options) CreateClient(create bool) *Options {
   147  	op.optFuncs = append(op.optFuncs, func(t *T) {
   148  		t.createClient = &create
   149  	})
   150  	return op
   151  }
   152  
   153  // CreateCollection specifies whether or not a collection should be created for a test. The default value is true.
   154  func (op *Options) CreateCollection(create bool) *Options {
   155  	op.optFuncs = append(op.optFuncs, func(t *T) {
   156  		t.createCollection = &create
   157  	})
   158  	return op
   159  }
   160  
   161  // ShareClient specifies whether or not a test should pass its client down to sub-tests. This should be set when calling
   162  // New() if the inheriting behavior is desired. This option must not be used if the test accesses command monitoring
   163  // events.
   164  func (op *Options) ShareClient(share bool) *Options {
   165  	op.optFuncs = append(op.optFuncs, func(t *T) {
   166  		t.shareClient = &share
   167  	})
   168  	return op
   169  }
   170  
   171  // CollectionName specifies the name for the collection for the test.
   172  func (op *Options) CollectionName(collName string) *Options {
   173  	op.optFuncs = append(op.optFuncs, func(t *T) {
   174  		t.collName = collName
   175  	})
   176  	return op
   177  }
   178  
   179  // DatabaseName specifies the name of the database for the test.
   180  func (op *Options) DatabaseName(dbName string) *Options {
   181  	op.optFuncs = append(op.optFuncs, func(t *T) {
   182  		t.dbName = dbName
   183  	})
   184  	return op
   185  }
   186  
   187  // ClientType specifies the type of client that should be created for a test. This option will be propagated to all
   188  // sub-tests. If the provided ClientType is Proxy, the SSL(false) option will be also be added because the internal
   189  // proxy dialer and connection types do not support SSL.
   190  func (op *Options) ClientType(ct ClientType) *Options {
   191  	op.optFuncs = append(op.optFuncs, func(t *T) {
   192  		t.clientType = ct
   193  
   194  		if ct == Proxy {
   195  			t.ssl = &falseBool
   196  		}
   197  	})
   198  	return op
   199  }
   200  
   201  // MockResponses specifies the responses returned by a mock deployment. This should only be used if the current test
   202  // is being run with MockDeployment(true). Responses can also be added after a sub-test has already been created.
   203  func (op *Options) MockResponses(responses ...bson.D) *Options {
   204  	op.optFuncs = append(op.optFuncs, func(t *T) {
   205  		t.mockResponses = responses
   206  	})
   207  	return op
   208  }
   209  
   210  // RunOn specifies run-on blocks used to determine if a test should run. If a test's environment meets at least one of the
   211  // given constraints, it will be run. Otherwise, it will be skipped.
   212  func (op *Options) RunOn(blocks ...RunOnBlock) *Options {
   213  	op.optFuncs = append(op.optFuncs, func(t *T) {
   214  		t.runOn = append(t.runOn, blocks...)
   215  	})
   216  	return op
   217  }
   218  
   219  // MinServerVersion specifies the minimum server version for the test.
   220  func (op *Options) MinServerVersion(version string) *Options {
   221  	op.optFuncs = append(op.optFuncs, func(t *T) {
   222  		t.minServerVersion = version
   223  	})
   224  	return op
   225  }
   226  
   227  // MaxServerVersion specifies the maximum server version for the test.
   228  func (op *Options) MaxServerVersion(version string) *Options {
   229  	op.optFuncs = append(op.optFuncs, func(t *T) {
   230  		t.maxServerVersion = version
   231  	})
   232  	return op
   233  }
   234  
   235  // Topologies specifies a list of topologies that the test can run on.
   236  func (op *Options) Topologies(topos ...TopologyKind) *Options {
   237  	op.optFuncs = append(op.optFuncs, func(t *T) {
   238  		t.validTopologies = topos
   239  	})
   240  	return op
   241  }
   242  
   243  // Auth specifies whether or not auth should be enabled for this test to run. By default, a test will run regardless
   244  // of whether or not auth is enabled.
   245  func (op *Options) Auth(auth bool) *Options {
   246  	op.optFuncs = append(op.optFuncs, func(t *T) {
   247  		t.auth = &auth
   248  	})
   249  	return op
   250  }
   251  
   252  // SSL specifies whether or not SSL should be enabled for this test to run. By default, a test will run regardless
   253  // of whether or not SSL is enabled.
   254  func (op *Options) SSL(ssl bool) *Options {
   255  	op.optFuncs = append(op.optFuncs, func(t *T) {
   256  		t.ssl = &ssl
   257  	})
   258  	return op
   259  }
   260  
   261  // Enterprise specifies whether or not this test should only be run on enterprise server variants. Defaults to false.
   262  func (op *Options) Enterprise(ent bool) *Options {
   263  	op.optFuncs = append(op.optFuncs, func(t *T) {
   264  		t.enterprise = &ent
   265  	})
   266  	return op
   267  }
   268  
   269  // AtlasDataLake specifies whether this test should only be run against Atlas Data Lake servers. Defaults to false.
   270  func (op *Options) AtlasDataLake(adl bool) *Options {
   271  	op.optFuncs = append(op.optFuncs, func(t *T) {
   272  		t.dataLake = &adl
   273  	})
   274  	return op
   275  }
   276  
   277  // RequireAPIVersion specifies whether this test should only be run when REQUIRE_API_VERSION is true. Defaults to false.
   278  func (op *Options) RequireAPIVersion(rav bool) *Options {
   279  	op.optFuncs = append(op.optFuncs, func(t *T) {
   280  		t.requireAPIVersion = &rav
   281  	})
   282  	return op
   283  }
   284  

View as plain text