...

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

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

     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  //go:build cse
     8  // +build cse
     9  
    10  package integration
    11  
    12  import (
    13  	"context"
    14  	"crypto/tls"
    15  	"encoding/base64"
    16  	"fmt"
    17  	"io/ioutil"
    18  	"net"
    19  	"net/http"
    20  	"os"
    21  	"path/filepath"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"go.mongodb.org/mongo-driver/bson"
    27  	"go.mongodb.org/mongo-driver/bson/bsontype"
    28  	"go.mongodb.org/mongo-driver/bson/primitive"
    29  	"go.mongodb.org/mongo-driver/event"
    30  	"go.mongodb.org/mongo-driver/internal/assert"
    31  	"go.mongodb.org/mongo-driver/internal/handshake"
    32  	"go.mongodb.org/mongo-driver/internal/integtest"
    33  	"go.mongodb.org/mongo-driver/mongo"
    34  	"go.mongodb.org/mongo-driver/mongo/integration/mtest"
    35  	"go.mongodb.org/mongo-driver/mongo/options"
    36  	"go.mongodb.org/mongo-driver/mongo/writeconcern"
    37  	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
    38  	"go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt"
    39  	mongocryptopts "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options"
    40  )
    41  
    42  var (
    43  	localMasterKey = []byte("2x44+xduTaBBkY16Er5DuADaghvS4vwdkg8tpPp3tz6gV01A1CwbD9itQ2HFDgPWOp8eMaC1Oi766JzXZBdBdbdMurdonJ1d")
    44  )
    45  
    46  const (
    47  	clientEncryptionProseDir      = "../../testdata/client-side-encryption-prose"
    48  	deterministicAlgorithm        = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
    49  	randomAlgorithm               = "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
    50  	kvNamespace                   = "keyvault.datakeys" // default namespace for the key vault collection
    51  	keySubtype               byte = 4                   // expected subtype for data keys
    52  	encryptedValueSubtype    byte = 6                   // expected subtypes for encrypted values
    53  	cryptMaxBatchSizeBytes        = 2097152             // max bytes in write batch when auto encryption is enabled
    54  	maxBsonObjSize                = 16777216            // max bytes in BSON object
    55  )
    56  
    57  func containsSubstring(possibleSubstrings []string, str string) bool {
    58  	for _, possibleSubstring := range possibleSubstrings {
    59  		if strings.Contains(str, possibleSubstring) {
    60  			return true
    61  		}
    62  	}
    63  
    64  	return false
    65  }
    66  
    67  func TestClientSideEncryptionProse(t *testing.T) {
    68  	t.Parallel()
    69  
    70  	verifyClientSideEncryptionVarsSet(t)
    71  	mt := mtest.New(t, mtest.NewOptions().MinServerVersion("4.2").Enterprise(true).CreateClient(false))
    72  
    73  	defaultKvClientOptions := options.Client().ApplyURI(mtest.ClusterURI())
    74  	integtest.AddTestServerAPIVersion(defaultKvClientOptions)
    75  	fullKmsProvidersMap := map[string]map[string]interface{}{
    76  		"aws": {
    77  			"accessKeyId":     awsAccessKeyID,
    78  			"secretAccessKey": awsSecretAccessKey,
    79  		},
    80  		"azure": {
    81  			"tenantId":     azureTenantID,
    82  			"clientId":     azureClientID,
    83  			"clientSecret": azureClientSecret,
    84  		},
    85  		"gcp": {
    86  			"email":      gcpEmail,
    87  			"privateKey": gcpPrivateKey,
    88  		},
    89  		"local": {"key": localMasterKey},
    90  		"kmip": {
    91  			"endpoint": "localhost:5698",
    92  		},
    93  	}
    94  
    95  	mt.Run("1. custom key material test", func(mt *mtest.T) {
    96  		const (
    97  			dkCollection = "datakeys"
    98  			idKey        = "_id"
    99  			kvDatabase   = "keyvault"
   100  		)
   101  
   102  		// Create a ClientEncryption object (referred to as client_encryption) with client set as the keyVaultClient.
   103  		// Using client, drop the collection keyvault.datakeys.
   104  		cse := setup(mt, nil, defaultKvClientOptions, options.ClientEncryption().
   105  			SetKmsProviders(fullKmsProvidersMap).
   106  			SetKeyVaultNamespace(kvNamespace))
   107  
   108  		err := cse.kvClient.Database(kvDatabase).Collection(dkCollection).Drop(context.Background())
   109  		assert.Nil(mt, err, "error dropping %q namespace: %v", kvNamespace, err)
   110  
   111  		// Using client_encryption, create a data key with a local KMS provider and the declared b64 custom key material
   112  		// (given as base64).
   113  		const b641 = `xPTAjBRG5JiPm+d3fj6XLi2q5DMXUS/f1f+SMAlhhwkhDRL0kr8r9GDLIGTAGlvC+HVjSIgdL+RKwZCvpXSyxTICWSXT` +
   114  			`UYsWYPyu3IoHbuBZdmw2faM3WhcRIgbMReU5`
   115  
   116  		// Decode the base64-encoded keyMaterial string.
   117  		km, err := base64.StdEncoding.DecodeString(b641)
   118  		assert.Nil(mt, err, "error decoding b64: %v", err)
   119  
   120  		_, err = cse.clientEnc.CreateDataKey(context.Background(), "local", options.DataKey().SetKeyMaterial(km))
   121  		assert.Nil(mt, err, "error creating data key: %v", err)
   122  
   123  		// Find the resulting key document in keyvault.datakeys, save a copy of the key document, then remove the key
   124  		// document from the collection.
   125  		coll := cse.kvClient.Database(kvDatabase).Collection(dkCollection)
   126  
   127  		keydoc, err := coll.FindOne(context.Background(), bson.D{}).Raw()
   128  		assert.Nil(mt, err, "error in decoding bytes: %v", err)
   129  
   130  		// Remove the key document from the collection.
   131  		id, err := keydoc.LookupErr(idKey)
   132  		assert.Nil(mt, err, "error looking up %s: %v", idKey, err)
   133  
   134  		_, err = coll.DeleteOne(context.Background(), bson.D{{idKey, id}})
   135  		assert.Nil(mt, err, "error deleting key document: %v", err)
   136  
   137  		// Replace the _id field in the copied key document with a UUID with base64 value AAAAAAAAAAAAAAAAAAAAAA== (16
   138  		// bytes all equal to 0x00) and insert the modified key document into keyvault.datakeys with majority write
   139  		// concern.
   140  		cidx, alteredKeydoc := bsoncore.AppendDocumentStart(nil)
   141  		docElems, _ := keydoc.Elements()
   142  		for _, element := range docElems {
   143  			if key := element.Key(); key != idKey {
   144  				alteredKeydoc = bsoncore.AppendValueElement(alteredKeydoc, key, rawValueToCoreValue(element.Value()))
   145  			}
   146  		}
   147  		empty := [16]byte{}
   148  		uuidSubtype, _ := keydoc.Lookup(idKey).Binary()
   149  		alteredKeydoc = bsoncore.AppendBinaryElement(alteredKeydoc, idKey, uuidSubtype, empty[:])
   150  		alteredKeydoc, _ = bsoncore.AppendDocumentEnd(alteredKeydoc, cidx)
   151  
   152  		// Insert the copied key document into keyvault.datakeys with majority write concern.
   153  		wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second))
   154  		wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority)
   155  		wcmColl := cse.kvClient.Database(kvDatabase).Collection(dkCollection, wcMajorityCollectionOpts)
   156  		_, err = wcmColl.InsertOne(context.Background(), alteredKeydoc)
   157  		assert.Nil(mt, err, "error inserting altered key document: %v", err)
   158  
   159  		// Using client_encryption, encrypt the string "test" with the modified data key using the
   160  		// AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic algorithm and assert the resulting value is equal to the
   161  		// declared b64 constant.
   162  		const b642 = `AQAAAAAAAAAAAAAAAAAAAAACz0ZOLuuhEYi807ZXTdhbqhLaS2/t9wLifJnnNYwiw79d75QYIZ6M/aYC1h9nCzCjZ7pG` +
   163  			`UpAuNnkUhnIXM3PjrA==`
   164  
   165  		empty = [16]byte{}
   166  		keyid := primitive.Binary{Subtype: 0x04, Data: empty[:]}
   167  
   168  		encOpts := options.Encrypt().SetAlgorithm(deterministicAlgorithm).SetKeyID(keyid)
   169  		testVal := bson.RawValue{
   170  			Type:  bson.TypeString,
   171  			Value: bsoncore.AppendString(nil, "test"),
   172  		}
   173  		actual, err := cse.clientEnc.Encrypt(context.Background(), testVal, encOpts)
   174  		assert.Nil(mt, err, "error encrypting data: %v", err)
   175  
   176  		expected := primitive.Binary{Subtype: 0x06}
   177  		expected.Data, _ = base64.StdEncoding.DecodeString(b642)
   178  
   179  		assert.Equal(t, actual, expected, "expected: %v, got: %v", actual, expected)
   180  	})
   181  	mt.RunOpts("2. data key and double encryption", noClientOpts, func(mt *mtest.T) {
   182  		// set up options structs
   183  		schema := bson.D{
   184  			{"bsonType", "object"},
   185  			{"properties", bson.D{
   186  				{"encrypted_placeholder", bson.D{
   187  					{"encrypt", bson.D{
   188  						{"keyId", "/placeholder"},
   189  						{"bsonType", "string"},
   190  						{"algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random"},
   191  					}},
   192  				}},
   193  			}},
   194  		}
   195  		schemaMap := map[string]interface{}{"db.coll": schema}
   196  		tlsConfig := make(map[string]*tls.Config)
   197  		if tlsCAFileKMIP != "" && tlsClientCertificateKeyFileKMIP != "" {
   198  			tlsOpts := map[string]interface{}{
   199  				"tlsCertificateKeyFile": tlsClientCertificateKeyFileKMIP,
   200  				"tlsCAFile":             tlsCAFileKMIP,
   201  			}
   202  			kmipConfig, err := options.BuildTLSConfig(tlsOpts)
   203  			assert.Nil(mt, err, "BuildTLSConfig error: %v", err)
   204  			tlsConfig["kmip"] = kmipConfig
   205  		}
   206  
   207  		aeo := options.AutoEncryption().
   208  			SetKmsProviders(fullKmsProvidersMap).
   209  			SetKeyVaultNamespace(kvNamespace).
   210  			SetSchemaMap(schemaMap).
   211  			SetTLSConfig(tlsConfig).
   212  			SetExtraOptions(getCryptSharedLibExtraOptions())
   213  
   214  		ceo := options.ClientEncryption().
   215  			SetKmsProviders(fullKmsProvidersMap).
   216  			SetKeyVaultNamespace(kvNamespace).
   217  			SetTLSConfig(tlsConfig)
   218  
   219  		awsMasterKey := bson.D{
   220  			{"region", "us-east-1"},
   221  			{"key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"},
   222  		}
   223  		azureMasterKey := bson.D{
   224  			{"keyVaultEndpoint", "key-vault-csfle.vault.azure.net"},
   225  			{"keyName", "key-name-csfle"},
   226  		}
   227  		gcpMasterKey := bson.D{
   228  			{"projectId", "devprod-drivers"},
   229  			{"location", "global"},
   230  			{"keyRing", "key-ring-csfle"},
   231  			{"keyName", "key-name-csfle"},
   232  		}
   233  		kmipMasterKey := bson.D{}
   234  		testCases := []struct {
   235  			provider  string
   236  			masterKey interface{}
   237  		}{
   238  			{"local", nil},
   239  			{"aws", awsMasterKey},
   240  			{"azure", azureMasterKey},
   241  			{"gcp", gcpMasterKey},
   242  			{"kmip", kmipMasterKey},
   243  		}
   244  		for _, tc := range testCases {
   245  			mt.Run(tc.provider, func(mt *mtest.T) {
   246  				if tc.provider == "kmip" && "" == os.Getenv("KMS_MOCK_SERVERS_RUNNING") {
   247  					mt.Skipf("Skipping test as KMS_MOCK_SERVERS_RUNNING is not set")
   248  				}
   249  				var startedEvents []*event.CommandStartedEvent
   250  				monitor := &event.CommandMonitor{
   251  					Started: func(_ context.Context, evt *event.CommandStartedEvent) {
   252  						startedEvents = append(startedEvents, evt)
   253  					},
   254  				}
   255  				kvClientOpts := options.Client().ApplyURI(mtest.ClusterURI()).SetMonitor(monitor)
   256  				integtest.AddTestServerAPIVersion(kvClientOpts)
   257  				cpt := setup(mt, aeo, kvClientOpts, ceo)
   258  				defer cpt.teardown(mt)
   259  
   260  				// create data key
   261  				keyAltName := fmt.Sprintf("%s_altname", tc.provider)
   262  				dataKeyOpts := options.DataKey().SetKeyAltNames([]string{keyAltName})
   263  				if tc.masterKey != nil {
   264  					dataKeyOpts.SetMasterKey(tc.masterKey)
   265  				}
   266  				dataKeyID, err := cpt.clientEnc.CreateDataKey(context.Background(), tc.provider, dataKeyOpts)
   267  				assert.Nil(mt, err, "CreateDataKey error: %v", err)
   268  				assert.Equal(mt, keySubtype, dataKeyID.Subtype,
   269  					"expected data key subtype %v, got %v", keySubtype, dataKeyID.Subtype)
   270  
   271  				// assert that the key exists in the key vault
   272  				cursor, err := cpt.keyVaultColl.Find(context.Background(), bson.D{{"_id", dataKeyID}})
   273  				assert.Nil(mt, err, "key vault Find error: %v", err)
   274  				assert.True(mt, cursor.Next(context.Background()), "no keys found in key vault")
   275  				provider := cursor.Current.Lookup("masterKey", "provider").StringValue()
   276  				assert.Equal(mt, tc.provider, provider, "expected provider %v, got %v", tc.provider, provider)
   277  				assert.False(mt, cursor.Next(context.Background()), "unexpected document in key vault: %v", cursor.Current)
   278  
   279  				// verify that the key was inserted using write concern majority
   280  				assert.Equal(mt, 1, len(startedEvents), "expected 1 CommandStartedEvent, got %v", len(startedEvents))
   281  				evt := startedEvents[0]
   282  				assert.Equal(mt, "insert", evt.CommandName, "expected command 'insert', got '%v'", evt.CommandName)
   283  				writeConcernVal, err := evt.Command.LookupErr("writeConcern")
   284  				assert.Nil(mt, err, "expected writeConcern in command %s", evt.Command)
   285  				wString := writeConcernVal.Document().Lookup("w").StringValue()
   286  				assert.Equal(mt, "majority", wString, "expected write concern 'majority', got %v", wString)
   287  
   288  				// encrypt a value with the new key by ID
   289  				valueToEncrypt := fmt.Sprintf("hello %s", tc.provider)
   290  				rawVal := bson.RawValue{Type: bson.TypeString, Value: bsoncore.AppendString(nil, valueToEncrypt)}
   291  				encrypted, err := cpt.clientEnc.Encrypt(context.Background(), rawVal,
   292  					options.Encrypt().SetAlgorithm(deterministicAlgorithm).SetKeyID(dataKeyID))
   293  				assert.Nil(mt, err, "Encrypt error while encrypting value by ID: %v", err)
   294  				assert.Equal(mt, encryptedValueSubtype, encrypted.Subtype,
   295  					"expected encrypted value subtype %v, got %v", encryptedValueSubtype, encrypted.Subtype)
   296  
   297  				// insert an encrypted value. the value shouldn't be encrypted again because it's not in the schema.
   298  				_, err = cpt.cseColl.InsertOne(context.Background(), bson.D{{"_id", tc.provider}, {"value", encrypted}})
   299  				assert.Nil(mt, err, "InsertOne error: %v", err)
   300  
   301  				// find the inserted document. the value should be decrypted automatically
   302  				resBytes, err := cpt.cseColl.FindOne(context.Background(), bson.D{{"_id", tc.provider}}).Raw()
   303  				assert.Nil(mt, err, "Find error: %v", err)
   304  				foundVal := resBytes.Lookup("value").StringValue()
   305  				assert.Equal(mt, valueToEncrypt, foundVal, "expected value %v, got %v", valueToEncrypt, foundVal)
   306  
   307  				// encrypt a value with an alternate name for the new key
   308  				altEncrypted, err := cpt.clientEnc.Encrypt(context.Background(), rawVal,
   309  					options.Encrypt().SetAlgorithm(deterministicAlgorithm).SetKeyAltName(keyAltName))
   310  				assert.Nil(mt, err, "Encrypt error while encrypting value by alt key name: %v", err)
   311  				assert.Equal(mt, encryptedValueSubtype, altEncrypted.Subtype,
   312  					"expected encrypted value subtype %v, got %v", encryptedValueSubtype, altEncrypted.Subtype)
   313  				assert.Equal(mt, encrypted.Data, altEncrypted.Data,
   314  					"expected data %v, got %v", encrypted.Data, altEncrypted.Data)
   315  
   316  				// insert an encrypted value for an auto-encrypted field
   317  				_, err = cpt.cseColl.InsertOne(context.Background(), bson.D{{"encrypted_placeholder", encrypted}})
   318  				assert.NotNil(mt, err, "expected InsertOne error, got nil")
   319  			})
   320  		}
   321  	})
   322  	mt.RunOpts("3. external key vault", noClientOpts, func(mt *mtest.T) {
   323  		testCases := []struct {
   324  			name          string
   325  			externalVault bool
   326  		}{
   327  			{"with external vault", true},
   328  			{"without external vault", false},
   329  		}
   330  
   331  		for _, tc := range testCases {
   332  			mt.Run(tc.name, func(mt *mtest.T) {
   333  				// setup options structs
   334  				kmsProviders := map[string]map[string]interface{}{
   335  					"local": {
   336  						"key": localMasterKey,
   337  					},
   338  				}
   339  				schemaMap := map[string]interface{}{"db.coll": readJSONFile(mt, "external-schema.json")}
   340  				aeo := options.AutoEncryption().
   341  					SetKmsProviders(kmsProviders).
   342  					SetKeyVaultNamespace(kvNamespace).
   343  					SetSchemaMap(schemaMap).
   344  					SetExtraOptions(getCryptSharedLibExtraOptions())
   345  				ceo := options.ClientEncryption().
   346  					SetKmsProviders(kmsProviders).
   347  					SetKeyVaultNamespace(kvNamespace)
   348  				kvClientOpts := defaultKvClientOptions
   349  
   350  				if tc.externalVault {
   351  					externalKvOpts := options.Client().ApplyURI(mtest.ClusterURI()).SetAuth(options.Credential{
   352  						Username: "fake-user",
   353  						Password: "fake-password",
   354  					})
   355  					integtest.AddTestServerAPIVersion(externalKvOpts)
   356  					aeo.SetKeyVaultClientOptions(externalKvOpts)
   357  					kvClientOpts = externalKvOpts
   358  				}
   359  				cpt := setup(mt, aeo, kvClientOpts, ceo)
   360  				defer cpt.teardown(mt)
   361  
   362  				// manually insert data key
   363  				key := readJSONFile(mt, "external-key.json")
   364  				_, err := cpt.keyVaultColl.InsertOne(context.Background(), key)
   365  				assert.Nil(mt, err, "InsertOne error for data key: %v", err)
   366  				subtype, data := key.Lookup("_id").Binary()
   367  				dataKeyID := primitive.Binary{Subtype: subtype, Data: data}
   368  
   369  				doc := bson.D{{"encrypted", "test"}}
   370  				_, insertErr := cpt.cseClient.Database("db").Collection("coll").InsertOne(context.Background(), doc)
   371  				rawVal := bson.RawValue{Type: bson.TypeString, Value: bsoncore.AppendString(nil, "test")}
   372  				_, encErr := cpt.clientEnc.Encrypt(context.Background(), rawVal,
   373  					options.Encrypt().SetKeyID(dataKeyID).SetAlgorithm(deterministicAlgorithm))
   374  
   375  				if tc.externalVault {
   376  					assert.NotNil(mt, insertErr, "expected InsertOne auth error, got nil")
   377  					assert.NotNil(mt, encErr, "expected Encrypt auth error, got nil")
   378  					assert.True(mt, strings.Contains(insertErr.Error(), "auth error"),
   379  						"expected InsertOne auth error, got %v", insertErr)
   380  					assert.True(mt, strings.Contains(encErr.Error(), "auth error"),
   381  						"expected Encrypt auth error, got %v", insertErr)
   382  					return
   383  				}
   384  				assert.Nil(mt, insertErr, "InsertOne error: %v", insertErr)
   385  				assert.Nil(mt, encErr, "Encrypt error: %v", err)
   386  			})
   387  		}
   388  	})
   389  	mt.Run("4. bson size limits", func(mt *mtest.T) {
   390  		kmsProviders := map[string]map[string]interface{}{
   391  			"local": {
   392  				"key": localMasterKey,
   393  			},
   394  		}
   395  		aeo := options.AutoEncryption().
   396  			SetKmsProviders(kmsProviders).
   397  			SetKeyVaultNamespace(kvNamespace).
   398  			SetExtraOptions(getCryptSharedLibExtraOptions())
   399  		cpt := setup(mt, aeo, nil, nil)
   400  		defer cpt.teardown(mt)
   401  
   402  		// create coll with JSON schema
   403  		err := mt.Client.Database("db").RunCommand(context.Background(), bson.D{
   404  			{"create", "coll"},
   405  			{"validator", bson.D{
   406  				{"$jsonSchema", readJSONFile(mt, "limits-schema.json")},
   407  			}},
   408  		}).Err()
   409  		assert.Nil(mt, err, "create error with validator: %v", err)
   410  
   411  		// insert key
   412  		key := readJSONFile(mt, "limits-key.json")
   413  		_, err = cpt.keyVaultColl.InsertOne(context.Background(), key)
   414  		assert.Nil(mt, err, "InsertOne error for key: %v", err)
   415  
   416  		var builder2mb, builder16mb strings.Builder
   417  		for i := 0; i < cryptMaxBatchSizeBytes; i++ {
   418  			builder2mb.WriteByte('a')
   419  		}
   420  		for i := 0; i < maxBsonObjSize; i++ {
   421  			builder16mb.WriteByte('a')
   422  		}
   423  		complete2mbStr := builder2mb.String()
   424  		complete16mbStr := builder16mb.String()
   425  
   426  		// insert a document over 2MiB
   427  		doc := bson.D{{"over_2mib_under_16mib", complete2mbStr}}
   428  		_, err = cpt.cseColl.InsertOne(context.Background(), doc)
   429  		assert.Nil(mt, err, "InsertOne error for 2MiB document: %v", err)
   430  
   431  		str := complete2mbStr[:cryptMaxBatchSizeBytes-2000] // remove last 2000 bytes
   432  		limitsDoc := readJSONFile(mt, "limits-doc.json")
   433  
   434  		// insert a doc smaller than 2MiB that is bigger than 2MiB after encryption
   435  		var extendedLimitsDoc []byte
   436  		extendedLimitsDoc = append(extendedLimitsDoc, limitsDoc...)
   437  		extendedLimitsDoc = extendedLimitsDoc[:len(extendedLimitsDoc)-1] // remove last byte to add new fields
   438  		extendedLimitsDoc = bsoncore.AppendStringElement(extendedLimitsDoc, "_id", "encryption_exceeds_2mib")
   439  		extendedLimitsDoc = bsoncore.AppendStringElement(extendedLimitsDoc, "unencrypted", str)
   440  		extendedLimitsDoc, _ = bsoncore.AppendDocumentEnd(extendedLimitsDoc, 0)
   441  		_, err = cpt.cseColl.InsertOne(context.Background(), extendedLimitsDoc)
   442  		assert.Nil(mt, err, "error inserting extended limits document: %v", err)
   443  
   444  		// bulk insert two 2MiB documents, each over 2 MiB
   445  		// each document should be split into its own batch because the documents are bigger than 2MiB but smaller
   446  		// than 16MiB
   447  		cpt.cseStarted = cpt.cseStarted[:0]
   448  		firstDoc := bson.D{{"_id", "over_2mib_1"}, {"unencrypted", complete2mbStr}}
   449  		secondDoc := bson.D{{"_id", "over_2mib_2"}, {"unencrypted", complete2mbStr}}
   450  		_, err = cpt.cseColl.InsertMany(context.Background(), []interface{}{firstDoc, secondDoc})
   451  		assert.Nil(mt, err, "InsertMany error for small documents: %v", err)
   452  		assert.Equal(mt, 2, len(cpt.cseStarted), "expected 2 insert events, got %d", len(cpt.cseStarted))
   453  
   454  		// bulk insert two documents
   455  		str = complete2mbStr[:cryptMaxBatchSizeBytes-20000]
   456  		firstBulkDoc := make([]byte, len(limitsDoc))
   457  		copy(firstBulkDoc, limitsDoc)
   458  		firstBulkDoc = firstBulkDoc[:len(firstBulkDoc)-1] // remove last byte to append new fields
   459  		firstBulkDoc = bsoncore.AppendStringElement(firstBulkDoc, "_id", "encryption_exceeds_2mib_1")
   460  		firstBulkDoc = bsoncore.AppendStringElement(firstBulkDoc, "unencrypted", string(str))
   461  		firstBulkDoc, _ = bsoncore.AppendDocumentEnd(firstBulkDoc, 0)
   462  
   463  		secondBulkDoc := make([]byte, len(limitsDoc))
   464  		copy(secondBulkDoc, limitsDoc)
   465  		secondBulkDoc = secondBulkDoc[:len(secondBulkDoc)-1] // remove last byte to append new fields
   466  		secondBulkDoc = bsoncore.AppendStringElement(secondBulkDoc, "_id", "encryption_exceeds_2mib_2")
   467  		secondBulkDoc = bsoncore.AppendStringElement(secondBulkDoc, "unencrypted", string(str))
   468  		secondBulkDoc, _ = bsoncore.AppendDocumentEnd(secondBulkDoc, 0)
   469  
   470  		cpt.cseStarted = cpt.cseStarted[:0]
   471  		_, err = cpt.cseColl.InsertMany(context.Background(), []interface{}{firstBulkDoc, secondBulkDoc})
   472  		assert.Nil(mt, err, "InsertMany error for large documents: %v", err)
   473  		assert.Equal(mt, 2, len(cpt.cseStarted), "expected 2 insert events, got %d", len(cpt.cseStarted))
   474  
   475  		// insert a document slightly smaller than 16MiB and expect the operation to succeed
   476  		doc = bson.D{{"_id", "under_16mib"}, {"unencrypted", complete16mbStr[:maxBsonObjSize-2000]}}
   477  		_, err = cpt.cseColl.InsertOne(context.Background(), doc)
   478  		assert.Nil(mt, err, "InsertOne error: %v", err)
   479  
   480  		// insert a document over 16MiB and expect the operation to fail
   481  		var over16mb []byte
   482  		over16mb = append(over16mb, limitsDoc...)
   483  		over16mb = over16mb[:len(over16mb)-1] // remove last byte
   484  		over16mb = bsoncore.AppendStringElement(over16mb, "_id", "encryption_exceeds_16mib")
   485  		over16mb = bsoncore.AppendStringElement(over16mb, "unencrypted", complete16mbStr[:maxBsonObjSize-2000])
   486  		over16mb, _ = bsoncore.AppendDocumentEnd(over16mb, 0)
   487  		_, err = cpt.cseColl.InsertOne(context.Background(), over16mb)
   488  		assert.NotNil(mt, err, "expected InsertOne error for document over 16MiB, got nil")
   489  	})
   490  	mt.Run("5. views are prohibited", func(mt *mtest.T) {
   491  		mt.Parallel()
   492  
   493  		kmsProviders := map[string]map[string]interface{}{
   494  			"local": {
   495  				"key": localMasterKey,
   496  			},
   497  		}
   498  		aeo := options.AutoEncryption().
   499  			SetKmsProviders(kmsProviders).
   500  			SetKeyVaultNamespace(kvNamespace).
   501  			SetExtraOptions(getCryptSharedLibExtraOptions())
   502  		cpt := setup(mt, aeo, nil, nil)
   503  		defer cpt.teardown(mt)
   504  
   505  		// create view on db.coll
   506  		mt.CreateCollection(mtest.Collection{
   507  			Name:         "view",
   508  			DB:           cpt.cseColl.Database().Name(),
   509  			ViewOn:       "coll",
   510  			ViewPipeline: mongo.Pipeline{},
   511  		}, true)
   512  
   513  		view := cpt.cseColl.Database().Collection("view")
   514  		_, err := view.InsertOne(context.Background(), bson.D{{"_id", "insert_on_view"}})
   515  		assert.NotNil(mt, err, "expected InsertOne error on view, got nil")
   516  		errStr := strings.ToLower(err.Error())
   517  		viewErrSubstr := "cannot auto encrypt a view"
   518  		assert.True(mt, strings.Contains(errStr, viewErrSubstr),
   519  			"expected error '%v' to contain substring '%v'", errStr, viewErrSubstr)
   520  	})
   521  	mt.RunOpts("6. corpus test", noClientOpts, func(mt *mtest.T) {
   522  		if "" == os.Getenv("KMS_MOCK_SERVERS_RUNNING") {
   523  			mt.Skipf("Skipping test as KMS_MOCK_SERVERS_RUNNING is not set")
   524  		}
   525  		corpusSchema := readJSONFile(mt, "corpus-schema.json")
   526  		localSchemaMap := map[string]interface{}{
   527  			"db.coll": corpusSchema,
   528  		}
   529  
   530  		tlsConfig := make(map[string]*tls.Config)
   531  		if tlsCAFileKMIP != "" && tlsClientCertificateKeyFileKMIP != "" {
   532  			tlsOpts := map[string]interface{}{
   533  				"tlsCertificateKeyFile": tlsClientCertificateKeyFileKMIP,
   534  				"tlsCAFile":             tlsCAFileKMIP,
   535  			}
   536  			kmipConfig, err := options.BuildTLSConfig(tlsOpts)
   537  			assert.Nil(mt, err, "BuildTLSConfig error: %v", err)
   538  			tlsConfig["kmip"] = kmipConfig
   539  		}
   540  
   541  		getBaseAutoEncryptionOpts := func() *options.AutoEncryptionOptions {
   542  			return options.AutoEncryption().
   543  				SetKmsProviders(fullKmsProvidersMap).
   544  				SetKeyVaultNamespace(kvNamespace).
   545  				SetTLSConfig(tlsConfig).
   546  				SetExtraOptions(getCryptSharedLibExtraOptions())
   547  		}
   548  
   549  		testCases := []struct {
   550  			name   string
   551  			aeo    *options.AutoEncryptionOptions
   552  			schema bson.Raw // the schema to create the collection. if nil, the collection won't be explicitly created
   553  		}{
   554  			{"remote schema", getBaseAutoEncryptionOpts(), corpusSchema},
   555  			{"local schema", getBaseAutoEncryptionOpts().SetSchemaMap(localSchemaMap), nil},
   556  		}
   557  
   558  		for _, tc := range testCases {
   559  			mt.Run(tc.name, func(mt *mtest.T) {
   560  				ceo := options.ClientEncryption().
   561  					SetKmsProviders(fullKmsProvidersMap).
   562  					SetKeyVaultNamespace(kvNamespace).
   563  					SetTLSConfig(tlsConfig)
   564  
   565  				cpt := setup(mt, tc.aeo, defaultKvClientOptions, ceo)
   566  				defer cpt.teardown(mt)
   567  
   568  				// create collection with JSON schema
   569  				if tc.schema != nil {
   570  					db := cpt.coll.Database()
   571  					err := db.RunCommand(context.Background(), bson.D{
   572  						{"create", "coll"},
   573  						{"validator", bson.D{
   574  							{"$jsonSchema", readJSONFile(mt, "corpus-schema.json")},
   575  						}},
   576  					}).Err()
   577  					assert.Nil(mt, err, "create error with validator: %v", err)
   578  				}
   579  
   580  				// Manually insert keys for each KMS provider into the key vault.
   581  				_, err := cpt.keyVaultColl.InsertMany(context.Background(), []interface{}{
   582  					readJSONFile(mt, "corpus-key-local.json"),
   583  					readJSONFile(mt, "corpus-key-aws.json"),
   584  					readJSONFile(mt, "corpus-key-azure.json"),
   585  					readJSONFile(mt, "corpus-key-gcp.json"),
   586  					readJSONFile(mt, "corpus-key-kmip.json"),
   587  				})
   588  				assert.Nil(mt, err, "InsertMany error for key vault: %v", err)
   589  
   590  				// read original corpus and recursively copy over each value to new corpus, encrypting certain values
   591  				// when needed
   592  				corpus := readJSONFile(mt, "corpus.json")
   593  				cidx, copied := bsoncore.AppendDocumentStart(nil)
   594  				elems, _ := corpus.Elements()
   595  
   596  				// Keys for top-level non-document elements that should be copied directly.
   597  				copiedKeys := map[string]struct{}{
   598  					"_id":           {},
   599  					"altname_aws":   {},
   600  					"altname_local": {},
   601  					"altname_azure": {},
   602  					"altname_gcp":   {},
   603  					"altname_kmip":  {},
   604  				}
   605  
   606  				for _, elem := range elems {
   607  					key := elem.Key()
   608  					val := elem.Value()
   609  
   610  					if _, ok := copiedKeys[key]; ok {
   611  						copied = bsoncore.AppendStringElement(copied, key, val.StringValue())
   612  						continue
   613  					}
   614  
   615  					doc := val.Document()
   616  					switch method := doc.Lookup("method").StringValue(); method {
   617  					case "auto":
   618  						// Copy the value directly because it will be auto-encrypted later.
   619  						copied = bsoncore.AppendDocumentElement(copied, key, doc)
   620  						continue
   621  					case "explicit":
   622  						// Handled below.
   623  					default:
   624  						mt.Fatalf("unrecognized 'method' value %q", method)
   625  					}
   626  
   627  					// explicitly encrypt value
   628  					algorithm := deterministicAlgorithm
   629  					if doc.Lookup("algo").StringValue() == "rand" {
   630  						algorithm = randomAlgorithm
   631  					}
   632  					eo := options.Encrypt().SetAlgorithm(algorithm)
   633  
   634  					identifier := doc.Lookup("identifier").StringValue()
   635  					kms := doc.Lookup("kms").StringValue()
   636  					switch identifier {
   637  					case "id":
   638  						var keyID string
   639  						switch kms {
   640  						case "local":
   641  							keyID = "LOCALAAAAAAAAAAAAAAAAA=="
   642  						case "aws":
   643  							keyID = "AWSAAAAAAAAAAAAAAAAAAA=="
   644  						case "azure":
   645  							keyID = "AZUREAAAAAAAAAAAAAAAAA=="
   646  						case "gcp":
   647  							keyID = "GCPAAAAAAAAAAAAAAAAAAA=="
   648  						case "kmip":
   649  							keyID = "KMIPAAAAAAAAAAAAAAAAAA=="
   650  						default:
   651  							mt.Fatalf("unrecognized KMS provider %q", kms)
   652  						}
   653  
   654  						keyIDBytes, err := base64.StdEncoding.DecodeString(keyID)
   655  						assert.Nil(mt, err, "base64 DecodeString error: %v", err)
   656  						eo.SetKeyID(primitive.Binary{Subtype: 4, Data: keyIDBytes})
   657  					case "altname":
   658  						eo.SetKeyAltName(kms) // alt name for a key is the same as the KMS name
   659  					default:
   660  						mt.Fatalf("unrecognized identifier: %v", identifier)
   661  					}
   662  
   663  					// iterate over all elements in the document. copy elements directly, except for ones that need to
   664  					// be encrypted, which should be copied after encryption.
   665  					var nestedIdx int32
   666  					nestedIdx, copied = bsoncore.AppendDocumentElementStart(copied, key)
   667  					docElems, _ := doc.Elements()
   668  					for _, de := range docElems {
   669  						deKey := de.Key()
   670  						deVal := de.Value()
   671  
   672  						// element to encrypt has key "value"
   673  						if deKey != "value" {
   674  							copied = bsoncore.AppendValueElement(copied, deKey, rawValueToCoreValue(deVal))
   675  							continue
   676  						}
   677  
   678  						encrypted, err := cpt.clientEnc.Encrypt(context.Background(), deVal, eo)
   679  						if !doc.Lookup("allowed").Boolean() {
   680  							// if allowed is false, encryption should error. in this case, the unencrypted value should be
   681  							// copied over
   682  							assert.NotNil(mt, err, "expected error encrypting value for key %v, got nil", key)
   683  							copied = bsoncore.AppendValueElement(copied, deKey, rawValueToCoreValue(deVal))
   684  							continue
   685  						}
   686  
   687  						// copy encrypted value
   688  						assert.Nil(mt, err, "Encrypt error for key %v: %v", key, err)
   689  						copied = bsoncore.AppendBinaryElement(copied, deKey, encrypted.Subtype, encrypted.Data)
   690  					}
   691  					copied, _ = bsoncore.AppendDocumentEnd(copied, nestedIdx)
   692  				}
   693  				copied, _ = bsoncore.AppendDocumentEnd(copied, cidx)
   694  
   695  				// insert document with encrypted values
   696  				_, err = cpt.cseColl.InsertOne(context.Background(), copied)
   697  				assert.Nil(mt, err, "InsertOne error for corpus document: %v", err)
   698  
   699  				// find document using client with encryption and assert it matches original
   700  				decryptedDoc, err := cpt.cseColl.FindOne(context.Background(), bson.D{}).Raw()
   701  				assert.Nil(mt, err, "Find error with encrypted client: %v", err)
   702  				assert.Equal(mt, corpus, decryptedDoc, "expected document %v, got %v", corpus, decryptedDoc)
   703  
   704  				// find document using a client without encryption enabled and assert fields remain encrypted
   705  				corpusEncrypted := readJSONFile(mt, "corpus-encrypted.json")
   706  				foundDoc, err := cpt.coll.FindOne(context.Background(), bson.D{}).Raw()
   707  				assert.Nil(mt, err, "Find error with unencrypted client: %v", err)
   708  
   709  				encryptedElems, _ := corpusEncrypted.Elements()
   710  				for _, encryptedElem := range encryptedElems {
   711  					// skip non-document fields
   712  					encryptedDoc, ok := encryptedElem.Value().DocumentOK()
   713  					if !ok {
   714  						continue
   715  					}
   716  
   717  					allowed := encryptedDoc.Lookup("allowed").Boolean()
   718  					expectedKey := encryptedElem.Key()
   719  					expectedVal := encryptedDoc.Lookup("value")
   720  					foundVal := foundDoc.Lookup(expectedKey).Document().Lookup("value")
   721  
   722  					// for deterministic encryption, the value should be exactly equal
   723  					// for random encryption, the value should not be equal if allowed is true
   724  					algo := encryptedDoc.Lookup("algo").StringValue()
   725  					switch algo {
   726  					case "det":
   727  						assert.True(mt, expectedVal.Equal(foundVal),
   728  							"expected value %v for key %v, got %v", expectedVal, expectedKey, foundVal)
   729  					case "rand":
   730  						if allowed {
   731  							assert.False(mt, expectedVal.Equal(foundVal),
   732  								"expected values for key %v to be different but were %v", expectedKey, expectedVal)
   733  						}
   734  					}
   735  
   736  					// if allowed is true, decrypt both values with clientEnc and validate equality
   737  					if allowed {
   738  						sub, data := expectedVal.Binary()
   739  						expectedDecrypted, err := cpt.clientEnc.Decrypt(context.Background(), primitive.Binary{Subtype: sub, Data: data})
   740  						assert.Nil(mt, err, "Decrypt error: %v", err)
   741  						sub, data = foundVal.Binary()
   742  						actualDecrypted, err := cpt.clientEnc.Decrypt(context.Background(), primitive.Binary{Subtype: sub, Data: data})
   743  						assert.Nil(mt, err, "Decrypt error: %v", err)
   744  
   745  						assert.True(mt, expectedDecrypted.Equal(actualDecrypted),
   746  							"expected decrypted value %v for key %v, got %v", expectedDecrypted, expectedKey, actualDecrypted)
   747  						continue
   748  					}
   749  
   750  					// if allowed is false, validate found value equals the original value in corpus
   751  					corpusVal := corpus.Lookup(expectedKey).Document().Lookup("value")
   752  					assert.True(mt, corpusVal.Equal(foundVal),
   753  						"expected value %v for key %v, got %v", corpusVal, expectedKey, foundVal)
   754  				}
   755  			})
   756  		}
   757  	})
   758  	mt.Run("7. custom endpoint", func(mt *mtest.T) {
   759  		validKmsProviders := map[string]map[string]interface{}{
   760  			"aws": {
   761  				"accessKeyId":     awsAccessKeyID,
   762  				"secretAccessKey": awsSecretAccessKey,
   763  			},
   764  			"azure": {
   765  				"tenantId":                 azureTenantID,
   766  				"clientId":                 azureClientID,
   767  				"clientSecret":             azureClientSecret,
   768  				"identityPlatformEndpoint": "login.microsoftonline.com:443",
   769  			},
   770  			"gcp": {
   771  				"email":      gcpEmail,
   772  				"privateKey": gcpPrivateKey,
   773  				"endpoint":   "oauth2.googleapis.com:443",
   774  			},
   775  			"kmip": {
   776  				"endpoint": "localhost:5698",
   777  			},
   778  		}
   779  
   780  		tlsConfig := make(map[string]*tls.Config)
   781  		if tlsCAFileKMIP != "" && tlsClientCertificateKeyFileKMIP != "" {
   782  			tlsOpts := map[string]interface{}{
   783  				"tlsCertificateKeyFile": tlsClientCertificateKeyFileKMIP,
   784  				"tlsCAFile":             tlsCAFileKMIP,
   785  			}
   786  			kmipConfig, err := options.BuildTLSConfig(tlsOpts)
   787  			assert.Nil(mt, err, "BuildTLSConfig error: %v", err)
   788  			tlsConfig["kmip"] = kmipConfig
   789  		}
   790  
   791  		validClientEncryptionOptions := options.ClientEncryption().
   792  			SetKmsProviders(validKmsProviders).
   793  			SetKeyVaultNamespace(kvNamespace).
   794  			SetTLSConfig(tlsConfig)
   795  
   796  		invalidKmsProviders := map[string]map[string]interface{}{
   797  			"azure": {
   798  				"tenantId":                 azureTenantID,
   799  				"clientId":                 azureClientID,
   800  				"clientSecret":             azureClientSecret,
   801  				"identityPlatformEndpoint": "doesnotexist.invalid:443",
   802  			},
   803  			"gcp": {
   804  				"email":      gcpEmail,
   805  				"privateKey": gcpPrivateKey,
   806  				"endpoint":   "doesnotexist.invalid:443",
   807  			},
   808  			"kmip": {
   809  				"endpoint": "doesnotexist.local:5698",
   810  			},
   811  		}
   812  
   813  		invalidClientEncryptionOptions := options.ClientEncryption().
   814  			SetKmsProviders(invalidKmsProviders).
   815  			SetKeyVaultNamespace(kvNamespace).
   816  			SetTLSConfig(tlsConfig)
   817  
   818  		awsSuccessWithoutEndpoint := map[string]interface{}{
   819  			"region": "us-east-1",
   820  			"key":    "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
   821  		}
   822  		awsSuccessWithEndpoint := map[string]interface{}{
   823  			"region":   "us-east-1",
   824  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
   825  			"endpoint": "kms.us-east-1.amazonaws.com",
   826  		}
   827  		awsSuccessWithHTTPSEndpoint := map[string]interface{}{
   828  			"region":   "us-east-1",
   829  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
   830  			"endpoint": "kms.us-east-1.amazonaws.com:443",
   831  		}
   832  		awsFailureConnectionError := map[string]interface{}{
   833  			"region":   "us-east-1",
   834  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
   835  			"endpoint": "kms.us-east-1.amazonaws.com:12345",
   836  		}
   837  		awsFailureInvalidEndpoint := map[string]interface{}{
   838  			"region":   "us-east-1",
   839  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
   840  			"endpoint": "kms.us-east-2.amazonaws.com",
   841  		}
   842  		awsFailureParseError := map[string]interface{}{
   843  			"region":   "us-east-1",
   844  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
   845  			"endpoint": "doesnotexist.invalid",
   846  		}
   847  		azure := map[string]interface{}{
   848  			"keyVaultEndpoint": "key-vault-csfle.vault.azure.net",
   849  			"keyName":          "key-name-csfle",
   850  		}
   851  		gcpSuccess := map[string]interface{}{
   852  			"projectId": "devprod-drivers",
   853  			"location":  "global",
   854  			"keyRing":   "key-ring-csfle",
   855  			"keyName":   "key-name-csfle",
   856  			"endpoint":  "cloudkms.googleapis.com:443",
   857  		}
   858  		gcpFailure := map[string]interface{}{
   859  			"projectId": "devprod-drivers",
   860  			"location":  "global",
   861  			"keyRing":   "key-ring-csfle",
   862  			"keyName":   "key-name-csfle",
   863  			"endpoint":  "doesnotexist.invalid:443",
   864  		}
   865  		kmipSuccessWithoutEndpoint := map[string]interface{}{
   866  			"keyId": "1",
   867  		}
   868  		kmipSuccessWithEndpoint := map[string]interface{}{
   869  			"keyId":    "1",
   870  			"endpoint": "localhost:5698",
   871  		}
   872  		kmipFailureInvalidEndpoint := map[string]interface{}{
   873  			"keyId":    "1",
   874  			"endpoint": "doesnotexist.local:5698",
   875  		}
   876  
   877  		const (
   878  			errConnectionRefused           = "connection refused"
   879  			errInvalidKMSResponse          = "Invalid KMS response"
   880  			errMongocryptError             = "mongocrypt error"
   881  			errNoSuchHost                  = "no such host"
   882  			errServerMisbehaving           = "server misbehaving"
   883  			errWindowsTLSConnectionRefused = "No connection could be made because the target machine actively refused it"
   884  		)
   885  
   886  		testCases := []struct {
   887  			name                                  string
   888  			provider                              string
   889  			masterKey                             interface{}
   890  			errorSubstring                        []string
   891  			testInvalidClientEncryption           bool
   892  			invalidClientEncryptionErrorSubstring []string
   893  		}{
   894  			{
   895  				name:                                  "Case 1: aws success without endpoint",
   896  				provider:                              "aws",
   897  				masterKey:                             awsSuccessWithoutEndpoint,
   898  				errorSubstring:                        []string{},
   899  				testInvalidClientEncryption:           false,
   900  				invalidClientEncryptionErrorSubstring: []string{},
   901  			},
   902  			{
   903  				name:                                  "Case 2: aws success with endpoint",
   904  				provider:                              "aws",
   905  				masterKey:                             awsSuccessWithEndpoint,
   906  				errorSubstring:                        []string{},
   907  				testInvalidClientEncryption:           false,
   908  				invalidClientEncryptionErrorSubstring: []string{},
   909  			},
   910  			{
   911  				name:                                  "Case 3: aws success with https endpoint",
   912  				provider:                              "aws",
   913  				masterKey:                             awsSuccessWithHTTPSEndpoint,
   914  				errorSubstring:                        []string{},
   915  				testInvalidClientEncryption:           false,
   916  				invalidClientEncryptionErrorSubstring: []string{},
   917  			},
   918  			{
   919  				name:                                  "Case 4: aws failure with connection error",
   920  				provider:                              "aws",
   921  				masterKey:                             awsFailureConnectionError,
   922  				errorSubstring:                        []string{errConnectionRefused, errWindowsTLSConnectionRefused},
   923  				testInvalidClientEncryption:           false,
   924  				invalidClientEncryptionErrorSubstring: []string{},
   925  			},
   926  			{
   927  				name:                                  "Case 5: aws failure with wrong endpoint",
   928  				provider:                              "aws",
   929  				masterKey:                             awsFailureInvalidEndpoint,
   930  				errorSubstring:                        []string{errMongocryptError},
   931  				testInvalidClientEncryption:           false,
   932  				invalidClientEncryptionErrorSubstring: []string{},
   933  			},
   934  			{
   935  				name:                                  "Case 6: aws failure with parse error",
   936  				provider:                              "aws",
   937  				masterKey:                             awsFailureParseError,
   938  				errorSubstring:                        []string{errNoSuchHost, errServerMisbehaving},
   939  				testInvalidClientEncryption:           false,
   940  				invalidClientEncryptionErrorSubstring: []string{},
   941  			},
   942  			{
   943  				name:                                  "Case 7: azure success",
   944  				provider:                              "azure",
   945  				masterKey:                             azure,
   946  				errorSubstring:                        []string{},
   947  				testInvalidClientEncryption:           true,
   948  				invalidClientEncryptionErrorSubstring: []string{errNoSuchHost, errServerMisbehaving},
   949  			},
   950  			{
   951  				name:                                  "Case 8: gcp success",
   952  				provider:                              "gcp",
   953  				masterKey:                             gcpSuccess,
   954  				errorSubstring:                        []string{},
   955  				testInvalidClientEncryption:           true,
   956  				invalidClientEncryptionErrorSubstring: []string{errNoSuchHost, errServerMisbehaving},
   957  			},
   958  			{
   959  				name:                                  "Case 9: gcp failure",
   960  				provider:                              "gcp",
   961  				masterKey:                             gcpFailure,
   962  				errorSubstring:                        []string{errInvalidKMSResponse},
   963  				testInvalidClientEncryption:           false,
   964  				invalidClientEncryptionErrorSubstring: []string{},
   965  			},
   966  			{
   967  				name:                                  "Case 10: kmip success without endpoint",
   968  				provider:                              "kmip",
   969  				masterKey:                             kmipSuccessWithoutEndpoint,
   970  				errorSubstring:                        []string{},
   971  				testInvalidClientEncryption:           true,
   972  				invalidClientEncryptionErrorSubstring: []string{errNoSuchHost, errServerMisbehaving},
   973  			},
   974  			{
   975  				name:                                  "Case 11: kmip success with endpoint",
   976  				provider:                              "kmip",
   977  				masterKey:                             kmipSuccessWithEndpoint,
   978  				errorSubstring:                        []string{},
   979  				testInvalidClientEncryption:           false,
   980  				invalidClientEncryptionErrorSubstring: []string{},
   981  			},
   982  			{
   983  				name:                                  "Case 12: kmip failure with invalid endpoint",
   984  				provider:                              "kmip",
   985  				masterKey:                             kmipFailureInvalidEndpoint,
   986  				errorSubstring:                        []string{errNoSuchHost, errServerMisbehaving},
   987  				testInvalidClientEncryption:           false,
   988  				invalidClientEncryptionErrorSubstring: []string{},
   989  			},
   990  		}
   991  		for _, tc := range testCases {
   992  			mt.Run(tc.name, func(mt *mtest.T) {
   993  				if strings.Contains(tc.name, "kmip") && "" == os.Getenv("KMS_MOCK_SERVERS_RUNNING") {
   994  					mt.Skipf("Skipping test as KMS_MOCK_SERVERS_RUNNING is not set")
   995  				}
   996  				cpt := setup(mt, nil, defaultKvClientOptions, validClientEncryptionOptions)
   997  				defer cpt.teardown(mt)
   998  
   999  				dkOpts := options.DataKey().SetMasterKey(tc.masterKey)
  1000  				createdKey, err := cpt.clientEnc.CreateDataKey(context.Background(), tc.provider, dkOpts)
  1001  				if len(tc.errorSubstring) > 0 {
  1002  					assert.NotNil(mt, err, "expected error, got nil")
  1003  
  1004  					assert.True(t, containsSubstring(tc.errorSubstring, err.Error()),
  1005  						"expected tc.errorSubstring=%v to contain %v, but it didn't", tc.errorSubstring, err.Error())
  1006  
  1007  					return
  1008  				}
  1009  				assert.Nil(mt, err, "CreateDataKey error: %v", err)
  1010  
  1011  				encOpts := options.Encrypt().SetKeyID(createdKey).SetAlgorithm(deterministicAlgorithm)
  1012  				testVal := bson.RawValue{
  1013  					Type:  bson.TypeString,
  1014  					Value: bsoncore.AppendString(nil, "test"),
  1015  				}
  1016  				encrypted, err := cpt.clientEnc.Encrypt(context.Background(), testVal, encOpts)
  1017  				assert.Nil(mt, err, "Encrypt error: %v", err)
  1018  				decrypted, err := cpt.clientEnc.Decrypt(context.Background(), encrypted)
  1019  				assert.Nil(mt, err, "Decrypt error: %v", err)
  1020  				assert.Equal(mt, testVal, decrypted, "expected value %s, got %s", testVal, decrypted)
  1021  
  1022  				if !tc.testInvalidClientEncryption {
  1023  					return
  1024  				}
  1025  
  1026  				invalidClientEncryption, err := mongo.NewClientEncryption(cpt.kvClient, invalidClientEncryptionOptions)
  1027  				assert.Nil(mt, err, "error creating invalidClientEncryption object: %v", err)
  1028  				defer invalidClientEncryption.Close(context.Background())
  1029  
  1030  				invalidKeyOpts := options.DataKey().SetMasterKey(tc.masterKey)
  1031  				_, err = invalidClientEncryption.CreateDataKey(context.Background(), tc.provider, invalidKeyOpts)
  1032  				assert.NotNil(mt, err, "expected CreateDataKey error, got nil")
  1033  
  1034  				assert.True(t, containsSubstring(tc.invalidClientEncryptionErrorSubstring, err.Error()),
  1035  					"expected tc.invalidClientEncryptionErrorSubstring=%v to contain %v, but it didn't",
  1036  					tc.invalidClientEncryptionErrorSubstring, err.Error())
  1037  			})
  1038  		}
  1039  	})
  1040  	mt.RunOpts("8. bypass mongocryptd spawning", noClientOpts, func(mt *mtest.T) {
  1041  		mt.Parallel()
  1042  
  1043  		kmsProviders := map[string]map[string]interface{}{
  1044  			"local": {
  1045  				"key": localMasterKey,
  1046  			},
  1047  		}
  1048  		schemaMap := map[string]interface{}{
  1049  			"db.coll": readJSONFile(mt, "external-schema.json"),
  1050  		}
  1051  
  1052  		// All mongocryptd options use port 27021 instead of the default 27020 to avoid interference
  1053  		// with mongocryptd instances spawned by previous tests. Explicitly disable loading the
  1054  		// crypt_shared library to make sure we're testing mongocryptd spawning behavior that is not
  1055  		// influenced by loading the crypt_shared library.
  1056  		mongocryptdBypassSpawnTrue := map[string]interface{}{
  1057  			"mongocryptdBypassSpawn":              true,
  1058  			"mongocryptdURI":                      "mongodb://localhost:27021/db?serverSelectionTimeoutMS=1000",
  1059  			"mongocryptdSpawnArgs":                []string{"--pidfilepath=bypass-spawning-mongocryptd.pid", "--port=27021"},
  1060  			"__cryptSharedLibDisabledForTestOnly": true, // Disable loading the crypt_shared library.
  1061  		}
  1062  		mongocryptdBypassSpawnFalse := map[string]interface{}{
  1063  			"mongocryptdBypassSpawn":              false,
  1064  			"mongocryptdSpawnArgs":                []string{"--pidfilepath=bypass-spawning-mongocryptd.pid", "--port=27021"},
  1065  			"__cryptSharedLibDisabledForTestOnly": true, // Disable loading the crypt_shared library.
  1066  		}
  1067  		mongocryptdBypassSpawnNotSet := map[string]interface{}{
  1068  			"mongocryptdSpawnArgs":                []string{"--pidfilepath=bypass-spawning-mongocryptd.pid", "--port=27021"},
  1069  			"__cryptSharedLibDisabledForTestOnly": true, // Disable loading the crypt_shared library.
  1070  		}
  1071  
  1072  		testCases := []struct {
  1073  			name                    string
  1074  			mongocryptdOpts         map[string]interface{}
  1075  			setBypassAutoEncryption bool
  1076  			bypassAutoEncryption    bool
  1077  			bypassQueryAnalysis     bool
  1078  			useSharedLib            bool
  1079  		}{
  1080  			{
  1081  				name:            "mongocryptdBypassSpawn only",
  1082  				mongocryptdOpts: mongocryptdBypassSpawnTrue,
  1083  			},
  1084  			{
  1085  				name:                    "bypassAutoEncryption only",
  1086  				mongocryptdOpts:         mongocryptdBypassSpawnNotSet,
  1087  				setBypassAutoEncryption: true,
  1088  				bypassAutoEncryption:    true,
  1089  			},
  1090  			{
  1091  				name:                    "mongocryptdBypassSpawn false, bypassAutoEncryption true",
  1092  				mongocryptdOpts:         mongocryptdBypassSpawnFalse,
  1093  				setBypassAutoEncryption: true,
  1094  				bypassAutoEncryption:    true,
  1095  			},
  1096  			{
  1097  				name:                    "mongocryptdBypassSpawn true, bypassAutoEncryption false",
  1098  				mongocryptdOpts:         mongocryptdBypassSpawnTrue,
  1099  				setBypassAutoEncryption: true,
  1100  				bypassAutoEncryption:    false,
  1101  			},
  1102  			{
  1103  				name:                "bypassQueryAnalysis only",
  1104  				mongocryptdOpts:     mongocryptdBypassSpawnNotSet,
  1105  				bypassQueryAnalysis: true,
  1106  			},
  1107  			{
  1108  				name:         "use shared library",
  1109  				useSharedLib: true,
  1110  				mongocryptdOpts: map[string]interface{}{
  1111  					"mongocryptdURI":       "mongodb://localhost:27021/db?serverSelectionTimeoutMS=1000",
  1112  					"mongocryptdSpawnArgs": []string{"--pidfilepath=bypass-spawning-mongocryptd.pid", "--port=27021"},
  1113  					"cryptSharedLibPath":   os.Getenv("CRYPT_SHARED_LIB_PATH"),
  1114  					"cryptSharedRequired":  true,
  1115  				},
  1116  			},
  1117  		}
  1118  		for _, tc := range testCases {
  1119  			mt.Run(tc.name, func(mt *mtest.T) {
  1120  				if tc.useSharedLib && os.Getenv("CRYPT_SHARED_LIB_PATH") == "" {
  1121  					mt.Skip("CRYPT_SHARED_LIB_PATH not set, skipping")
  1122  					return
  1123  				}
  1124  				aeo := options.AutoEncryption().
  1125  					SetKmsProviders(kmsProviders).
  1126  					SetKeyVaultNamespace(kvNamespace).
  1127  					SetSchemaMap(schemaMap).
  1128  					SetExtraOptions(tc.mongocryptdOpts)
  1129  				if tc.setBypassAutoEncryption {
  1130  					aeo.SetBypassAutoEncryption(tc.bypassAutoEncryption)
  1131  				}
  1132  				aeo.SetBypassQueryAnalysis(tc.bypassQueryAnalysis)
  1133  				cpt := setup(mt, aeo, nil, nil)
  1134  				defer cpt.teardown(mt)
  1135  
  1136  				_, err := cpt.cseColl.InsertOne(context.Background(), bson.D{{"unencrypted", "test"}})
  1137  
  1138  				// Check for mongocryptd server selection error if auto encryption needed mongocryptd.
  1139  				if !(tc.setBypassAutoEncryption && tc.bypassAutoEncryption) && !tc.bypassQueryAnalysis && !tc.useSharedLib {
  1140  					assert.NotNil(mt, err, "expected InsertOne error, got nil")
  1141  					mcryptErr, ok := err.(mongo.MongocryptdError)
  1142  					assert.True(mt, ok, "expected error type %T, got %v of type %T", mongo.MongocryptdError{}, err, err)
  1143  					assert.True(mt, strings.Contains(mcryptErr.Error(), "server selection error"),
  1144  						"expected mongocryptd server selection error, got %v", err)
  1145  					return
  1146  				}
  1147  
  1148  				// If mongocryptd was not needed, the command should succeed. Create a new client to connect to
  1149  				// mongocryptd and verify it is not running.
  1150  				assert.Nil(mt, err, "InsertOne error: %v", err)
  1151  
  1152  				mcryptOpts := options.Client().ApplyURI("mongodb://localhost:27021").
  1153  					SetServerSelectionTimeout(1 * time.Second)
  1154  				integtest.AddTestServerAPIVersion(mcryptOpts)
  1155  				mcryptClient, err := mongo.Connect(context.Background(), mcryptOpts)
  1156  				assert.Nil(mt, err, "mongocryptd Connect error: %v", err)
  1157  
  1158  				err = mcryptClient.Database("admin").RunCommand(context.Background(), bson.D{{handshake.LegacyHelloLowercase, 1}}).Err()
  1159  				assert.NotNil(mt, err, "expected mongocryptd legacy hello error, got nil")
  1160  				assert.True(mt, strings.Contains(err.Error(), "server selection error"),
  1161  					"expected mongocryptd server selection error, got %v", err)
  1162  			})
  1163  		}
  1164  	})
  1165  	changeStreamOpts := mtest.NewOptions().
  1166  		CreateClient(false).
  1167  		Topologies(mtest.ReplicaSet)
  1168  	mt.RunOpts("change streams", changeStreamOpts, func(mt *mtest.T) {
  1169  		// Change streams can't easily fit into the spec test format because of their tailable nature, so there are two
  1170  		// prose tests for them instead:
  1171  		//
  1172  		// 1. Auto-encryption errors for Watch operations. Collection-level change streams error because the
  1173  		// $changeStream aggregation stage is not valid for encryption. Client and database-level streams error because
  1174  		// only collection-level operations are valid for encryption.
  1175  		//
  1176  		// 2. Events are automatically decrypted: If the Watch() is done with BypassAutoEncryption=true, the Watch
  1177  		// should succeed and subsequent getMore calls should decrypt documents when necessary.
  1178  
  1179  		var testConfig struct {
  1180  			JSONSchema        bson.Raw   `bson:"json_schema"`
  1181  			KeyVaultData      []bson.Raw `bson:"key_vault_data"`
  1182  			EncryptedDocument bson.Raw   `bson:"encrypted_document"`
  1183  			DecryptedDocument bson.Raw   `bson:"decrytped_document"`
  1184  		}
  1185  		decodeJSONFile(mt, "change-streams-test.json", &testConfig)
  1186  
  1187  		schemaMap := map[string]interface{}{
  1188  			"db.coll": testConfig.JSONSchema,
  1189  		}
  1190  		kmsProviders := map[string]map[string]interface{}{
  1191  			"aws": {
  1192  				"accessKeyId":     awsAccessKeyID,
  1193  				"secretAccessKey": awsSecretAccessKey,
  1194  			},
  1195  		}
  1196  
  1197  		testCases := []struct {
  1198  			name       string
  1199  			streamType mongo.StreamType
  1200  		}{
  1201  			{"client", mongo.ClientStream},
  1202  			{"database", mongo.DatabaseStream},
  1203  			{"collection", mongo.CollectionStream},
  1204  		}
  1205  		mt.RunOpts("auto encryption errors", noClientOpts, func(mt *mtest.T) {
  1206  			mt.Parallel()
  1207  
  1208  			for _, tc := range testCases {
  1209  				mt.Run(tc.name, func(mt *mtest.T) {
  1210  					autoEncryptionOpts := options.AutoEncryption().
  1211  						SetKmsProviders(kmsProviders).
  1212  						SetKeyVaultNamespace(kvNamespace).
  1213  						SetSchemaMap(schemaMap).
  1214  						SetExtraOptions(getCryptSharedLibExtraOptions())
  1215  					cpt := setup(mt, autoEncryptionOpts, nil, nil)
  1216  					defer cpt.teardown(mt)
  1217  
  1218  					_, err := getWatcher(mt, tc.streamType, cpt).Watch(context.Background(), mongo.Pipeline{})
  1219  					assert.NotNil(mt, err, "expected Watch error: %v", err)
  1220  				})
  1221  			}
  1222  		})
  1223  		mt.RunOpts("events are automatically decrypted", noClientOpts, func(mt *mtest.T) {
  1224  			for _, tc := range testCases {
  1225  				mt.Run(tc.name, func(mt *mtest.T) {
  1226  					autoEncryptionOpts := options.AutoEncryption().
  1227  						SetKmsProviders(kmsProviders).
  1228  						SetKeyVaultNamespace(kvNamespace).
  1229  						SetSchemaMap(schemaMap).
  1230  						SetBypassAutoEncryption(true)
  1231  					cpt := setup(mt, autoEncryptionOpts, nil, nil)
  1232  					defer cpt.teardown(mt)
  1233  
  1234  					// Insert key vault data so the key can be accessed when starting the change stream.
  1235  					insertDocuments(mt, cpt.keyVaultColl, testConfig.KeyVaultData)
  1236  
  1237  					stream, err := getWatcher(mt, tc.streamType, cpt).Watch(context.Background(), mongo.Pipeline{})
  1238  					assert.Nil(mt, err, "Watch error: %v", err)
  1239  					defer stream.Close(context.Background())
  1240  
  1241  					// Insert already encrypted data and verify that it is automatically decrypted by Next().
  1242  					insertDocuments(mt, cpt.coll, []bson.Raw{testConfig.EncryptedDocument})
  1243  					assert.True(mt, stream.Next(context.Background()), "expected Next to return true, got false")
  1244  					gotValue, err := stream.Current.LookupErr("fullDocument")
  1245  					assert.Nil(mt, err, "did not find fullDocument in stream.Current: %v", stream.Current)
  1246  					gotDocument := gotValue.Document()
  1247  					err = compareDocs(mt, testConfig.DecryptedDocument, gotDocument)
  1248  					assert.Nil(mt, err, "compareDocs error: %v", err)
  1249  				})
  1250  			}
  1251  		})
  1252  	})
  1253  	mt.RunOpts("9. deadlock tests", noClientOpts, func(mt *mtest.T) {
  1254  		testcases := []struct {
  1255  			description                            string
  1256  			maxPoolSize                            uint64
  1257  			bypassAutoEncryption                   bool
  1258  			keyVaultClientSet                      bool
  1259  			clientEncryptedTopologyOpeningExpected int
  1260  			clientEncryptedCommandStartedExpected  []startedEvent
  1261  			clientKeyVaultCommandStartedExpected   []startedEvent
  1262  		}{
  1263  			// In the following comments, "special auto encryption options" refers to the "bypassAutoEncryption" and
  1264  			// "keyVaultClient" options
  1265  			{
  1266  				// If the client has a limited maxPoolSize, and no special auto-encryption options are set, the
  1267  				// driver should create an internal Client for metadata/keyVault operations.
  1268  				"deadlock case 1", 1, false, false, 2,
  1269  				[]startedEvent{{"listCollections", "db"}, {"find", "keyvault"}, {"insert", "db"}, {"find", "db"}},
  1270  				nil,
  1271  			},
  1272  			{
  1273  				// If the client has a limited maxPoolSize, and a keyVaultClient is set, the driver should create
  1274  				// an internal Client for metadata operations.
  1275  				"deadlock case 2", 1, false, true, 2,
  1276  				[]startedEvent{{"listCollections", "db"}, {"insert", "db"}, {"find", "db"}},
  1277  				[]startedEvent{{"find", "keyvault"}},
  1278  			},
  1279  			{
  1280  				// If the client has a limited maxPoolSize, and a bypassAutomaticEncryption=true, the driver should
  1281  				// create an internal Client for keyVault operations.
  1282  				"deadlock case 3", 1, true, false, 2,
  1283  				[]startedEvent{{"find", "db"}, {"find", "keyvault"}},
  1284  				nil,
  1285  			},
  1286  			{
  1287  				// If the client has a limited maxPoolSize, bypassAutomaticEncryption=true, and a keyVaultClient is set,
  1288  				// the driver should not create an internal Client.
  1289  				"deadlock case 4", 1, true, true, 1,
  1290  				[]startedEvent{{"find", "db"}},
  1291  				[]startedEvent{{"find", "keyvault"}},
  1292  			},
  1293  			{
  1294  				// If the client has an unlimited maxPoolSize, and no special auto-encryption options are set,  the
  1295  				// driver should reuse the client for metadata/keyVault operations
  1296  				"deadlock case 5", 0, false, false, 1,
  1297  				[]startedEvent{{"listCollections", "db"}, {"listCollections", "keyvault"}, {"find", "keyvault"}, {"insert", "db"}, {"find", "db"}},
  1298  				nil,
  1299  			},
  1300  			{
  1301  				// If the client has an unlimited maxPoolSize, and a keyVaultClient is set, the driver should reuse the
  1302  				// client for metadata operations.
  1303  				"deadlock case 6", 0, false, true, 1,
  1304  				[]startedEvent{{"listCollections", "db"}, {"insert", "db"}, {"find", "db"}},
  1305  				[]startedEvent{{"find", "keyvault"}},
  1306  			},
  1307  			{
  1308  				// If the client has an unlimited maxPoolSize, and bypassAutomaticEncryption=true, the driver should
  1309  				// reuse the client for keyVault operations
  1310  				"deadlock case 7", 0, true, false, 1,
  1311  				[]startedEvent{{"find", "db"}, {"find", "keyvault"}},
  1312  				nil,
  1313  			},
  1314  			{
  1315  				// If the client has an unlimited maxPoolSize, bypassAutomaticEncryption=true, and a keyVaultClient is
  1316  				// set, the driver should not create an internal Client.
  1317  				"deadlock case 8", 0, true, true, 1,
  1318  				[]startedEvent{{"find", "db"}},
  1319  				[]startedEvent{{"find", "keyvault"}},
  1320  			},
  1321  		}
  1322  
  1323  		for _, tc := range testcases {
  1324  			mt.Run(tc.description, func(mt *mtest.T) {
  1325  				var clientEncryptedEvents []startedEvent
  1326  				var clientEncryptedTopologyOpening int
  1327  
  1328  				d := newDeadlockTest(mt)
  1329  				defer d.disconnect(mt)
  1330  
  1331  				kmsProviders := map[string]map[string]interface{}{
  1332  					"local": {"key": localMasterKey},
  1333  				}
  1334  				aeOpts := options.AutoEncryption()
  1335  				aeOpts.SetKeyVaultNamespace("keyvault.datakeys").
  1336  					SetKmsProviders(kmsProviders).
  1337  					SetBypassAutoEncryption(tc.bypassAutoEncryption)
  1338  
  1339  				// Only set the crypt_shared library extra options if bypassAutoEncryption isn't
  1340  				// true because it's invalid to set cryptSharedLibRequired=true and
  1341  				// bypassAutoEncryption=true together.
  1342  				if !tc.bypassAutoEncryption {
  1343  					aeOpts.SetExtraOptions(getCryptSharedLibExtraOptions())
  1344  				}
  1345  
  1346  				if tc.keyVaultClientSet {
  1347  					integtest.AddTestServerAPIVersion(d.clientKeyVaultOpts)
  1348  					aeOpts.SetKeyVaultClientOptions(d.clientKeyVaultOpts)
  1349  				}
  1350  
  1351  				ceOpts := options.Client().ApplyURI(mtest.ClusterURI()).
  1352  					SetMonitor(&event.CommandMonitor{
  1353  						Started: func(ctx context.Context, event *event.CommandStartedEvent) {
  1354  							clientEncryptedEvents = append(clientEncryptedEvents, startedEvent{event.CommandName, event.DatabaseName})
  1355  						},
  1356  					}).
  1357  					SetServerMonitor(&event.ServerMonitor{
  1358  						TopologyOpening: func(event *event.TopologyOpeningEvent) {
  1359  							clientEncryptedTopologyOpening++
  1360  						},
  1361  					}).
  1362  					SetMaxPoolSize(tc.maxPoolSize).
  1363  					SetAutoEncryptionOptions(aeOpts)
  1364  
  1365  				integtest.AddTestServerAPIVersion(ceOpts)
  1366  				clientEncrypted, err := mongo.Connect(context.Background(), ceOpts)
  1367  				assert.Nil(mt, err, "Connect error: %v", err)
  1368  				defer clientEncrypted.Disconnect(context.Background())
  1369  
  1370  				coll := clientEncrypted.Database("db").Collection("coll")
  1371  				if !tc.bypassAutoEncryption {
  1372  					_, err = coll.InsertOne(context.Background(), bson.M{"_id": 0, "encrypted": "string0"})
  1373  				} else {
  1374  					unencryptedColl := d.clientTest.Database("db").Collection("coll")
  1375  					_, err = unencryptedColl.InsertOne(context.Background(), bson.M{"_id": 0, "encrypted": d.ciphertext})
  1376  				}
  1377  				assert.Nil(mt, err, "InsertOne error: %v", err)
  1378  
  1379  				raw, err := coll.FindOne(context.Background(), bson.M{"_id": 0}).Raw()
  1380  				assert.Nil(mt, err, "FindOne error: %v", err)
  1381  
  1382  				expected := bsoncore.NewDocumentBuilder().
  1383  					AppendInt32("_id", 0).
  1384  					AppendString("encrypted", "string0").
  1385  					Build()
  1386  				assert.Equal(mt, bson.Raw(expected), raw, "returned value unequal, expected: %v, got: %v", expected, raw)
  1387  
  1388  				assert.Equal(mt, clientEncryptedEvents, tc.clientEncryptedCommandStartedExpected, "mismatched events for clientEncrypted. Expected %v, got %v", clientEncryptedEvents, tc.clientEncryptedCommandStartedExpected)
  1389  				assert.Equal(mt, d.clientKeyVaultEvents, tc.clientKeyVaultCommandStartedExpected, "mismatched events for clientKeyVault. Expected %v, got %v", d.clientKeyVaultEvents, tc.clientKeyVaultCommandStartedExpected)
  1390  				assert.Equal(mt, clientEncryptedTopologyOpening, tc.clientEncryptedTopologyOpeningExpected, "wrong number of TopologyOpening events. Expected %v, got %v", tc.clientEncryptedTopologyOpeningExpected, clientEncryptedTopologyOpening)
  1391  			})
  1392  		}
  1393  	})
  1394  
  1395  	// These tests only run when 3 KMS HTTP servers and 1 KMS KMIP server are running. See specification for port numbers and necessary arguments:
  1396  	// https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#kms-tls-options-tests
  1397  	mt.RunOpts("10. kms tls tests", noClientOpts, func(mt *mtest.T) {
  1398  		kmsTlsTestcase := os.Getenv("KMS_TLS_TESTCASE")
  1399  		if kmsTlsTestcase == "" {
  1400  			mt.Skipf("Skipping test as KMS_TLS_TESTCASE is not set")
  1401  		}
  1402  
  1403  		testcases := []struct {
  1404  			name       string
  1405  			port       int
  1406  			envValue   string
  1407  			errMessage string
  1408  		}{
  1409  			{
  1410  				"invalid certificate",
  1411  				9000,
  1412  				"INVALID_CERT",
  1413  				"expired",
  1414  			},
  1415  			{
  1416  				"invalid hostname",
  1417  				9001,
  1418  				"INVALID_HOSTNAME",
  1419  				"SANs",
  1420  			},
  1421  		}
  1422  
  1423  		for _, tc := range testcases {
  1424  			mt.Run(tc.name, func(mt *mtest.T) {
  1425  				// Only run test if correct KMS mock server is running.
  1426  				if kmsTlsTestcase != tc.envValue {
  1427  					mt.Skipf("Skipping test as KMS_TLS_TESTCASE is set to %q, expected %v", kmsTlsTestcase, tc.envValue)
  1428  				}
  1429  
  1430  				ceo := options.ClientEncryption().
  1431  					SetKmsProviders(fullKmsProvidersMap).
  1432  					SetKeyVaultNamespace(kvNamespace)
  1433  				cpt := setup(mt, nil, nil, ceo)
  1434  				defer cpt.teardown(mt)
  1435  
  1436  				_, err := cpt.clientEnc.CreateDataKey(context.Background(), "aws", options.DataKey().SetMasterKey(
  1437  					bson.D{
  1438  						{"region", "us-east-1"},
  1439  						{"key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"},
  1440  						{"endpoint", fmt.Sprintf("127.0.0.1:%d", tc.port)},
  1441  					},
  1442  				))
  1443  				assert.NotNil(mt, err, "expected CreateDataKey error, got nil")
  1444  				assert.True(mt, strings.Contains(err.Error(), tc.errMessage),
  1445  					"expected CreateDataKey error to contain %v, got %v", tc.errMessage, err.Error())
  1446  			})
  1447  		}
  1448  	})
  1449  
  1450  	// These tests only run when 3 KMS HTTP servers and 1 KMS KMIP server are running. See specification for port numbers and necessary arguments:
  1451  	// https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#kms-tls-options-tests
  1452  	mt.RunOpts("11. kms tls options tests", noClientOpts, func(mt *mtest.T) {
  1453  		if os.Getenv("KMS_MOCK_SERVERS_RUNNING") == "" {
  1454  			mt.Skipf("Skipping test as KMS_MOCK_SERVERS_RUNNING is not set")
  1455  		}
  1456  		validKmsProviders := map[string]map[string]interface{}{
  1457  			"aws": {
  1458  				"accessKeyId":     awsAccessKeyID,
  1459  				"secretAccessKey": awsSecretAccessKey,
  1460  			},
  1461  			"azure": {
  1462  				"tenantId":                 azureTenantID,
  1463  				"clientId":                 azureClientID,
  1464  				"clientSecret":             azureClientSecret,
  1465  				"identityPlatformEndpoint": "127.0.0.1:9002",
  1466  			},
  1467  			"gcp": {
  1468  				"email":      gcpEmail,
  1469  				"privateKey": gcpPrivateKey,
  1470  				"endpoint":   "127.0.0.1:9002",
  1471  			},
  1472  			"kmip": {
  1473  				"endpoint": "127.0.0.1:5698",
  1474  			},
  1475  		}
  1476  
  1477  		expiredKmsProviders := map[string]map[string]interface{}{
  1478  			"aws": {
  1479  				"accessKeyId":     awsAccessKeyID,
  1480  				"secretAccessKey": awsSecretAccessKey,
  1481  			},
  1482  			"azure": {
  1483  				"tenantId":                 azureTenantID,
  1484  				"clientId":                 azureClientID,
  1485  				"clientSecret":             azureClientSecret,
  1486  				"identityPlatformEndpoint": "127.0.0.1:9000",
  1487  			},
  1488  			"gcp": {
  1489  				"email":      gcpEmail,
  1490  				"privateKey": gcpPrivateKey,
  1491  				"endpoint":   "127.0.0.1:9000",
  1492  			},
  1493  			"kmip": {
  1494  				"endpoint": "127.0.0.1:9000",
  1495  			},
  1496  		}
  1497  
  1498  		invalidKmsProviders := map[string]map[string]interface{}{
  1499  			"aws": {
  1500  				"accessKeyId":     awsAccessKeyID,
  1501  				"secretAccessKey": awsSecretAccessKey,
  1502  			},
  1503  			"azure": {
  1504  				"tenantId":                 azureTenantID,
  1505  				"clientId":                 azureClientID,
  1506  				"clientSecret":             azureClientSecret,
  1507  				"identityPlatformEndpoint": "127.0.0.1:9001",
  1508  			},
  1509  			"gcp": {
  1510  				"email":      gcpEmail,
  1511  				"privateKey": gcpPrivateKey,
  1512  				"endpoint":   "127.0.0.1:9001",
  1513  			},
  1514  			"kmip": {
  1515  				"endpoint": "127.0.0.1:9001",
  1516  			},
  1517  		}
  1518  
  1519  		// create valid Client Encryption options without a client certificate
  1520  		validClientEncryptionOptionsWithoutClientCert := options.ClientEncryption().
  1521  			SetKmsProviders(validKmsProviders).
  1522  			SetKeyVaultNamespace(kvNamespace)
  1523  
  1524  		// make TLS opts containing client certificate and CA file
  1525  		tlsConfig := make(map[string]*tls.Config)
  1526  		if tlsCAFileKMIP != "" && tlsClientCertificateKeyFileKMIP != "" {
  1527  			clientAndCATlsMap := map[string]interface{}{
  1528  				"tlsCertificateKeyFile": tlsClientCertificateKeyFileKMIP,
  1529  				"tlsCAFile":             tlsCAFileKMIP,
  1530  			}
  1531  			certConfig, err := options.BuildTLSConfig(clientAndCATlsMap)
  1532  			assert.Nil(mt, err, "BuildTLSConfig error: %v", err)
  1533  			tlsConfig["aws"] = certConfig
  1534  			tlsConfig["azure"] = certConfig
  1535  			tlsConfig["gcp"] = certConfig
  1536  			tlsConfig["kmip"] = certConfig
  1537  		}
  1538  
  1539  		// create valid Client Encryption options and set valid TLS options
  1540  		validClientEncryptionOptionsWithTLS := options.ClientEncryption().
  1541  			SetKmsProviders(validKmsProviders).
  1542  			SetKeyVaultNamespace(kvNamespace).
  1543  			SetTLSConfig(tlsConfig)
  1544  
  1545  		// make TLS opts containing only CA file
  1546  		if tlsCAFileKMIP != "" {
  1547  			caTlsMap := map[string]interface{}{
  1548  				"tlsCAFile": tlsCAFileKMIP,
  1549  			}
  1550  			certConfig, err := options.BuildTLSConfig(caTlsMap)
  1551  			assert.Nil(mt, err, "BuildTLSConfig error: %v", err)
  1552  			tlsConfig["aws"] = certConfig
  1553  			tlsConfig["azure"] = certConfig
  1554  			tlsConfig["gcp"] = certConfig
  1555  			tlsConfig["kmip"] = certConfig
  1556  		}
  1557  
  1558  		// create invalid Client Encryption options with expired credentials
  1559  		expiredClientEncryptionOptions := options.ClientEncryption().
  1560  			SetKmsProviders(expiredKmsProviders).
  1561  			SetKeyVaultNamespace(kvNamespace).
  1562  			SetTLSConfig(tlsConfig)
  1563  
  1564  		// create invalid Client Encryption options with invalid hostnames
  1565  		invalidHostnameClientEncryptionOptions := options.ClientEncryption().
  1566  			SetKmsProviders(invalidKmsProviders).
  1567  			SetKeyVaultNamespace(kvNamespace).
  1568  			SetTLSConfig(tlsConfig)
  1569  
  1570  		awsMasterKeyNoClientCert := map[string]interface{}{
  1571  			"region":   "us-east-1",
  1572  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
  1573  			"endpoint": "127.0.0.1:9002",
  1574  		}
  1575  		awsMasterKeyWithTLS := map[string]interface{}{
  1576  			"region":   "us-east-1",
  1577  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
  1578  			"endpoint": "127.0.0.1:9002",
  1579  		}
  1580  		awsMasterKeyExpired := map[string]interface{}{
  1581  			"region":   "us-east-1",
  1582  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
  1583  			"endpoint": "127.0.0.1:9000",
  1584  		}
  1585  		awsMasterKeyInvalidHostname := map[string]interface{}{
  1586  			"region":   "us-east-1",
  1587  			"key":      "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
  1588  			"endpoint": "127.0.0.1:9001",
  1589  		}
  1590  		azureMasterKey := map[string]interface{}{
  1591  			"keyVaultEndpoint": "doesnotexist.local",
  1592  			"keyName":          "foo",
  1593  		}
  1594  		gcpMasterKey := map[string]interface{}{
  1595  			"projectId": "foo",
  1596  			"location":  "bar",
  1597  			"keyRing":   "baz",
  1598  			"keyName":   "foo",
  1599  		}
  1600  		kmipMasterKey := map[string]interface{}{}
  1601  
  1602  		testCases := []struct {
  1603  			name                     string
  1604  			masterKeyNoClientCert    interface{}
  1605  			masterKeyWithTLS         interface{}
  1606  			masterKeyExpired         interface{}
  1607  			masterKeyInvalidHostname interface{}
  1608  			tlsError                 string
  1609  			expiredError             string
  1610  			invalidHostnameError     string
  1611  		}{
  1612  			{"aws", awsMasterKeyNoClientCert, awsMasterKeyWithTLS, awsMasterKeyExpired, awsMasterKeyInvalidHostname, "parse error", "certificate has expired", "cannot validate certificate"},
  1613  			{"azure", azureMasterKey, azureMasterKey, azureMasterKey, azureMasterKey, "HTTP status=404", "certificate has expired", "cannot validate certificate"},
  1614  			{"gcp", gcpMasterKey, gcpMasterKey, gcpMasterKey, gcpMasterKey, "HTTP status=404", "certificate has expired", "cannot validate certificate"},
  1615  			{"kmip", kmipMasterKey, kmipMasterKey, kmipMasterKey, kmipMasterKey, "", "certificate has expired", "cannot validate certificate"},
  1616  		}
  1617  
  1618  		for _, tc := range testCases {
  1619  			mt.Run(tc.name, func(mt *mtest.T) {
  1620  				if tc.name == "kmip" && "" == os.Getenv("KMS_MOCK_SERVERS_RUNNING") {
  1621  					mt.Skipf("Skipping test as KMS_MOCK_SERVERS_RUNNING is not set")
  1622  				}
  1623  				// call CreateDataKey with CEO no TLS with each provider and corresponding master key
  1624  				cpt := setup(mt, nil, defaultKvClientOptions, validClientEncryptionOptionsWithoutClientCert)
  1625  				defer cpt.teardown(mt)
  1626  
  1627  				dkOpts := options.DataKey().SetMasterKey(tc.masterKeyNoClientCert)
  1628  				_, err := cpt.clientEnc.CreateDataKey(context.Background(), tc.name, dkOpts)
  1629  
  1630  				assert.NotNil(mt, err, "expected error, got nil")
  1631  				assert.True(mt, strings.Contains(err.Error(), "certificate signed by unknown authority"),
  1632  					"expected error '%s' to contain '%s'", err.Error(), "certificate signed by unknown authority")
  1633  
  1634  				// call CreateDataKey with CEO & TLS with each provider and corresponding master key
  1635  				cpt = setup(mt, nil, defaultKvClientOptions, validClientEncryptionOptionsWithTLS)
  1636  
  1637  				dkOpts = options.DataKey().SetMasterKey(tc.masterKeyWithTLS)
  1638  				_, err = cpt.clientEnc.CreateDataKey(context.Background(), tc.name, dkOpts)
  1639  				// check if current test case is KMIP, which should pass
  1640  				if tc.name == "kmip" {
  1641  					assert.Nil(mt, err, "expected no error, got err: %v", err)
  1642  				} else {
  1643  					assert.NotNil(mt, err, "expected error, got nil")
  1644  					assert.True(mt, strings.Contains(err.Error(), tc.tlsError),
  1645  						"expected error '%s' to contain '%s'", err.Error(), tc.tlsError)
  1646  				}
  1647  
  1648  				// call CreateDataKey with expired CEO each provider and same masterKey
  1649  				cpt = setup(mt, nil, defaultKvClientOptions, expiredClientEncryptionOptions)
  1650  
  1651  				dkOpts = options.DataKey().SetMasterKey(tc.masterKeyExpired)
  1652  				_, err = cpt.clientEnc.CreateDataKey(context.Background(), tc.name, dkOpts)
  1653  				assert.NotNil(mt, err, "expected error, got nil")
  1654  				assert.True(mt, strings.Contains(err.Error(), tc.expiredError),
  1655  					"expected error '%s' to contain '%s'", err.Error(), tc.expiredError)
  1656  
  1657  				// call CreateDataKey with invalid hostname CEO with each provider and same masterKey
  1658  				cpt = setup(mt, nil, defaultKvClientOptions, invalidHostnameClientEncryptionOptions)
  1659  
  1660  				dkOpts = options.DataKey().SetMasterKey(tc.masterKeyInvalidHostname)
  1661  				_, err = cpt.clientEnc.CreateDataKey(context.Background(), tc.name, dkOpts)
  1662  				assert.NotNil(mt, err, "expected error, got nil")
  1663  				assert.True(mt, strings.Contains(err.Error(), tc.invalidHostnameError),
  1664  					"expected error '%s' to contain '%s'", err.Error(), tc.invalidHostnameError)
  1665  			})
  1666  		}
  1667  	})
  1668  	runOpts := mtest.NewOptions().MinServerVersion("7.0").Topologies(mtest.ReplicaSet, mtest.LoadBalanced, mtest.ShardedReplicaSet)
  1669  	// Only test MongoDB Server 7.0+. MongoDB Server 7.0 introduced a backwards breaking change to the Queryable Encryption (QE) protocol: QEv2.
  1670  	// libmongocrypt is configured to use the QEv2 protocol.
  1671  	mt.RunOpts("12. explicit encryption", runOpts, func(mt *mtest.T) {
  1672  		// Test Setup ... begin
  1673  		encryptedFields := readJSONFile(mt, "encrypted-fields.json")
  1674  		key1Document := readJSONFile(mt, "key1-document.json")
  1675  		var key1ID primitive.Binary
  1676  		{
  1677  			subtype, data := key1Document.Lookup("_id").Binary()
  1678  			key1ID = primitive.Binary{Subtype: subtype, Data: data}
  1679  		}
  1680  
  1681  		testSetup := func() (*mongo.Client, *mongo.ClientEncryption) {
  1682  			mtest.DropEncryptedCollection(mt, mt.Client.Database("db").Collection("explicit_encryption"), encryptedFields)
  1683  			cco := options.CreateCollection().SetEncryptedFields(encryptedFields)
  1684  			err := mt.Client.Database("db").CreateCollection(context.Background(), "explicit_encryption", cco)
  1685  			assert.Nil(mt, err, "error on CreateCollection: %v", err)
  1686  			err = mt.Client.Database("keyvault").Collection("datakeys").Drop(context.Background())
  1687  			assert.Nil(mt, err, "error on Drop: %v", err)
  1688  			keyVaultClient, err := mongo.Connect(context.Background(), options.Client().ApplyURI(mtest.ClusterURI()))
  1689  			assert.Nil(mt, err, "error on Connect: %v", err)
  1690  			datakeysColl := keyVaultClient.Database("keyvault").Collection("datakeys", options.Collection().SetWriteConcern(mtest.MajorityWc))
  1691  			_, err = datakeysColl.InsertOne(context.Background(), key1Document)
  1692  			assert.Nil(mt, err, "error on InsertOne: %v", err)
  1693  			// Create a ClientEncryption.
  1694  			ceo := options.ClientEncryption().
  1695  				SetKeyVaultNamespace("keyvault.datakeys").
  1696  				SetKmsProviders(fullKmsProvidersMap)
  1697  			clientEncryption, err := mongo.NewClientEncryption(keyVaultClient, ceo)
  1698  			assert.Nil(mt, err, "error on NewClientEncryption: %v", err)
  1699  
  1700  			// Create a MongoClient with AutoEncryptionOpts and bypassQueryAnalysis=true.
  1701  			aeo := options.AutoEncryption().
  1702  				SetKeyVaultNamespace("keyvault.datakeys").
  1703  				SetKmsProviders(fullKmsProvidersMap).
  1704  				SetBypassQueryAnalysis(true)
  1705  			co := options.Client().SetAutoEncryptionOptions(aeo).ApplyURI(mtest.ClusterURI())
  1706  			encryptedClient, err := mongo.Connect(context.Background(), co)
  1707  			assert.Nil(mt, err, "error on Connect: %v", err)
  1708  			return encryptedClient, clientEncryption
  1709  		}
  1710  		// Test Setup ... end
  1711  
  1712  		mt.Run("case 1: can insert encrypted indexed and find", func(mt *mtest.T) {
  1713  			encryptedClient, clientEncryption := testSetup()
  1714  			defer clientEncryption.Close(context.Background())
  1715  			defer encryptedClient.Disconnect(context.Background())
  1716  
  1717  			// Explicit encrypt the value "encrypted indexed value" with algorithm: "Indexed".
  1718  			eo := options.Encrypt().SetAlgorithm("Indexed").SetKeyID(key1ID).SetContentionFactor(0)
  1719  			valueToEncrypt := "encrypted indexed value"
  1720  			rawVal := bson.RawValue{Type: bson.TypeString, Value: bsoncore.AppendString(nil, valueToEncrypt)}
  1721  			insertPayload, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1722  			assert.Nil(mt, err, "error in Encrypt: %v", err)
  1723  			// Insert.
  1724  			coll := encryptedClient.Database("db").Collection("explicit_encryption")
  1725  			_, err = coll.InsertOne(context.Background(), bson.D{{"_id", 1}, {"encryptedIndexed", insertPayload}})
  1726  			assert.Nil(mt, err, "Error in InsertOne: %v", err)
  1727  			// Explicit encrypt an indexed value to find.
  1728  			eo = options.Encrypt().SetAlgorithm("Indexed").SetKeyID(key1ID).SetQueryType(options.QueryTypeEquality).SetContentionFactor(0)
  1729  			findPayload, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1730  			assert.Nil(mt, err, "error in Encrypt: %v", err)
  1731  			// Find.
  1732  			res := coll.FindOne(context.Background(), bson.D{{"encryptedIndexed", findPayload}})
  1733  			assert.Nil(mt, res.Err(), "Error in FindOne: %v", res.Err())
  1734  			got, err := res.Raw()
  1735  			assert.Nil(mt, err, "error in Raw: %v", err)
  1736  			gotValue, err := got.LookupErr("encryptedIndexed")
  1737  			assert.Nil(mt, err, "error in LookupErr: %v", err)
  1738  			assert.Equal(mt, gotValue.StringValue(), valueToEncrypt, "expected %q, got %q", valueToEncrypt, gotValue.StringValue())
  1739  		})
  1740  		mt.Run("case 2: can insert encrypted indexed and find with non-zero contention", func(mt *mtest.T) {
  1741  			encryptedClient, clientEncryption := testSetup()
  1742  			defer clientEncryption.Close(context.Background())
  1743  			defer encryptedClient.Disconnect(context.Background())
  1744  
  1745  			coll := encryptedClient.Database("db").Collection("explicit_encryption")
  1746  			valueToEncrypt := "encrypted indexed value"
  1747  			rawVal := bson.RawValue{Type: bson.TypeString, Value: bsoncore.AppendString(nil, valueToEncrypt)}
  1748  
  1749  			for i := 0; i < 10; i++ {
  1750  				// Explicit encrypt the value "encrypted indexed value" with algorithm: "Indexed".
  1751  				eo := options.Encrypt().SetAlgorithm("Indexed").SetKeyID(key1ID).SetContentionFactor(10)
  1752  				insertPayload, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1753  				assert.Nil(mt, err, "error in Encrypt: %v", err)
  1754  				// Insert.
  1755  				_, err = coll.InsertOne(context.Background(), bson.D{{"_id", i}, {"encryptedIndexed", insertPayload}})
  1756  				assert.Nil(mt, err, "Error in InsertOne: %v", err)
  1757  			}
  1758  
  1759  			// Explicit encrypt an indexed value to find with default contentionFactor 0.
  1760  			{
  1761  				eo := options.Encrypt().SetAlgorithm("Indexed").SetKeyID(key1ID).SetQueryType(options.QueryTypeEquality).SetContentionFactor(0)
  1762  				findPayload, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1763  				assert.Nil(mt, err, "error in Encrypt: %v", err)
  1764  				// Find with contentionFactor=0.
  1765  				cursor, err := coll.Find(context.Background(), bson.D{{"encryptedIndexed", findPayload}})
  1766  				assert.Nil(mt, err, "error in Find: %v", err)
  1767  				var got []bson.Raw
  1768  				err = cursor.All(context.Background(), &got)
  1769  				assert.Nil(mt, err, "error in All: %v", err)
  1770  				assert.True(mt, len(got) < 10, "expected len(got) < 10, got: %v", len(got))
  1771  				for _, doc := range got {
  1772  					gotValue, err := doc.LookupErr("encryptedIndexed")
  1773  					assert.Nil(mt, err, "error in LookupErr: %v", err)
  1774  					assert.Equal(mt, gotValue.StringValue(), valueToEncrypt, "expected %q, got %q", valueToEncrypt, gotValue.StringValue())
  1775  				}
  1776  			}
  1777  
  1778  			// Explicit encrypt an indexed value to find with contentionFactor 10.
  1779  			{
  1780  				eo := options.Encrypt().SetAlgorithm("Indexed").SetKeyID(key1ID).SetQueryType(options.QueryTypeEquality).SetContentionFactor(10)
  1781  				findPayload2, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1782  				assert.Nil(mt, err, "error in Encrypt: %v", err)
  1783  				// Find with contentionFactor=10.
  1784  				cursor, err := coll.Find(context.Background(), bson.D{{"encryptedIndexed", findPayload2}})
  1785  				assert.Nil(mt, err, "error in Find: %v", err)
  1786  				var got []bson.Raw
  1787  				err = cursor.All(context.Background(), &got)
  1788  				assert.Nil(mt, err, "error in All: %v", err)
  1789  				assert.True(mt, len(got) == 10, "expected len(got) == 10, got: %v", len(got))
  1790  				for _, doc := range got {
  1791  					gotValue, err := doc.LookupErr("encryptedIndexed")
  1792  					assert.Nil(mt, err, "error in LookupErr: %v", err)
  1793  					assert.Equal(mt, gotValue.StringValue(), valueToEncrypt, "expected %q, got %q", valueToEncrypt, gotValue.StringValue())
  1794  				}
  1795  			}
  1796  		})
  1797  		mt.Run("case 3: can insert encrypted unindexed", func(mt *mtest.T) {
  1798  			encryptedClient, clientEncryption := testSetup()
  1799  			defer clientEncryption.Close(context.Background())
  1800  			defer encryptedClient.Disconnect(context.Background())
  1801  
  1802  			// Explicit encrypt the value "encrypted indexed value" with algorithm: "Indexed".
  1803  			eo := options.Encrypt().SetAlgorithm("Unindexed").SetKeyID(key1ID)
  1804  			valueToEncrypt := "encrypted unindexed value"
  1805  			rawVal := bson.RawValue{Type: bson.TypeString, Value: bsoncore.AppendString(nil, valueToEncrypt)}
  1806  			insertPayload, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1807  			assert.Nil(mt, err, "error in Encrypt: %v", err)
  1808  			// Insert.
  1809  			coll := encryptedClient.Database("db").Collection("explicit_encryption")
  1810  			_, err = coll.InsertOne(context.Background(), bson.D{{"_id", 1}, {"encryptedUnindexed", insertPayload}})
  1811  			assert.Nil(mt, err, "Error in InsertOne: %v", err)
  1812  			// Find.
  1813  			res := coll.FindOne(context.Background(), bson.D{{"_id", 1}})
  1814  			assert.Nil(mt, res.Err(), "Error in FindOne: %v", res.Err())
  1815  			got, err := res.Raw()
  1816  			assert.Nil(mt, err, "error in Raw: %v", err)
  1817  			gotValue, err := got.LookupErr("encryptedUnindexed")
  1818  			assert.Nil(mt, err, "error in LookupErr: %v", err)
  1819  			assert.Equal(mt, gotValue.StringValue(), valueToEncrypt, "expected %q, got %q", valueToEncrypt, gotValue.StringValue())
  1820  		})
  1821  		mt.Run("case 4: can roundtrip encrypted indexed", func(mt *mtest.T) {
  1822  			encryptedClient, clientEncryption := testSetup()
  1823  			defer clientEncryption.Close(context.Background())
  1824  			defer encryptedClient.Disconnect(context.Background())
  1825  
  1826  			// Explicit encrypt the value "encrypted indexed value" with algorithm: "Indexed".
  1827  			eo := options.Encrypt().SetAlgorithm("Indexed").SetKeyID(key1ID).SetContentionFactor(0)
  1828  			valueToEncrypt := "encrypted indexed value"
  1829  			rawVal := bson.RawValue{Type: bson.TypeString, Value: bsoncore.AppendString(nil, valueToEncrypt)}
  1830  			payload, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1831  			assert.Nil(mt, err, "error in Encrypt: %v", err)
  1832  			gotValue, err := clientEncryption.Decrypt(context.Background(), payload)
  1833  			assert.Nil(mt, err, "error in Decrypt: %v", err)
  1834  			assert.Equal(mt, gotValue.StringValue(), valueToEncrypt, "expected %q, got %q", valueToEncrypt, gotValue.StringValue())
  1835  		})
  1836  		mt.Run("case 5: can roundtrip encrypted unindexed", func(mt *mtest.T) {
  1837  			encryptedClient, clientEncryption := testSetup()
  1838  			defer clientEncryption.Close(context.Background())
  1839  			defer encryptedClient.Disconnect(context.Background())
  1840  
  1841  			// Explicit encrypt the value "encrypted indexed value" with algorithm: "Indexed".
  1842  			eo := options.Encrypt().SetAlgorithm("Unindexed").SetKeyID(key1ID)
  1843  			valueToEncrypt := "encrypted unindexed value"
  1844  			rawVal := bson.RawValue{Type: bson.TypeString, Value: bsoncore.AppendString(nil, valueToEncrypt)}
  1845  			payload, err := clientEncryption.Encrypt(context.Background(), rawVal, eo)
  1846  			assert.Nil(mt, err, "error in Encrypt: %v", err)
  1847  			gotValue, err := clientEncryption.Decrypt(context.Background(), payload)
  1848  			assert.Nil(mt, err, "error in Decrypt: %v", err)
  1849  			assert.Equal(mt, gotValue.StringValue(), valueToEncrypt, "expected %q, got %q", valueToEncrypt, gotValue.StringValue())
  1850  		})
  1851  	})
  1852  
  1853  	runOpts = mtest.NewOptions().MinServerVersion("4.2").
  1854  		Topologies(mtest.ReplicaSet, mtest.LoadBalanced, mtest.ShardedReplicaSet)
  1855  	mt.RunOpts("13. Unique Index on keyAltNames", runOpts, func(mt *mtest.T) {
  1856  		const (
  1857  			dkCollection  = "datakeys"
  1858  			idKey         = "_id"
  1859  			kvDatabase    = "keyvault"
  1860  			defKeyAltName = "def"
  1861  			abcKeyAltName = "abc"
  1862  		)
  1863  
  1864  		var cse *cseProseTest
  1865  
  1866  		var initialize = func() primitive.Binary {
  1867  			// Create a ClientEncryption object (referred to as client_encryption) with client set as the keyVaultClient.
  1868  			// Using client, drop the collection keyvault.datakeys.
  1869  			cse = setup(mt, nil, defaultKvClientOptions, options.ClientEncryption().
  1870  				SetKmsProviders(fullKmsProvidersMap).
  1871  				SetKeyVaultNamespace(kvNamespace))
  1872  
  1873  			err := cse.kvClient.Database(kvDatabase).Collection(dkCollection).Drop(context.Background())
  1874  			assert.Nil(mt, err, "error dropping %q namespace: %v", kvNamespace, err)
  1875  
  1876  			// Using client, create a unique index on keyAltNames with a partial index filter for only documents where
  1877  			// keyAltNames exists using writeConcern "majority".
  1878  			keyVaultIndex := mongo.IndexModel{
  1879  				Keys: bson.D{{"keyAltNames", 1}},
  1880  				Options: options.Index().
  1881  					SetUnique(true).
  1882  					SetName("keyAltNames_1").
  1883  					SetPartialFilterExpression(bson.D{
  1884  						{"keyAltNames", bson.D{
  1885  							{"$exists", true},
  1886  						}},
  1887  					}),
  1888  			}
  1889  
  1890  			wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second))
  1891  			wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority)
  1892  			wcmColl := cse.kvClient.Database(kvDatabase).Collection(dkCollection, wcMajorityCollectionOpts)
  1893  			_, err = wcmColl.Indexes().CreateOne(context.Background(), keyVaultIndex)
  1894  			assert.Nil(mt, err, "error creating keyAltNames index: %v", err)
  1895  
  1896  			// Using client_encryption, create a data key with a local KMS provider and the keyAltName "def".
  1897  			opts := options.DataKey().SetKeyAltNames([]string{defKeyAltName})
  1898  			defKeyID, err := cse.clientEnc.CreateDataKey(context.Background(), "local", opts)
  1899  			assert.Nil(mt, err, "error creating %q data key: %v", defKeyAltName, err)
  1900  			return defKeyID
  1901  		}
  1902  
  1903  		var validateAddKeyAltName = func(mt *mtest.T, cse *cseProseTest, res *mongo.SingleResult, expected ...string) {
  1904  			assert.Nil(mt, res.Err(), "error adding key alt name: %v", res.Err())
  1905  
  1906  			resbytes, err := res.Raw()
  1907  			assert.Nil(mt, err, "error decoding result bytes: %v", err)
  1908  
  1909  			idsubtype, iddata := bson.RawValue{Type: bsontype.EmbeddedDocument, Value: resbytes}.
  1910  				Document().Lookup("_id").Binary()
  1911  			filter := bsoncore.NewDocumentBuilder().AppendBinary("_id", idsubtype, iddata).Build()
  1912  
  1913  			ctx := context.Background()
  1914  			updatedData, err := cse.keyVaultColl.FindOne(ctx, filter).Raw()
  1915  			assert.Nil(mt, err, "error decoding result bytes: %v", err)
  1916  
  1917  			updated := bson.RawValue{Type: bsontype.EmbeddedDocument, Value: updatedData}
  1918  			updatedKeyAltNames, err := updated.Document().Lookup("keyAltNames").Array().Values()
  1919  			assert.Nil(mt, err, "error looking up raw keyAltNames: %v", err)
  1920  			assert.Equal(mt, len(updatedKeyAltNames), len(expected), "expected raw keyAltNames length to be 1")
  1921  
  1922  			for idx, keyAltName := range updatedKeyAltNames {
  1923  				str := keyAltName.StringValue()
  1924  				assert.Equal(mt, str, expected[idx], "expected keyAltName to be %q, got: %q", expected[idx], str)
  1925  			}
  1926  		}
  1927  
  1928  		mt.Run("case 1: createKey()", func(mt *mtest.T) {
  1929  			initialize()
  1930  
  1931  			// Use client_encryption to create a new local data key with a keyAltName "abc" and assert the operation
  1932  			// does not fail.
  1933  			opts := options.DataKey().SetKeyAltNames([]string{abcKeyAltName})
  1934  			_, err := cse.clientEnc.CreateDataKey(context.Background(), "local", opts)
  1935  			assert.Nil(mt, err, "error creating %q data key: %v", abcKeyAltName, err)
  1936  
  1937  			// Repeat Step 1 and assert the operation fails due to a duplicate key server error (error code 11000).
  1938  			opts = options.DataKey().SetKeyAltNames([]string{abcKeyAltName})
  1939  			_, err = cse.clientEnc.CreateDataKey(context.Background(), "local", opts)
  1940  			assert.NotNil(mt, err, "duplicate %q key did not propagate expected error", abcKeyAltName)
  1941  
  1942  			e110000 := "E11000 duplicate key"
  1943  			correctError := strings.Contains(err.Error(), e110000)
  1944  			assert.True(t, correctError, "expected error to contain %q, got: %v", e110000, err)
  1945  
  1946  			// Use client_encryption to create a new local data key with a keyAltName "def" and assert the operation
  1947  			// fails due to a duplicate key server error (error code 11000).
  1948  			opts = options.DataKey().SetKeyAltNames([]string{defKeyAltName})
  1949  			_, err = cse.clientEnc.CreateDataKey(context.Background(), "local", opts)
  1950  			assert.NotNil(mt, err, "duplicate %q key did not propagate expected error", defKeyAltName)
  1951  
  1952  			e110000 = "E11000 duplicate key"
  1953  			correctError = strings.Contains(err.Error(), e110000)
  1954  			assert.True(t, correctError, "expected error to contain %q, got: %v", e110000, err)
  1955  		})
  1956  
  1957  		mt.Run("case 2: addKeyAltName()", func(t *mtest.T) {
  1958  			defKeyID := initialize()
  1959  
  1960  			var someNewKeyID primitive.Binary
  1961  			// Use client_encryption to create a new local data key and assert the operation does not fail.
  1962  			var err error
  1963  			someNewKeyID, err = cse.clientEnc.CreateDataKey(context.Background(), "local")
  1964  			assert.Nil(mt, err, "error creating data key: %v", err)
  1965  
  1966  			// Use client_encryption to add a keyAltName "abc" to the key created in Step 1 and assert the operation
  1967  			// does not fail.
  1968  			res := cse.clientEnc.AddKeyAltName(context.Background(), someNewKeyID, abcKeyAltName)
  1969  			validateAddKeyAltName(mt, cse, res, abcKeyAltName)
  1970  
  1971  			// Repeat Step 2, assert the operation does not fail, and assert the returned key document contains the
  1972  			// keyAltName "abc" added in Step 2.
  1973  			res = cse.clientEnc.AddKeyAltName(context.Background(), someNewKeyID, abcKeyAltName)
  1974  			validateAddKeyAltName(mt, cse, res, abcKeyAltName)
  1975  
  1976  			// Use client_encryption to add a keyAltName "def" to the key created in Step 1 and assert the operation
  1977  			// fails due to a duplicate key server error (error code 11000).
  1978  			res = cse.clientEnc.AddKeyAltName(context.Background(), someNewKeyID, defKeyAltName)
  1979  			assert.NotNil(mt, res.Err(), "duplicate %q key did not propagate expected error", defKeyAltName)
  1980  
  1981  			e110000 := "E11000 duplicate key"
  1982  			correctError := strings.Contains(res.Err().Error(), e110000)
  1983  			assert.True(t, correctError, "expected error to contain %q, got: %v", e110000, res.Err())
  1984  
  1985  			// Use client_encryption to add a keyAltName "def" to the existing key, assert the operation does not fail,
  1986  			// and assert the returned key document contains the keyAltName "def" added during Setup.
  1987  			res = cse.clientEnc.AddKeyAltName(context.Background(), defKeyID, defKeyAltName)
  1988  			validateAddKeyAltName(mt, cse, res, defKeyAltName)
  1989  		})
  1990  
  1991  	})
  1992  
  1993  	mt.RunOpts("16. Rewrap", runOpts, func(mt *mtest.T) {
  1994  		mt.Run("Case 1: Rewrap with separate ClientEncryption", func(mt *mtest.T) {
  1995  			dataKeyMap := map[string]bson.M{
  1996  				"aws": {
  1997  					"region": "us-east-1",
  1998  					"key":    "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
  1999  				},
  2000  				"azure": {
  2001  					"keyVaultEndpoint": "key-vault-csfle.vault.azure.net",
  2002  					"keyName":          "key-name-csfle",
  2003  				},
  2004  				"gcp": {
  2005  					"projectId": "devprod-drivers",
  2006  					"location":  "global",
  2007  					"keyRing":   "key-ring-csfle",
  2008  					"keyName":   "key-name-csfle",
  2009  				},
  2010  				"kmip": {},
  2011  			}
  2012  
  2013  			tlsConfig := make(map[string]*tls.Config)
  2014  			if tlsCAFileKMIP != "" && tlsClientCertificateKeyFileKMIP != "" {
  2015  				tlsOpts := map[string]interface{}{
  2016  					"tlsCertificateKeyFile": tlsClientCertificateKeyFileKMIP,
  2017  					"tlsCAFile":             tlsCAFileKMIP,
  2018  				}
  2019  				kmipConfig, err := options.BuildTLSConfig(tlsOpts)
  2020  				assert.Nil(mt, err, "BuildTLSConfig error: %v", err)
  2021  				tlsConfig["kmip"] = kmipConfig
  2022  			}
  2023  
  2024  			kmsProviders := []string{"local", "aws", "gcp", "azure", "kmip"}
  2025  			for _, srcProvider := range kmsProviders {
  2026  				for _, dstProvider := range kmsProviders {
  2027  					mt.Run(fmt.Sprintf("%s to %s", srcProvider, dstProvider), func(mt *mtest.T) {
  2028  						var err error
  2029  						// Drop the collection ``keyvault.datakeys``.
  2030  						{
  2031  							err = mt.Client.Database("keyvault").Collection("datakeys").Drop(context.Background())
  2032  							assert.Nil(mt, err, "error on Drop: %v", err)
  2033  						}
  2034  
  2035  						// Create a ``ClientEncryption`` object named ``clientEncryption1``.
  2036  						var clientEncryption1 *mongo.ClientEncryption
  2037  						{
  2038  							var keyVaultClient *mongo.Client
  2039  							{
  2040  								co := options.Client().ApplyURI(mtest.ClusterURI())
  2041  								keyVaultClient, err = mongo.Connect(context.Background(), co)
  2042  								defer keyVaultClient.Disconnect(context.Background())
  2043  								integtest.AddTestServerAPIVersion(co)
  2044  								assert.Nil(mt, err, "error on Connect: %v", err)
  2045  							}
  2046  							ceOpts := options.ClientEncryption().
  2047  								SetKeyVaultNamespace("keyvault.datakeys").
  2048  								SetKmsProviders(fullKmsProvidersMap).
  2049  								SetTLSConfig(tlsConfig)
  2050  							clientEncryption1, err = mongo.NewClientEncryption(keyVaultClient, ceOpts)
  2051  							assert.Nil(mt, err, "error in NewClientEncryption: %v", err)
  2052  							defer clientEncryption1.Close(context.Background())
  2053  						}
  2054  
  2055  						// Call ``clientEncryption1.createDataKey``.
  2056  						var keyID primitive.Binary
  2057  						{
  2058  							dkOpts := options.DataKey()
  2059  							if val, ok := dataKeyMap[srcProvider]; ok {
  2060  								dkOpts.SetMasterKey(val)
  2061  							}
  2062  							keyID, err = clientEncryption1.CreateDataKey(context.Background(), srcProvider, dkOpts)
  2063  							assert.Nil(mt, err, "error in CreateDataKey: %v", err)
  2064  						}
  2065  
  2066  						// Call ``clientEncryption1.encrypt`` with the value "test".
  2067  						var ciphertext primitive.Binary
  2068  						{
  2069  							t, value, err := bson.MarshalValue("test")
  2070  							assert.Nil(mt, err, "error in MarshalValue: %v", err)
  2071  							plaintext := bson.RawValue{Type: t, Value: value}
  2072  							eOpts := options.Encrypt().SetKeyID(keyID).SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")
  2073  							ciphertext, err = clientEncryption1.Encrypt(context.Background(), plaintext, eOpts)
  2074  							assert.Nil(mt, err, "error in Encrypt: %v", err)
  2075  						}
  2076  
  2077  						// Create a ``ClientEncryption`` object named ``clientEncryption2``.
  2078  						var clientEncryption2 *mongo.ClientEncryption
  2079  						{
  2080  							var keyVaultClient *mongo.Client
  2081  							{
  2082  								co := options.Client().ApplyURI(mtest.ClusterURI())
  2083  								keyVaultClient, err = mongo.Connect(context.Background(), co)
  2084  								defer keyVaultClient.Disconnect(context.Background())
  2085  								integtest.AddTestServerAPIVersion(co)
  2086  								assert.Nil(mt, err, "error on Connect: %v", err)
  2087  							}
  2088  							ceOpts := options.ClientEncryption().
  2089  								SetKeyVaultNamespace("keyvault.datakeys").
  2090  								SetKmsProviders(fullKmsProvidersMap).
  2091  								SetTLSConfig(tlsConfig)
  2092  							clientEncryption2, err = mongo.NewClientEncryption(keyVaultClient, ceOpts)
  2093  							assert.Nil(mt, err, "error in NewClientEncryption: %v", err)
  2094  							defer clientEncryption2.Close(context.Background())
  2095  						}
  2096  
  2097  						// Call ``clientEncryption2.rewrapManyDataKey`` with an empty ``filter``.
  2098  						{
  2099  							rwOpts := options.RewrapManyDataKey().SetProvider(dstProvider)
  2100  							if val, ok := dataKeyMap[dstProvider]; ok {
  2101  								rwOpts.SetMasterKey(val)
  2102  							}
  2103  							res, err := clientEncryption2.RewrapManyDataKey(context.Background(), bson.D{}, rwOpts)
  2104  							assert.Nil(mt, err, "error in RewrapManyDataKey: %v", err)
  2105  							assert.Equal(mt, res.BulkWriteResult.ModifiedCount, int64(1), "expected ModifiedCount of 1, got %v", res.BulkWriteResult.ModifiedCount)
  2106  						}
  2107  
  2108  						// Call ``clientEncryption1.decrypt`` with the ``ciphertext``.
  2109  						{
  2110  							plaintext, err := clientEncryption1.Decrypt(context.Background(), ciphertext)
  2111  							assert.Nil(mt, err, "error in Decrypt: %v", err)
  2112  							assert.Equal(mt, plaintext.StringValue(), "test", "expected plaintext 'test', got %q", plaintext.StringValue())
  2113  						}
  2114  
  2115  						// Call ``clientEncryption2.decrypt`` with the ``ciphertext``.
  2116  						{
  2117  							plaintext, err := clientEncryption2.Decrypt(context.Background(), ciphertext)
  2118  							assert.Nil(mt, err, "error in Decrypt: %v", err)
  2119  							assert.Equal(mt, plaintext.StringValue(), "test", "expected plaintext 'test', got %q", plaintext.StringValue())
  2120  						}
  2121  					})
  2122  				}
  2123  			}
  2124  		})
  2125  
  2126  		mt.Run("Case 2: RewrapManyDataKeyOpts.provider is not optional", func(mt *mtest.T) {
  2127  			var err error
  2128  			var clientEncryption *mongo.ClientEncryption
  2129  			{
  2130  				var keyVaultClient *mongo.Client
  2131  				{
  2132  					co := options.Client().ApplyURI(mtest.ClusterURI())
  2133  					keyVaultClient, err = mongo.Connect(context.Background(), co)
  2134  					defer keyVaultClient.Disconnect(context.Background())
  2135  					integtest.AddTestServerAPIVersion(co)
  2136  					assert.Nil(mt, err, "error on Connect: %v", err)
  2137  				}
  2138  				ceOpts := options.ClientEncryption().
  2139  					SetKeyVaultNamespace("keyvault.datakeys").
  2140  					SetKmsProviders(fullKmsProvidersMap)
  2141  				clientEncryption, err = mongo.NewClientEncryption(keyVaultClient, ceOpts)
  2142  				assert.Nil(mt, err, "error in NewClientEncryption: %v", err)
  2143  				defer clientEncryption.Close(context.Background())
  2144  			}
  2145  
  2146  			_, err = clientEncryption.RewrapManyDataKey(context.Background(), bson.D{}, options.RewrapManyDataKey().SetMasterKey(bson.D{}))
  2147  			assert.ErrorContains(mt, err, "expected 'Provider' to be set to identify type of 'MasterKey'")
  2148  		})
  2149  	})
  2150  
  2151  	mt.RunOpts("18. Azure IMDS Credentials", noClientOpts, func(mt *mtest.T) {
  2152  		buf := make([]byte, 0, 256)
  2153  		kmsProvidersMap := map[string]map[string]interface{}{
  2154  			"azure": {},
  2155  		}
  2156  		p, err := bson.MarshalAppend(buf[:0], kmsProvidersMap)
  2157  		assert.Nil(mt, err, "error in MarshalAppendWithRegistry: %v", err)
  2158  
  2159  		getClient := func(header http.Header) *http.Client {
  2160  			lt := &localTransport{
  2161  				header: header,
  2162  				rt:     http.DefaultTransport,
  2163  			}
  2164  			return &http.Client{
  2165  				Timeout:   30 * time.Second,
  2166  				Transport: lt,
  2167  			}
  2168  		}
  2169  
  2170  		mt.Run("Case 1: Success", func(mt *mtest.T) {
  2171  			opts := &mongocryptopts.MongoCryptOptions{
  2172  				KmsProviders: p,
  2173  				HTTPClient:   getClient(nil),
  2174  			}
  2175  			crypt, err := mongocrypt.NewMongoCrypt(opts)
  2176  			assert.Nil(mt, err, "error in NewMongoCrypt: %v", err)
  2177  			doc, err := crypt.GetKmsProviders(context.Background())
  2178  			assert.Nil(mt, err, "error in GetKmsProviders: %v", err)
  2179  			val, err := doc.LookupErr("azure")
  2180  			assert.Nil(mt, err, "error in LookupErr: %v", err)
  2181  			assert.Equal(mt, `{"accessToken": "magic-cookie"}`, val.String(), "expected accessToken, got %s", val.String())
  2182  		})
  2183  		mt.Run("Case 2: Empty JSON", func(mt *mtest.T) {
  2184  			header := make(http.Header)
  2185  			header.Set("X-MongoDB-HTTP-TestParams", "case=empty-json")
  2186  			opts := &mongocryptopts.MongoCryptOptions{
  2187  				KmsProviders: p,
  2188  				HTTPClient:   getClient(header),
  2189  			}
  2190  			crypt, err := mongocrypt.NewMongoCrypt(opts)
  2191  			assert.Nil(mt, err, "error in NewMongoCrypt: %v", err)
  2192  			_, err = crypt.GetKmsProviders(context.Background())
  2193  			assert.ErrorContains(mt, err, "got unexpected empty accessToken")
  2194  		})
  2195  		mt.Run("Case 3: Bad JSON", func(mt *mtest.T) {
  2196  			header := make(http.Header)
  2197  			header.Set("X-MongoDB-HTTP-TestParams", "case=bad-json")
  2198  			opts := &mongocryptopts.MongoCryptOptions{
  2199  				KmsProviders: p,
  2200  				HTTPClient:   getClient(header),
  2201  			}
  2202  			crypt, err := mongocrypt.NewMongoCrypt(opts)
  2203  			assert.Nil(mt, err, "error in NewMongoCrypt: %v", err)
  2204  			_, err = crypt.GetKmsProviders(context.Background())
  2205  			assert.ErrorContains(mt, err, "error reading body JSON")
  2206  		})
  2207  		mt.Run("Case 4: HTTP 404", func(mt *mtest.T) {
  2208  			header := make(http.Header)
  2209  			header.Set("X-MongoDB-HTTP-TestParams", "case=404")
  2210  			opts := &mongocryptopts.MongoCryptOptions{
  2211  				KmsProviders: p,
  2212  				HTTPClient:   getClient(header),
  2213  			}
  2214  			crypt, err := mongocrypt.NewMongoCrypt(opts)
  2215  			assert.Nil(mt, err, "error in NewMongoCrypt: %v", err)
  2216  			_, err = crypt.GetKmsProviders(context.Background())
  2217  			assert.ErrorContains(mt, err, "got StatusCode: 404")
  2218  		})
  2219  		mt.Run("Case 5: HTTP 500", func(mt *mtest.T) {
  2220  			header := make(http.Header)
  2221  			header.Set("X-MongoDB-HTTP-TestParams", "case=500")
  2222  			opts := &mongocryptopts.MongoCryptOptions{
  2223  				KmsProviders: p,
  2224  				HTTPClient:   getClient(header),
  2225  			}
  2226  			crypt, err := mongocrypt.NewMongoCrypt(opts)
  2227  			assert.Nil(mt, err, "error in NewMongoCrypt: %v", err)
  2228  			_, err = crypt.GetKmsProviders(context.Background())
  2229  			assert.ErrorContains(mt, err, "got StatusCode: 500")
  2230  		})
  2231  		mt.Run("Case 6: Slow Response", func(mt *mtest.T) {
  2232  			header := make(http.Header)
  2233  			header.Set("X-MongoDB-HTTP-TestParams", "case=slow")
  2234  			opts := &mongocryptopts.MongoCryptOptions{
  2235  				KmsProviders: p,
  2236  				HTTPClient:   getClient(header),
  2237  			}
  2238  			crypt, err := mongocrypt.NewMongoCrypt(opts)
  2239  			assert.Nil(mt, err, "error in NewMongoCrypt: %v", err)
  2240  			_, err = crypt.GetKmsProviders(context.Background())
  2241  
  2242  			possibleErrors := []string{
  2243  				"error reading response body: context deadline exceeded",    // <= 1.19 + RHEL & macOS
  2244  				"Client.Timeout or context cancellation while reading body", // > 1.20 on all OS
  2245  			}
  2246  
  2247  			assert.True(t, containsSubstring(possibleErrors, err.Error()),
  2248  				"expected possibleErrors=%v to contain %v, but it didn't",
  2249  				possibleErrors, err.Error())
  2250  		})
  2251  	})
  2252  
  2253  	mt.RunOpts("20. Bypass creating mongocryptd client when shared library is loaded",
  2254  		noClientOpts, func(mt *mtest.T) {
  2255  			cryptSharedLibPath := os.Getenv("CRYPT_SHARED_LIB_PATH")
  2256  			if cryptSharedLibPath == "" {
  2257  				mt.Skip("CRYPT_SHARED_LIB_PATH not set, skipping")
  2258  				return
  2259  			}
  2260  
  2261  			kmsProviders := map[string]map[string]interface{}{
  2262  				"local": {
  2263  					"key": localMasterKey,
  2264  				},
  2265  			}
  2266  
  2267  			// Listen for connections in a separate goroutine.
  2268  			listener := listenForConnections(t, func(c net.Conn) {
  2269  				mt.Fatalf("Unexpected connection created to mock mongocryptd goroutine")
  2270  				c.Close()
  2271  			})
  2272  			defer listener.Close()
  2273  
  2274  			uri := "mongodb://" + listener.Addr().String()
  2275  			mongocryptdSpawnArgs := map[string]interface{}{
  2276  				"mongocryptdURI":     uri,
  2277  				"cryptSharedLibPath": cryptSharedLibPath,
  2278  			}
  2279  
  2280  			aeo := options.AutoEncryption().SetKmsProviders(kmsProviders).
  2281  				SetExtraOptions(mongocryptdSpawnArgs)
  2282  			cliOpts := options.Client().ApplyURI(mtest.ClusterURI()).SetAutoEncryptionOptions(aeo)
  2283  			integtest.AddTestServerAPIVersion(cliOpts)
  2284  			encClient, err := mongo.Connect(context.Background(), cliOpts)
  2285  			assert.Nil(mt, err, "Connect error: %v", err)
  2286  			defer func() {
  2287  				err = encClient.Disconnect(context.Background())
  2288  				assert.Nil(mt, err, "encrypted client Disconnect error: %v", err)
  2289  			}()
  2290  
  2291  			// Run an Insert through the encrypted client to make sure mongocryptd is started ('insert' uses the
  2292  			// mongocryptd and will wait for it to be active).
  2293  			_, err = encClient.Database("db").Collection("coll").InsertOne(context.Background(), bson.D{{"unencrypted", "test"}})
  2294  			assert.Nil(mt, err, "InsertOne error: %v", err)
  2295  		})
  2296  
  2297  	// qeRunOpts are requirements for Queryable Encryption.
  2298  	qeRunOpts := mtest.NewOptions().MinServerVersion("7.0").Topologies(mtest.ReplicaSet, mtest.Sharded, mtest.LoadBalanced, mtest.ShardedReplicaSet)
  2299  	// Only test MongoDB Server 7.0+. MongoDB Server 7.0 introduced a backwards breaking change to the Queryable Encryption (QE) protocol: QEv2.
  2300  	// libmongocrypt is configured to use the QEv2 protocol.
  2301  	mt.RunOpts("21. automatic data encryption keys", qeRunOpts, func(mt *mtest.T) {
  2302  		setup := func() (*mongo.Client, *mongo.ClientEncryption, error) {
  2303  			opts := options.Client().ApplyURI(mtest.ClusterURI())
  2304  			client, err := mongo.Connect(context.Background(), opts)
  2305  			if err != nil {
  2306  				return nil, nil, err
  2307  			}
  2308  			client.Database("keyvault").Collection("datakeys").Drop(context.Background())
  2309  			client.Database("db").Drop(context.Background())
  2310  			ceo := options.ClientEncryption().
  2311  				SetKmsProviders(fullKmsProvidersMap).
  2312  				SetKeyVaultNamespace(kvNamespace)
  2313  			clientEnc, err := mongo.NewClientEncryption(client, ceo)
  2314  			if err != nil {
  2315  				return nil, nil, err
  2316  			}
  2317  			return client, clientEnc, nil
  2318  		}
  2319  
  2320  		type KMSProviderTestcase struct {
  2321  			kmsProvider string
  2322  			masterKey   *bson.D
  2323  		}
  2324  
  2325  		testcases := []KMSProviderTestcase{
  2326  			{
  2327  				kmsProvider: "local",
  2328  				masterKey:   nil,
  2329  			},
  2330  			{
  2331  				kmsProvider: "aws",
  2332  				masterKey: &bson.D{
  2333  					{"region", "us-east-1"},
  2334  					{"key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"},
  2335  				},
  2336  			},
  2337  		}
  2338  
  2339  		for _, tc := range testcases {
  2340  			mt.Run(tc.kmsProvider, func(mt *mtest.T) {
  2341  
  2342  				mt.Run("case 1: simple creation and validation", func(mt *mtest.T) {
  2343  					client, clientEnc, err := setup()
  2344  					assert.Nil(mt, err, "setup error: %v", err)
  2345  					defer func() {
  2346  						err := clientEnc.Close(context.Background())
  2347  						assert.Nil(mt, err, "error in Close")
  2348  					}()
  2349  
  2350  					var encryptedFields bson.Raw
  2351  					err = bson.UnmarshalExtJSON([]byte(`{
  2352  				"fields": [{
  2353  					"path": "ssn",
  2354  					"bsonType": "string",
  2355  					"keyId": null
  2356  				}]
  2357  			}`), true /* canonical */, &encryptedFields)
  2358  					assert.Nil(mt, err, "Unmarshal error: %v", err)
  2359  
  2360  					coll, _, err := clientEnc.CreateEncryptedCollection(
  2361  						context.Background(),
  2362  						client.Database("db"),
  2363  						"testing1", options.CreateCollection().SetEncryptedFields(encryptedFields),
  2364  						"local", nil,
  2365  					)
  2366  					assert.Nil(mt, err, "CreateCollection error: %v", err)
  2367  
  2368  					_, err = coll.InsertOne(context.Background(), bson.D{{"ssn", "123-45-6789"}})
  2369  					assert.ErrorContains(mt, err, "Document failed validation")
  2370  				})
  2371  				mt.Run("case 2: missing encryptedFields", func(mt *mtest.T) {
  2372  					client, clientEnc, err := setup()
  2373  					assert.Nil(mt, err, "setup error: %v", err)
  2374  					defer func() {
  2375  						err := clientEnc.Close(context.Background())
  2376  						assert.Nil(mt, err, "error in Close")
  2377  					}()
  2378  
  2379  					coll, _, err := clientEnc.CreateEncryptedCollection(
  2380  						context.Background(),
  2381  						client.Database("db"),
  2382  						"testing1", options.CreateCollection(),
  2383  						"local", nil,
  2384  					)
  2385  					assert.Nil(mt, coll, "expect nil collection")
  2386  					assert.EqualError(mt, err, "no EncryptedFields defined for the collection")
  2387  				})
  2388  				mt.Run("case 3: invalid keyId", func(mt *mtest.T) {
  2389  					client, clientEnc, err := setup()
  2390  					assert.Nil(mt, err, "setup error: %v", err)
  2391  					defer func() {
  2392  						err := clientEnc.Close(context.Background())
  2393  						assert.Nil(mt, err, "error in Close")
  2394  					}()
  2395  
  2396  					var encryptedFields bson.Raw
  2397  					err = bson.UnmarshalExtJSON([]byte(`{
  2398  				"fields": [{
  2399  					"path": "ssn",
  2400  					"bsonType": "string",
  2401  					"keyId": false
  2402  				}]
  2403  			}`), true /* canonical */, &encryptedFields)
  2404  					assert.Nil(mt, err, "Unmarshal error: %v", err)
  2405  
  2406  					_, _, err = clientEnc.CreateEncryptedCollection(
  2407  						context.Background(),
  2408  						client.Database("db"),
  2409  						"testing1", options.CreateCollection().SetEncryptedFields(encryptedFields),
  2410  						"local", nil,
  2411  					)
  2412  					assert.ErrorContains(mt, err, "BSON field 'create.encryptedFields.fields.keyId' is the wrong type 'bool', expected type 'binData'")
  2413  				})
  2414  				mt.Run("case 4: insert encrypted value", func(mt *mtest.T) {
  2415  					client, clientEnc, err := setup()
  2416  					assert.Nil(mt, err, "setup error: %v", err)
  2417  					defer func() {
  2418  						err := clientEnc.Close(context.Background())
  2419  						assert.Nil(mt, err, "error in Close")
  2420  					}()
  2421  
  2422  					var encryptedFields bson.Raw
  2423  					err = bson.UnmarshalExtJSON([]byte(`{
  2424  				"fields": [{
  2425  					"path": "ssn",
  2426  					"bsonType": "string",
  2427  					"keyId": null
  2428  				}]
  2429  			}`), true /* canonical */, &encryptedFields)
  2430  					assert.Nil(mt, err, "Unmarshal error: %v", err)
  2431  
  2432  					coll, ef, err := clientEnc.CreateEncryptedCollection(
  2433  						context.Background(),
  2434  						client.Database("db"),
  2435  						"testing1", options.CreateCollection().SetEncryptedFields(encryptedFields),
  2436  						"local", nil,
  2437  					)
  2438  					assert.Nil(mt, err, "CreateCollection error: %v", err)
  2439  
  2440  					keyid := ef["fields"].(bson.A)[0].(bson.M)["keyId"].(primitive.Binary)
  2441  					rawValueType, rawValueData, err := bson.MarshalValue("123-45-6789")
  2442  					assert.Nil(mt, err, "MarshalValue error: %v", err)
  2443  					rawValue := bson.RawValue{Type: rawValueType, Value: rawValueData}
  2444  					encryptionOpts := options.Encrypt().
  2445  						SetAlgorithm("Unindexed").
  2446  						SetKeyID(keyid)
  2447  					encryptedField, err := clientEnc.Encrypt(
  2448  						context.Background(),
  2449  						rawValue,
  2450  						encryptionOpts)
  2451  					assert.Nil(mt, err, "Encrypt error: %v", err)
  2452  
  2453  					_, err = coll.InsertOne(context.Background(), bson.D{{"ssn", encryptedField}})
  2454  					assert.Nil(mt, err, "InsertOne error: %v", err)
  2455  				})
  2456  			})
  2457  		}
  2458  	})
  2459  
  2460  	// GODRIVER-3123.  When we implement this feature, lower the min server version to 8.0.1
  2461  	qeRunOpts22 := qeRunOpts.MaxServerVersion("7.99.99")
  2462  	mt.RunOpts("22. range explicit encryption", qeRunOpts22, func(mt *mtest.T) {
  2463  		type testcase struct {
  2464  			typeStr       string
  2465  			field         string
  2466  			typeBson      bsontype.Type
  2467  			rangeOpts     options.RangeOptions
  2468  			zero          bson.RawValue
  2469  			six           bson.RawValue
  2470  			thirty        bson.RawValue
  2471  			twoHundred    bson.RawValue
  2472  			twoHundredOne bson.RawValue
  2473  		}
  2474  
  2475  		precision := int32(2)
  2476  
  2477  		d128_0, err := primitive.ParseDecimal128("0")
  2478  		assert.Nil(mt, err)
  2479  		d128_6, err := primitive.ParseDecimal128("6")
  2480  		assert.Nil(mt, err)
  2481  		d128_30, err := primitive.ParseDecimal128("30")
  2482  		assert.Nil(mt, err)
  2483  		d128_200, err := primitive.ParseDecimal128("200")
  2484  		assert.Nil(mt, err)
  2485  		d128_201, err := primitive.ParseDecimal128("201")
  2486  		assert.Nil(mt, err)
  2487  
  2488  		tests := []testcase{
  2489  			{
  2490  				typeStr:  "DecimalNoPrecision",
  2491  				field:    "encryptedDecimalNoPrecision",
  2492  				typeBson: bson.TypeDecimal128,
  2493  				rangeOpts: options.RangeOptions{
  2494  					Sparsity: 1,
  2495  				},
  2496  				zero:          bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_0)},
  2497  				six:           bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_6)},
  2498  				thirty:        bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_30)},
  2499  				twoHundred:    bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_200)},
  2500  				twoHundredOne: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_201)},
  2501  			},
  2502  			{
  2503  				typeStr:  "DecimalPrecision",
  2504  				field:    "encryptedDecimalPrecision",
  2505  				typeBson: bson.TypeDecimal128,
  2506  				rangeOpts: options.RangeOptions{
  2507  					Min:       &bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_0)},
  2508  					Max:       &bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_200)},
  2509  					Sparsity:  1,
  2510  					Precision: &precision,
  2511  				},
  2512  				zero:          bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_0)},
  2513  				six:           bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_6)},
  2514  				thirty:        bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_30)},
  2515  				twoHundred:    bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_200)},
  2516  				twoHundredOne: bson.RawValue{Type: bson.TypeDecimal128, Value: bsoncore.AppendDecimal128(nil, d128_201)},
  2517  			},
  2518  			{
  2519  				typeStr:  "DoubleNoPrecision",
  2520  				field:    "encryptedDoubleNoPrecision",
  2521  				typeBson: bson.TypeDouble,
  2522  				rangeOpts: options.RangeOptions{
  2523  					Sparsity: 1,
  2524  				},
  2525  				zero:          bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 0)},
  2526  				six:           bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 6)},
  2527  				thirty:        bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 30)},
  2528  				twoHundred:    bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 200)},
  2529  				twoHundredOne: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 201)},
  2530  			},
  2531  			{
  2532  				typeStr:  "DoublePrecision",
  2533  				field:    "encryptedDoublePrecision",
  2534  				typeBson: bson.TypeDouble,
  2535  				rangeOpts: options.RangeOptions{
  2536  					Min:       &bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 0)},
  2537  					Max:       &bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 200)},
  2538  					Sparsity:  1,
  2539  					Precision: &precision,
  2540  				},
  2541  				zero:          bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 0)},
  2542  				six:           bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 6)},
  2543  				thirty:        bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 30)},
  2544  				twoHundred:    bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 200)},
  2545  				twoHundredOne: bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 201)},
  2546  			},
  2547  			{
  2548  				typeStr:  "Date",
  2549  				field:    "encryptedDate",
  2550  				typeBson: bson.TypeDateTime,
  2551  				rangeOpts: options.RangeOptions{
  2552  					Min:      &bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 0)},
  2553  					Max:      &bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 200)},
  2554  					Sparsity: 1,
  2555  				},
  2556  				zero:          bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 0)},
  2557  				six:           bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 6)},
  2558  				thirty:        bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 30)},
  2559  				twoHundred:    bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 200)},
  2560  				twoHundredOne: bson.RawValue{Type: bson.TypeDateTime, Value: bsoncore.AppendDateTime(nil, 201)},
  2561  			},
  2562  			{
  2563  				typeStr:  "Int",
  2564  				field:    "encryptedInt",
  2565  				typeBson: bson.TypeInt32,
  2566  				rangeOpts: options.RangeOptions{
  2567  					Min:      &bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 0)},
  2568  					Max:      &bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 200)},
  2569  					Sparsity: 1,
  2570  				},
  2571  				zero:          bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 0)},
  2572  				six:           bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 6)},
  2573  				thirty:        bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 30)},
  2574  				twoHundred:    bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 200)},
  2575  				twoHundredOne: bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 201)},
  2576  			},
  2577  			{
  2578  				typeStr:  "Long",
  2579  				field:    "encryptedLong",
  2580  				typeBson: bson.TypeInt64,
  2581  				rangeOpts: options.RangeOptions{
  2582  					Min:      &bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 0)},
  2583  					Max:      &bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 200)},
  2584  					Sparsity: 1,
  2585  				},
  2586  				zero:          bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 0)},
  2587  				six:           bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 6)},
  2588  				thirty:        bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 30)},
  2589  				twoHundred:    bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 200)},
  2590  				twoHundredOne: bson.RawValue{Type: bson.TypeInt64, Value: bsoncore.AppendInt64(nil, 201)},
  2591  			},
  2592  		}
  2593  
  2594  		for _, test := range tests {
  2595  			mt.Run(test.typeStr, func(mt *mtest.T) {
  2596  				if test.typeStr == "DecimalNoPrecision" && mtest.ClusterTopologyKind() != mtest.ReplicaSet {
  2597  					mt.Skipf("Skipping DecimalNoPrecision tests on a non ReplicaSet topology. DecimalNoPrecision queries are expected to take a long time and may exceed the default mongos timeout")
  2598  				}
  2599  
  2600  				// Test Setup ... begin
  2601  				encryptedFields := readJSONFile(mt, fmt.Sprintf("range-encryptedFields-%v.json", test.typeStr))
  2602  				key1Document := readJSONFile(mt, "key1-document.json")
  2603  				var key1ID primitive.Binary
  2604  				{
  2605  					subtype, data := key1Document.Lookup("_id").Binary()
  2606  					key1ID = primitive.Binary{Subtype: subtype, Data: data}
  2607  				}
  2608  
  2609  				testSetup := func() (*mongo.Client, *mongo.ClientEncryption) {
  2610  					mtest.DropEncryptedCollection(mt, mt.Client.Database("db").Collection("explicit_encryption"), encryptedFields)
  2611  					cco := options.CreateCollection().SetEncryptedFields(encryptedFields)
  2612  					err := mt.Client.Database("db").CreateCollection(context.Background(), "explicit_encryption", cco)
  2613  					assert.Nil(mt, err, "error on CreateCollection: %v", err)
  2614  					err = mt.Client.Database("keyvault").Collection("datakeys").Drop(context.Background())
  2615  					assert.Nil(mt, err, "error on Drop: %v", err)
  2616  					keyVaultClient, err := mongo.Connect(context.Background(), options.Client().ApplyURI(mtest.ClusterURI()))
  2617  					assert.Nil(mt, err, "error on Connect: %v", err)
  2618  					datakeysColl := keyVaultClient.Database("keyvault").Collection("datakeys", options.Collection().SetWriteConcern(mtest.MajorityWc))
  2619  					_, err = datakeysColl.InsertOne(context.Background(), key1Document)
  2620  					assert.Nil(mt, err, "error on InsertOne: %v", err)
  2621  					// Create a ClientEncryption.
  2622  					ceo := options.ClientEncryption().
  2623  						SetKeyVaultNamespace("keyvault.datakeys").
  2624  						SetKmsProviders(fullKmsProvidersMap)
  2625  					clientEncryption, err := mongo.NewClientEncryption(keyVaultClient, ceo)
  2626  					assert.Nil(mt, err, "error on NewClientEncryption: %v", err)
  2627  
  2628  					// Create a MongoClient with AutoEncryptionOpts and bypassQueryAnalysis=true.
  2629  					aeo := options.AutoEncryption().
  2630  						SetKeyVaultNamespace("keyvault.datakeys").
  2631  						SetKmsProviders(fullKmsProvidersMap).
  2632  						SetBypassQueryAnalysis(true)
  2633  					co := options.Client().SetAutoEncryptionOptions(aeo).ApplyURI(mtest.ClusterURI())
  2634  					encryptedClient, err := mongo.Connect(context.Background(), co)
  2635  					assert.Nil(mt, err, "error on Connect: %v", err)
  2636  
  2637  					// Insert 0, 6, 30, and 200.
  2638  					coll := encryptedClient.Database("db").Collection("explicit_encryption")
  2639  					eo := options.Encrypt().
  2640  						SetAlgorithm("RangePreview").
  2641  						SetKeyID(key1ID).
  2642  						SetContentionFactor(0).
  2643  						SetRangeOptions(test.rangeOpts)
  2644  					// Insert 0.
  2645  					insertPayloadZero, err := clientEncryption.Encrypt(context.Background(), test.zero, eo)
  2646  					assert.Nil(mt, err, "error in Encrypt: %v", err)
  2647  					_, err = coll.InsertOne(context.Background(), bson.D{{"_id", 0}, {test.field, insertPayloadZero}})
  2648  					assert.Nil(mt, err, "error in InsertOne: %v", err)
  2649  					// Insert 6.
  2650  					insertPayloadSix, err := clientEncryption.Encrypt(context.Background(), test.six, eo)
  2651  					assert.Nil(mt, err, "error in Encrypt: %v", err)
  2652  					_, err = coll.InsertOne(context.Background(), bson.D{{"_id", 1}, {test.field, insertPayloadSix}})
  2653  					assert.Nil(mt, err, "error in InsertOne: %v", err)
  2654  					// Insert 30.
  2655  					insertPayloadThirty, err := clientEncryption.Encrypt(context.Background(), test.thirty, eo)
  2656  					assert.Nil(mt, err, "error in Encrypt: %v", err)
  2657  					_, err = coll.InsertOne(context.Background(), bson.D{{"_id", 2}, {test.field, insertPayloadThirty}})
  2658  					assert.Nil(mt, err, "error in InsertOne: %v", err)
  2659  					// Insert 200.
  2660  					insertPayloadTwoHundred, err := clientEncryption.Encrypt(context.Background(), test.twoHundred, eo)
  2661  					assert.Nil(mt, err, "error in Encrypt: %v", err)
  2662  					_, err = coll.InsertOne(context.Background(), bson.D{{"_id", 3}, {test.field, insertPayloadTwoHundred}})
  2663  					assert.Nil(mt, err, "error in InsertOne: %v", err)
  2664  
  2665  					return encryptedClient, clientEncryption
  2666  				}
  2667  				// Test Setup ... end
  2668  
  2669  				// checkCursorResults checks documents returned by a cursor.
  2670  				// Expects document i to have field `field` with value `values[i]`.
  2671  				// Expects exactly len(values) documents to be returned.
  2672  				checkCursorResults := func(cursor *mongo.Cursor, field string, values ...bson.RawValue) {
  2673  					for i, v := range values {
  2674  						assert.True(mt, cursor.Next(context.Background()), "expected Next true, got false. Expected document %v with value: %v", i, v)
  2675  						got, err := cursor.Current.LookupErr(test.field)
  2676  						assert.Nil(mt, err, "%v not found in document %v: %v", test.field, i, cursor.Current)
  2677  						assert.Equal(mt, v, got, "expected %v, got %v in document %v", v, got, i)
  2678  					}
  2679  					assert.False(mt, cursor.Next(context.Background()), "expected Next false, got true with document: %v", cursor.Current)
  2680  				}
  2681  
  2682  				mt.Run("Case 1: can decrypt a payload", func(mt *mtest.T) {
  2683  					encryptedClient, clientEncryption := testSetup()
  2684  					defer clientEncryption.Close(context.Background())
  2685  					defer encryptedClient.Disconnect(context.Background())
  2686  					eo := options.Encrypt().
  2687  						SetAlgorithm("RangePreview").
  2688  						SetKeyID(key1ID).
  2689  						SetContentionFactor(0).
  2690  						SetRangeOptions(test.rangeOpts)
  2691  					insertPayloadSix, err := clientEncryption.Encrypt(context.Background(), test.six, eo)
  2692  					assert.Nil(mt, err, "error in Encrypt: %v", err)
  2693  					got, err := clientEncryption.Decrypt(context.Background(), insertPayloadSix)
  2694  					assert.Nil(mt, err, "error in Decrypt: %v", err)
  2695  					assert.Equal(mt, test.six, got, "expected %v, got %v", test.six, got)
  2696  				})
  2697  
  2698  				mt.Run("Case 2: can find encrypted range and return the maximum", func(mt *mtest.T) {
  2699  					encryptedClient, clientEncryption := testSetup()
  2700  					defer clientEncryption.Close(context.Background())
  2701  					defer encryptedClient.Disconnect(context.Background())
  2702  					eo := options.Encrypt().
  2703  						SetAlgorithm("RangePreview").
  2704  						SetKeyID(key1ID).
  2705  						SetContentionFactor(0).
  2706  						SetQueryType("rangePreview").
  2707  						SetRangeOptions(test.rangeOpts)
  2708  
  2709  					expr := bson.M{
  2710  						"$and": bson.A{
  2711  							bson.M{
  2712  								test.field: bson.M{
  2713  									"$gte": test.six,
  2714  								},
  2715  							},
  2716  							bson.M{
  2717  								test.field: bson.M{
  2718  									"$lte": test.twoHundred,
  2719  								},
  2720  							},
  2721  						},
  2722  					}
  2723  
  2724  					// Encrypt.
  2725  					var encryptedExpr bson.Raw
  2726  					{
  2727  						err := clientEncryption.EncryptExpression(context.Background(), expr, &encryptedExpr, eo)
  2728  						assert.Nil(mt, err, "error in EncryptExpression: %v", err)
  2729  					}
  2730  
  2731  					coll := encryptedClient.Database("db").Collection("explicit_encryption")
  2732  					opts := options.Find().SetSort(bson.D{{"_id", 1}})
  2733  					cursor, err := coll.Find(context.Background(), encryptedExpr, opts)
  2734  					assert.Nil(mt, err, "error in coll.Find: %v", err)
  2735  					defer cursor.Close(context.Background())
  2736  
  2737  					checkCursorResults(cursor, test.field, test.six, test.thirty, test.twoHundred)
  2738  				})
  2739  
  2740  				mt.Run("Case 3: can find encrypted range and return the minimum", func(mt *mtest.T) {
  2741  					encryptedClient, clientEncryption := testSetup()
  2742  					defer clientEncryption.Close(context.Background())
  2743  					defer encryptedClient.Disconnect(context.Background())
  2744  					eo := options.Encrypt().
  2745  						SetAlgorithm("RangePreview").
  2746  						SetKeyID(key1ID).
  2747  						SetContentionFactor(0).
  2748  						SetQueryType("rangePreview").
  2749  						SetRangeOptions(test.rangeOpts)
  2750  
  2751  					expr := bson.M{
  2752  						"$and": bson.A{
  2753  							bson.M{
  2754  								test.field: bson.M{
  2755  									"$gte": test.zero,
  2756  								},
  2757  							},
  2758  							bson.M{
  2759  								test.field: bson.M{
  2760  									"$lte": test.six,
  2761  								},
  2762  							},
  2763  						},
  2764  					}
  2765  
  2766  					// Encrypt.
  2767  					var encryptedExpr bson.Raw
  2768  					{
  2769  						err := clientEncryption.EncryptExpression(context.Background(), expr, &encryptedExpr, eo)
  2770  						assert.Nil(mt, err, "error in EncryptExpression: %v", err)
  2771  					}
  2772  
  2773  					coll := encryptedClient.Database("db").Collection("explicit_encryption")
  2774  					opts := options.Find().SetSort(bson.D{{"_id", 1}})
  2775  					cursor, err := coll.Find(context.Background(), encryptedExpr, opts)
  2776  					assert.Nil(mt, err, "error in coll.Find: %v", err)
  2777  					defer cursor.Close(context.Background())
  2778  
  2779  					checkCursorResults(cursor, test.field, test.zero, test.six)
  2780  				})
  2781  
  2782  				mt.Run("Case 4: can find encrypted range with an open range query", func(mt *mtest.T) {
  2783  					encryptedClient, clientEncryption := testSetup()
  2784  					defer clientEncryption.Close(context.Background())
  2785  					defer encryptedClient.Disconnect(context.Background())
  2786  					eo := options.Encrypt().
  2787  						SetAlgorithm("RangePreview").
  2788  						SetKeyID(key1ID).
  2789  						SetContentionFactor(0).
  2790  						SetQueryType("rangePreview").
  2791  						SetRangeOptions(test.rangeOpts)
  2792  
  2793  					expr := bson.M{
  2794  						"$and": bson.A{
  2795  							bson.M{
  2796  								test.field: bson.M{
  2797  									"$gt": test.thirty,
  2798  								},
  2799  							},
  2800  						},
  2801  					}
  2802  
  2803  					// Encrypt.
  2804  					var encryptedExpr bson.Raw
  2805  					{
  2806  						err := clientEncryption.EncryptExpression(context.Background(), expr, &encryptedExpr, eo)
  2807  						assert.Nil(mt, err, "error in EncryptExpression: %v", err)
  2808  					}
  2809  
  2810  					coll := encryptedClient.Database("db").Collection("explicit_encryption")
  2811  					opts := options.Find().SetSort(bson.D{{"_id", 1}})
  2812  					cursor, err := coll.Find(context.Background(), encryptedExpr, opts)
  2813  					assert.Nil(mt, err, "error in coll.Find: %v", err)
  2814  					defer cursor.Close(context.Background())
  2815  
  2816  					checkCursorResults(cursor, test.field, test.twoHundred)
  2817  				})
  2818  
  2819  				mt.Run("Case 5: can run an aggregation expression inside $expr", func(mt *mtest.T) {
  2820  					encryptedClient, clientEncryption := testSetup()
  2821  					defer clientEncryption.Close(context.Background())
  2822  					defer encryptedClient.Disconnect(context.Background())
  2823  					eo := options.Encrypt().
  2824  						SetAlgorithm("RangePreview").
  2825  						SetKeyID(key1ID).
  2826  						SetContentionFactor(0).
  2827  						SetQueryType("rangePreview").
  2828  						SetRangeOptions(test.rangeOpts)
  2829  
  2830  					expr := bson.M{
  2831  						"$and": bson.A{
  2832  							bson.M{
  2833  								"$lt": bson.A{
  2834  									fmt.Sprintf("$%v", test.field),
  2835  									test.thirty,
  2836  								},
  2837  							},
  2838  						},
  2839  					}
  2840  
  2841  					// Encrypt.
  2842  					var encryptedExpr bson.Raw
  2843  					{
  2844  						err := clientEncryption.EncryptExpression(context.Background(), expr, &encryptedExpr, eo)
  2845  						assert.Nil(mt, err, "error in EncryptExpression: %v", err)
  2846  					}
  2847  
  2848  					coll := encryptedClient.Database("db").Collection("explicit_encryption")
  2849  					opts := options.Find().SetSort(bson.D{{"_id", 1}})
  2850  					cursor, err := coll.Find(context.Background(), bson.M{"$expr": encryptedExpr}, opts)
  2851  					assert.Nil(mt, err, "error in coll.Find: %v", err)
  2852  					defer cursor.Close(context.Background())
  2853  
  2854  					checkCursorResults(cursor, test.field, test.zero, test.six)
  2855  				})
  2856  
  2857  				if test.field != "encryptedDoubleNoPrecision" && test.field != "encryptedDecimalNoPrecision" {
  2858  					mt.Run("Case 6: encrypting a document greater than the maximum errors", func(mt *mtest.T) {
  2859  						encryptedClient, clientEncryption := testSetup()
  2860  						defer clientEncryption.Close(context.Background())
  2861  						defer encryptedClient.Disconnect(context.Background())
  2862  						eo := options.Encrypt().
  2863  							SetAlgorithm("RangePreview").
  2864  							SetKeyID(key1ID).
  2865  							SetContentionFactor(0).
  2866  							SetRangeOptions(test.rangeOpts)
  2867  
  2868  						_, err := clientEncryption.Encrypt(context.Background(), test.twoHundredOne, eo)
  2869  						assert.NotNil(mt, err, "expected error, but got none")
  2870  					})
  2871  
  2872  					mt.Run("Case 7: encrypting a document of a different type errors", func(mt *mtest.T) {
  2873  						encryptedClient, clientEncryption := testSetup()
  2874  						defer clientEncryption.Close(context.Background())
  2875  						defer encryptedClient.Disconnect(context.Background())
  2876  						eo := options.Encrypt().
  2877  							SetAlgorithm("RangePreview").
  2878  							SetKeyID(key1ID).
  2879  							SetContentionFactor(0).
  2880  							SetRangeOptions(test.rangeOpts)
  2881  
  2882  						var val bson.RawValue
  2883  						if test.field == "encryptedInt" {
  2884  							val = bson.RawValue{Type: bson.TypeDouble, Value: bsoncore.AppendDouble(nil, 6)}
  2885  						} else {
  2886  							val = bson.RawValue{Type: bson.TypeInt32, Value: bsoncore.AppendInt32(nil, 6)}
  2887  						}
  2888  
  2889  						_, err := clientEncryption.Encrypt(context.Background(), val, eo)
  2890  						assert.NotNil(mt, err, "expected error, but got none")
  2891  					})
  2892  				}
  2893  
  2894  				if test.field != "encryptedDoubleNoPrecision" && test.field != "encryptedDoublePrecision" && test.field != "encryptedDecimalNoPrecision" && test.field != "encryptedDecimalPrecision" {
  2895  					mt.Run("Case 8: setting precision errors if the type is not a double", func(mt *mtest.T) {
  2896  						encryptedClient, clientEncryption := testSetup()
  2897  						defer clientEncryption.Close(context.Background())
  2898  						defer encryptedClient.Disconnect(context.Background())
  2899  
  2900  						// Copy rangeOpts and set precision.
  2901  						ro := test.rangeOpts
  2902  						ro.SetPrecision(2)
  2903  						eo := options.Encrypt().
  2904  							SetAlgorithm("RangePreview").
  2905  							SetKeyID(key1ID).
  2906  							SetContentionFactor(0).
  2907  							SetRangeOptions(ro)
  2908  
  2909  						_, err := clientEncryption.Encrypt(context.Background(), test.six, eo)
  2910  						assert.NotNil(mt, err, "expected error, but got none")
  2911  					})
  2912  				}
  2913  			})
  2914  		}
  2915  	})
  2916  }
  2917  
  2918  func getWatcher(mt *mtest.T, streamType mongo.StreamType, cpt *cseProseTest) watcher {
  2919  	mt.Helper()
  2920  
  2921  	switch streamType {
  2922  	case mongo.ClientStream:
  2923  		return cpt.cseClient
  2924  	case mongo.DatabaseStream:
  2925  		return cpt.cseColl.Database()
  2926  	case mongo.CollectionStream:
  2927  		return cpt.cseColl
  2928  	default:
  2929  		mt.Fatalf("unknown stream type %v", streamType)
  2930  	}
  2931  	return nil
  2932  }
  2933  
  2934  type cseProseTest struct {
  2935  	coll         *mongo.Collection // collection db.coll
  2936  	kvClient     *mongo.Client
  2937  	keyVaultColl *mongo.Collection
  2938  	cseClient    *mongo.Client     // encrypted client
  2939  	cseColl      *mongo.Collection // db.coll with encrypted client
  2940  	clientEnc    *mongo.ClientEncryption
  2941  	cseStarted   []*event.CommandStartedEvent
  2942  }
  2943  
  2944  func setup(mt *mtest.T, aeo *options.AutoEncryptionOptions, kvClientOpts *options.ClientOptions,
  2945  	ceo *options.ClientEncryptionOptions) *cseProseTest {
  2946  	mt.Helper()
  2947  	var cpt cseProseTest
  2948  	var err error
  2949  	cpt.coll = mt.CreateCollection(mtest.Collection{
  2950  		Name: "coll",
  2951  		DB:   "db",
  2952  		Opts: options.Collection().SetWriteConcern(mtest.MajorityWc),
  2953  	}, false)
  2954  	cpt.keyVaultColl = mt.CreateCollection(mtest.Collection{
  2955  		Name: "datakeys",
  2956  		DB:   "keyvault",
  2957  		Opts: options.Collection().SetWriteConcern(mtest.MajorityWc),
  2958  	}, false)
  2959  
  2960  	if aeo != nil {
  2961  		cseMonitor := &event.CommandMonitor{
  2962  			Started: func(_ context.Context, evt *event.CommandStartedEvent) {
  2963  				cpt.cseStarted = append(cpt.cseStarted, evt)
  2964  			},
  2965  		}
  2966  		opts := options.Client().ApplyURI(mtest.ClusterURI()).SetWriteConcern(mtest.MajorityWc).
  2967  			SetReadPreference(mtest.PrimaryRp).SetAutoEncryptionOptions(aeo).SetMonitor(cseMonitor)
  2968  		integtest.AddTestServerAPIVersion(opts)
  2969  		cpt.cseClient, err = mongo.Connect(context.Background(), opts)
  2970  		assert.Nil(mt, err, "Connect error for encrypted client: %v", err)
  2971  		cpt.cseColl = cpt.cseClient.Database("db").Collection("coll")
  2972  	}
  2973  	if ceo != nil {
  2974  		cpt.kvClient, err = mongo.Connect(context.Background(), kvClientOpts)
  2975  		assert.Nil(mt, err, "Connect error for ClientEncryption key vault client: %v", err)
  2976  		cpt.clientEnc, err = mongo.NewClientEncryption(cpt.kvClient, ceo)
  2977  		assert.Nil(mt, err, "NewClientEncryption error: %v", err)
  2978  	}
  2979  	return &cpt
  2980  }
  2981  
  2982  func (cpt *cseProseTest) teardown(mt *mtest.T) {
  2983  	mt.Helper()
  2984  
  2985  	if cpt.cseClient != nil {
  2986  		_ = cpt.cseClient.Disconnect(context.Background())
  2987  	}
  2988  	if cpt.clientEnc != nil {
  2989  		_ = cpt.clientEnc.Close(context.Background())
  2990  	}
  2991  }
  2992  
  2993  func readJSONFile(mt *mtest.T, file string) bson.Raw {
  2994  	mt.Helper()
  2995  
  2996  	content, err := ioutil.ReadFile(filepath.Join(clientEncryptionProseDir, file))
  2997  	assert.Nil(mt, err, "ReadFile error for %v: %v", file, err)
  2998  
  2999  	var doc bson.Raw
  3000  	err = bson.UnmarshalExtJSON(content, true, &doc)
  3001  	assert.Nil(mt, err, "UnmarshalExtJSON error for file %v: %v", file, err)
  3002  	return doc
  3003  }
  3004  
  3005  func decodeJSONFile(mt *mtest.T, file string, val interface{}) bson.Raw {
  3006  	mt.Helper()
  3007  
  3008  	content, err := ioutil.ReadFile(filepath.Join(clientEncryptionProseDir, file))
  3009  	assert.Nil(mt, err, "ReadFile error for %v: %v", file, err)
  3010  
  3011  	var doc bson.Raw
  3012  	err = bson.UnmarshalExtJSON(content, true, val)
  3013  	assert.Nil(mt, err, "UnmarshalExtJSON error for file %v: %v", file, err)
  3014  	return doc
  3015  }
  3016  
  3017  func rawValueToCoreValue(rv bson.RawValue) bsoncore.Value {
  3018  	return bsoncore.Value{Type: rv.Type, Data: rv.Value}
  3019  }
  3020  
  3021  type deadlockTest struct {
  3022  	clientTest           *mongo.Client
  3023  	clientKeyVaultOpts   *options.ClientOptions
  3024  	clientKeyVaultEvents []startedEvent
  3025  	clientEncryption     *mongo.ClientEncryption
  3026  	ciphertext           primitive.Binary
  3027  }
  3028  
  3029  type startedEvent struct {
  3030  	Command  string
  3031  	Database string
  3032  }
  3033  
  3034  func newDeadlockTest(mt *mtest.T) *deadlockTest {
  3035  	mt.Helper()
  3036  
  3037  	var d deadlockTest
  3038  	var err error
  3039  
  3040  	clientTestOpts := options.Client().ApplyURI(mtest.ClusterURI()).SetWriteConcern(mtest.MajorityWc)
  3041  	integtest.AddTestServerAPIVersion(clientTestOpts)
  3042  	if d.clientTest, err = mongo.Connect(context.Background(), clientTestOpts); err != nil {
  3043  		mt.Fatalf("Connect error: %v", err)
  3044  	}
  3045  
  3046  	clientKeyVaultMonitor := &event.CommandMonitor{
  3047  		Started: func(ctx context.Context, event *event.CommandStartedEvent) {
  3048  			startedEvent := startedEvent{event.CommandName, event.DatabaseName}
  3049  			d.clientKeyVaultEvents = append(d.clientKeyVaultEvents, startedEvent)
  3050  		},
  3051  	}
  3052  
  3053  	d.clientKeyVaultOpts = options.Client().ApplyURI(mtest.ClusterURI()).
  3054  		SetMaxPoolSize(1).SetMonitor(clientKeyVaultMonitor)
  3055  
  3056  	keyvaultColl := d.clientTest.Database("keyvault").Collection("datakeys")
  3057  	dataColl := d.clientTest.Database("db").Collection("coll")
  3058  	err = dataColl.Drop(context.Background())
  3059  	assert.Nil(mt, err, "Drop error for collection db.coll: %v", err)
  3060  
  3061  	err = keyvaultColl.Drop(context.Background())
  3062  	assert.Nil(mt, err, "Drop error for key vault collection: %v", err)
  3063  
  3064  	keyDoc := readJSONFile(mt, "external-key.json")
  3065  	_, err = keyvaultColl.InsertOne(context.Background(), keyDoc)
  3066  	assert.Nil(mt, err, "InsertOne error into key vault collection: %v", err)
  3067  
  3068  	schemaDoc := readJSONFile(mt, "external-schema.json")
  3069  	createOpts := options.CreateCollection().SetValidator(bson.M{"$jsonSchema": schemaDoc})
  3070  	err = d.clientTest.Database("db").CreateCollection(context.Background(), "coll", createOpts)
  3071  	assert.Nil(mt, err, "CreateCollection error: %v", err)
  3072  
  3073  	kmsProviders := map[string]map[string]interface{}{
  3074  		"local": {"key": localMasterKey},
  3075  	}
  3076  	ceOpts := options.ClientEncryption().SetKmsProviders(kmsProviders).SetKeyVaultNamespace("keyvault.datakeys")
  3077  	d.clientEncryption, err = mongo.NewClientEncryption(d.clientTest, ceOpts)
  3078  	assert.Nil(mt, err, "NewClientEncryption error: %v", err)
  3079  
  3080  	t, value, err := bson.MarshalValue("string0")
  3081  	assert.Nil(mt, err, "MarshalValue error: %v", err)
  3082  	in := bson.RawValue{Type: t, Value: value}
  3083  	eopts := options.Encrypt().SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").SetKeyAltName("local")
  3084  	d.ciphertext, err = d.clientEncryption.Encrypt(context.Background(), in, eopts)
  3085  	assert.Nil(mt, err, "Encrypt error: %v", err)
  3086  
  3087  	return &d
  3088  }
  3089  
  3090  func (d *deadlockTest) disconnect(mt *mtest.T) {
  3091  	mt.Helper()
  3092  	err := d.clientEncryption.Close(context.Background())
  3093  	assert.Nil(mt, err, "clientEncryption Close error: %v", err)
  3094  	d.clientTest.Disconnect(context.Background())
  3095  	assert.Nil(mt, err, "clientTest Disconnect error: %v", err)
  3096  }
  3097  
  3098  // listenForConnections creates a listener that will listen for connections.
  3099  // The user provided run function will be called with the accepted
  3100  // connection. The user is responsible for calling Close on the returned listener.
  3101  func listenForConnections(t *testing.T, run func(net.Conn)) net.Listener {
  3102  	t.Helper()
  3103  
  3104  	l, err := net.Listen("tcp", "localhost:0")
  3105  	if err != nil {
  3106  		t.Errorf("Could not set up a listener: %v", err)
  3107  		t.FailNow()
  3108  	}
  3109  	go func() {
  3110  		for {
  3111  			// Ignore errors due to closing the listener connection.
  3112  			c, _ := l.Accept()
  3113  			if c == nil {
  3114  				break
  3115  			}
  3116  			go run(c)
  3117  		}
  3118  	}()
  3119  	return l
  3120  }
  3121  
  3122  type localTransport struct {
  3123  	rt http.RoundTripper
  3124  
  3125  	header http.Header
  3126  }
  3127  
  3128  func (t *localTransport) RoundTrip(req *http.Request) (*http.Response, error) {
  3129  	r := req.Clone(req.Context())
  3130  	r.URL.Host = "localhost:8080"
  3131  	for key, vals := range t.header {
  3132  		for _, val := range vals {
  3133  			r.Header.Add(key, val)
  3134  		}
  3135  	}
  3136  	return t.rt.RoundTrip(r)
  3137  }
  3138  

View as plain text