From e95c34bf6b24352efad81b1f013a6113aa801921 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Thu, 10 Aug 2023 12:50:05 -0400 Subject: [PATCH] e2e wip --- .evergreen/config.yml | 50 ++--- Makefile | 4 + internal/test/searchindex/Makefile | 8 - internal/test/searchindex/mongodb/go.mod | 28 --- internal/test/searchindex/mongodb/go.sum | 59 ------ internal/test/searchindex/mongodb/main.go | 106 ---------- internal/test/searchindex/template.yaml | 58 ------ mongo/search_index_prose_test.go | 224 ++++++++++++++++++++++ 8 files changed, 255 insertions(+), 282 deletions(-) delete mode 100644 internal/test/searchindex/Makefile delete mode 100644 internal/test/searchindex/mongodb/go.mod delete mode 100644 internal/test/searchindex/mongodb/go.sum delete mode 100644 internal/test/searchindex/mongodb/main.go delete mode 100644 internal/test/searchindex/template.yaml create mode 100644 mongo/search_index_prose_test.go diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 6981c48646..f3f9d615ff 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -706,6 +706,17 @@ functions: params: file: lb-expansion.yml + run-search-index-tests: + - command: shell.exec + type: test + params: + shell: "bash" + working_dir: src/go.mongodb.org/mongo-driver + script: | + ${PREPARE_SHELL} + TEST_INDEX_URI="${TEST_INDEX_URI}" \ + make evg-test-search-index + stop-load-balancer: - command: shell.exec params: @@ -2271,24 +2282,13 @@ tasks: ${PREPARE_SHELL} ./.evergreen/run-deployed-lambda-aws-tests.sh - - name: "test-aws-searchindex-deployed" + - name: "test-search-index" commands: - - command: ec2.assume_role - params: - role_arn: ${LAMBDA_AWS_ROLE_ARN} - duration_seconds: 3600 - - command: shell.exec - params: - working_dir: src/go.mongodb.org/mongo-driver - shell: bash - add_expansions_to_env: true - env: - TEST_LAMBDA_DIRECTORY: ${PROJECT_DIRECTORY}/internal/test/searchindex - LAMBDA_STACK_NAME: dbx-go-lambda - AWS_REGION: us-east-1 - script: | - ${PREPARE_SHELL} - ./.evergreen/run-deployed-lambda-aws-tests.sh + - func: "bootstrap-mongo-orchestration" + vars: + VERSION: "latest" + TOPOLOGY: "replica_set" + - func: "run-search-index-tests" axes: - id: version @@ -2657,29 +2657,33 @@ task_groups: binary: bash add_expansions_to_env: true env: - LAMBDA_STACK_NAME: dbx-go-lambda - AWS_REGION: us-east-1 MONGODB_VERSION: "7.0" args: - ${DRIVERS_TOOLS}/.evergreen/atlas/setup-atlas-cluster.sh - command: expansions.update params: file: src/go.mongodb.org/mongo-driver/atlas-expansion.yml + - command: shell.exec + params: + working_dir: src/go.mongodb.org/mongo-driver + shell: bash + script: |- + echo "TEST_INDEX_URI: ${MONGODB_URI}" > atlas-expansion.yml + - command: expansions.update + params: + file: src/go.mongodb.org/mongo-driver/atlas-expansion.yml teardown_group: - command: subprocess.exec params: working_dir: src/go.mongodb.org/mongo-driver binary: bash add_expansions_to_env: true - env: - LAMBDA_STACK_NAME: dbx-go-lambda - AWS_REGION: us-east-1 args: - ${DRIVERS_TOOLS}/.evergreen/atlas/teardown-atlas-cluster.sh setup_group_can_fail_task: true setup_group_timeout_secs: 1800 tasks: - - test-aws-searchindex-deployed + - test-search-index buildvariants: - name: static-analysis diff --git a/Makefile b/Makefile index f3d3b88292..8c7b494e93 100644 --- a/Makefile +++ b/Makefile @@ -160,6 +160,10 @@ evg-test-load-balancers: go test $(BUILD_TAGS) ./mongo/integration -run TestLoadBalancerSupport -v -timeout $(TEST_TIMEOUT)s >> test.suite go test $(BUILD_TAGS) ./mongo/integration/unified -run TestUnifiedSpec -v -timeout $(TEST_TIMEOUT)s >> test.suite +.PHONY: evg-test-search-index +evg-test-search-index: + go test ./mongo -run TestSearchIndexProse -v -timeout $(TEST_TIMEOUT)s + .PHONY: evg-test-ocsp evg-test-ocsp: go test -v ./mongo -run TestOCSP $(OCSP_TLS_SHOULD_SUCCEED) >> test.suite diff --git a/internal/test/searchindex/Makefile b/internal/test/searchindex/Makefile deleted file mode 100644 index b374dc97b8..0000000000 --- a/internal/test/searchindex/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -.PHONY: default -default: - sam build --debug - # Cannot connect to a local mongo server on non x86_64 architectures. - # These cases require either building a mongodb docker container or - # using a serverless service such as Atlas. - sam local invoke --parameter-overrides "MongoDbUri=${MONGODB_URI}" - diff --git a/internal/test/searchindex/mongodb/go.mod b/internal/test/searchindex/mongodb/go.mod deleted file mode 100644 index 7ad90aad0b..0000000000 --- a/internal/test/searchindex/mongodb/go.mod +++ /dev/null @@ -1,28 +0,0 @@ -module go.mongodb.go/mongo-driver/internal/test/mongodb - -go 1.20 - -replace go.mongodb.org/mongo-driver => ../../../../ - -require ( - github.com/aws/aws-lambda-go v1.41.0 - github.com/google/uuid v1.3.0 - // Note that the Go driver version is replaced with the local Go driver code - // by the replace directive above. - go.mongodb.org/mongo-driver v1.11.7 -) - -require ( - github.com/golang/snappy v0.0.1 // indirect - github.com/klauspost/compress v1.13.6 // indirect - github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect - github.com/xdg-go/pbkdf2 v1.0.0 // indirect - github.com/xdg-go/scram v1.1.2 // indirect - github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/text v0.7.0 // indirect -) - -replace gopkg.in/yaml.v2 => gopkg.in/yaml.v2 v2.2.8 diff --git a/internal/test/searchindex/mongodb/go.sum b/internal/test/searchindex/mongodb/go.sum deleted file mode 100644 index 96fdb1799b..0000000000 --- a/internal/test/searchindex/mongodb/go.sum +++ /dev/null @@ -1,59 +0,0 @@ -github.com/aws/aws-lambda-go v1.41.0 h1:l/5fyVb6Ud9uYd411xdHZzSf2n86TakxzpvIoz7l+3Y= -github.com/aws/aws-lambda-go v1.41.0/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= -github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/test/searchindex/mongodb/main.go b/internal/test/searchindex/mongodb/main.go deleted file mode 100644 index 6fe7047d2c..0000000000 --- a/internal/test/searchindex/mongodb/main.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2023-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package main - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "os" - "time" - - "github.com/aws/aws-lambda-go/events" - "github.com/aws/aws-lambda-go/lambda" - "github.com/google/uuid" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" -) - -const timeout = 5 * time.Minute - -// response is the data we return in the body of the API Gateway response. -type response struct { - Index string `json:"index"` - Cursor string `json:"cursor"` -} - -// gateway500 is a convenience function for constructing a gateway response with -// a 500 status code, indicating an internal server error. -func gateway500() events.APIGatewayProxyResponse { - return events.APIGatewayProxyResponse{ - StatusCode: http.StatusInternalServerError, - Body: http.StatusText(http.StatusInternalServerError), - } - -} - -// handler is the AWS Lambda handler, executing at runtime. -func handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { - ctx, cancel := context.WithTimeout(ctx, timeout) - defer cancel() - - clientOptions := options.Client().ApplyURI(os.Getenv("MONGODB_URI")). - SetTimeout(timeout) - - // Create a MongoClient that points to MONGODB_URI and listens to the - // ComandMonitor, ServerMonitor, and PoolMonitor events. - client, err := mongo.Connect(ctx, clientOptions) - if err != nil { - return gateway500(), fmt.Errorf("failed to create client: %w", err) - } - defer client.Disconnect(ctx) - - db := client.Database("test") - collName := fmt.Sprintf("col%s", uuid.New().String()) - err = db.CreateCollection(ctx, collName) - if err != nil { - return gateway500(), fmt.Errorf("failed to create collection: %w", err) - } - - collection := client.Database("test").Collection(collName) - defer collection.Drop(ctx) - - view := collection.SearchIndexes() - searchName := "test-search-index" - index, err := view.CreateOne(ctx, mongo.SearchIndexModel{ - Definition: bson.D{{"mappings", bson.D{{"dynamic", false}}}}, - Name: &searchName, - }) - if err != nil { - return gateway500(), fmt.Errorf("failed to create index: %w", err) - } - - time.Sleep(20 * time.Second) - - cursor, err := view.List(ctx, nil, nil) - if err != nil { - return gateway500(), fmt.Errorf("failed to list: %w", err) - } - - rsp := &response{ - Index: index, - Cursor: cursor.Current.String(), - } - - body, err := json.Marshal(rsp) - if err != nil { - return gateway500(), fmt.Errorf("failed to marshal: %w", err) - } - - return events.APIGatewayProxyResponse{ - Body: string(body), - StatusCode: http.StatusOK, - }, nil -} - -func main() { - ctx := context.Background() - - lambda.StartWithOptions(handler, lambda.WithContext(ctx)) -} diff --git a/internal/test/searchindex/template.yaml b/internal/test/searchindex/template.yaml deleted file mode 100644 index 4750c1a680..0000000000 --- a/internal/test/searchindex/template.yaml +++ /dev/null @@ -1,58 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: > - Go Driver lambda function test - -Parameters: - MongoDbUri: - Type: String - Description: The MongoDB connection string. - -Globals: - Function: - Timeout: 30 - -Resources: - MongoDBFunction: - Type: AWS::Serverless::Function - Properties: - CodeUri: mongodb/ - Handler: mongodb - Runtime: go1.x - Architectures: - - x86_64 - Events: - MongoDB: - Type: Api - Properties: - Path: /mongodb - Method: GET - Environment: - Variables: - MONGODB_URI: !Ref MongoDbUri - - ApplicationResourceGroup: - Type: AWS::ResourceGroups::Group - Properties: - Name: - Fn::Sub: ApplicationInsights-SAM-${AWS::StackName} - ResourceQuery: - Type: CLOUDFORMATION_STACK_1_0 - ApplicationInsightsMonitoring: - Type: AWS::ApplicationInsights::Application - Properties: - ResourceGroupName: - Ref: ApplicationResourceGroup - AutoConfigurationEnabled: 'true' - -Outputs: - MongoDBApi: - Description: "API Gateway endpoint URL for Prod stage for MongoDB function" - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/mongodb/" - MongoDBFunction: - Description: "MongoDB Lambda Function ARN" - Value: !GetAtt MongoDBFunction.Arn - MongoDBFunctionIamRole: - Description: "Implicit IAM Role created for MongoDB function" - Value: !GetAtt MongoDBFunctionRole.Arn - diff --git a/mongo/search_index_prose_test.go b/mongo/search_index_prose_test.go new file mode 100644 index 0000000000..803418cce9 --- /dev/null +++ b/mongo/search_index_prose_test.go @@ -0,0 +1,224 @@ +package mongo + +import ( + "context" + "fmt" + "os" + "sync" + "testing" + "time" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/internal/assert" + "go.mongodb.org/mongo-driver/internal/uuid" + "go.mongodb.org/mongo-driver/mongo/options" +) + +func newTestCollection(t *testing.T, client *Client) *Collection { + t.Helper() + + id, err := uuid.New() + assert.NoError(t, err) + collName := fmt.Sprintf("col%s", id.String()) + return client.Database("test").Collection(collName) +} + +func getDocument(t *testing.T, ctx context.Context, view SearchIndexView, index string) bson.Raw { + t.Helper() + + for { + cursor, err := view.List(ctx, &index, nil) + assert.NoError(t, err, "failed to list") + + if !cursor.Next(ctx) { + return nil + } + if cursor.Current.Lookup("queryable").Boolean() { + return cursor.Current + } + t.Logf("cursor: %s, sleep 5 seconds...", cursor.Current.String()) + time.Sleep(5 * time.Second) + } +} + +func TestSearchIndexProse(t *testing.T) { + const timeout = 5 * time.Minute + + ctx := context.Background() + + uri := os.Getenv("TEST_INDEX_URI") + if uri == "" { + t.Skip("skipping") + } + clientOptions := options.Client().ApplyURI(uri).SetTimeout(timeout) + + client, err := Connect(ctx, clientOptions) + assert.NoError(t, err, "failed to connect %s", uri) + defer client.Disconnect(ctx) + + t.Run("case 1: Driver can successfully create and list search indexes", func(t *testing.T) { + ctx := context.Background() + + collection := newTestCollection(t, client) + defer collection.Drop(ctx) + + _, err = collection.InsertOne(ctx, bson.D{}) + assert.NoError(t, err, "failed to insert") + + view := collection.SearchIndexes() + + definition := bson.D{{"mappings", bson.D{{"dynamic", false}}}} + searchName := "test-search-index" + model := SearchIndexModel{ + Definition: definition, + Name: &searchName, + } + index, err := view.CreateOne(ctx, model) + assert.NoError(t, err, "failed to create index") + assert.Equal(t, searchName, index, "unmatched name") + + doc := getDocument(t, ctx, view, searchName) + assert.NotNil(t, doc, "got empty document") + assert.Equal(t, searchName, doc.Lookup("name").StringValue(), "unmatched name") + expected, err := bson.Marshal(definition) + assert.NoError(t, err, "failed to marshal definition") + actual := doc.Lookup("latestDefinition").Value + assert.Equal(t, expected, actual, "unmatched definition") + }) + + t.Run("case 2: Driver can successfully create multiple indexes in batch", func(t *testing.T) { + ctx := context.Background() + + collection := newTestCollection(t, client) + defer collection.Drop(ctx) + + _, err = collection.InsertOne(ctx, bson.D{}) + assert.NoError(t, err, "failed to insert") + + view := collection.SearchIndexes() + + definition := bson.D{{"mappings", bson.D{{"dynamic", false}}}} + searchName0 := "test-search-index-1" + searchName1 := "test-search-index-2" + models := []SearchIndexModel{ + { + Definition: definition, + Name: &searchName0, + }, + { + Definition: definition, + Name: &searchName1, + }, + } + indexes, err := view.CreateMany(ctx, models) + assert.NoError(t, err, "failed to create index") + assert.Equal(t, len(indexes), 2, "expected 2 indexes") + assert.Contains(t, indexes, searchName0) + assert.Contains(t, indexes, searchName1) + + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + + doc := getDocument(t, ctx, view, searchName0) + assert.NotNil(t, doc, "got empty document") + assert.Equal(t, searchName0, doc.Lookup("name").StringValue(), "unmatched name") + expected, err := bson.Marshal(definition) + assert.NoError(t, err, "failed to marshal definition") + actual := doc.Lookup("latestDefinition").Value + assert.Equal(t, expected, actual, "unmatched definition") + }() + go func() { + defer wg.Done() + + doc := getDocument(t, ctx, view, searchName1) + assert.NotNil(t, doc, "got empty document") + assert.Equal(t, searchName1, doc.Lookup("name").StringValue(), "unmatched name") + expected, err := bson.Marshal(definition) + assert.NoError(t, err, "failed to marshal definition") + actual := doc.Lookup("latestDefinition").Value + assert.Equal(t, expected, actual, "unmatched definition") + }() + wg.Wait() + }) + + t.Run("case 3: Driver can successfully drop search indexes", func(t *testing.T) { + ctx := context.Background() + + collection := newTestCollection(t, client) + defer collection.Drop(ctx) + + _, err = collection.InsertOne(ctx, bson.D{}) + assert.NoError(t, err, "failed to insert") + + view := collection.SearchIndexes() + + definition := bson.D{{"mappings", bson.D{{"dynamic", false}}}} + searchName := "test-search-index" + model := SearchIndexModel{ + Definition: definition, + Name: &searchName, + } + index, err := view.CreateOne(ctx, model) + assert.NoError(t, err, "failed to create index") + assert.Equal(t, searchName, index, "unmatched name") + + doc := getDocument(t, ctx, view, searchName) + assert.NotNil(t, doc, "got empty document") + assert.Equal(t, searchName, doc.Lookup("name").StringValue(), "unmatched name") + + err = view.DropOne(ctx, searchName) + assert.NoError(t, err, "failed to drop index") + doc = getDocument(t, ctx, view, searchName) + assert.Nil(t, doc, "expected empty document") + }) + + t.Run("case 4: Driver can update a search index", func(t *testing.T) { + ctx := context.Background() + + collection := newTestCollection(t, client) + defer collection.Drop(ctx) + + _, err = collection.InsertOne(ctx, bson.D{}) + assert.NoError(t, err, "failed to insert") + + view := collection.SearchIndexes() + + definition := bson.D{{"mappings", bson.D{{"dynamic", false}}}} + searchName := "test-search-index" + model := SearchIndexModel{ + Definition: definition, + Name: &searchName, + } + index, err := view.CreateOne(ctx, model) + assert.NoError(t, err, "failed to create index") + assert.Equal(t, searchName, index, "unmatched name") + + doc := getDocument(t, ctx, view, searchName) + assert.NotNil(t, doc, "got empty document") + assert.Equal(t, searchName, doc.Lookup("name").StringValue(), "unmatched name") + + definition = bson.D{{"mappings", bson.D{{"dynamic", true}}}} + err = view.UpdateOne(ctx, searchName, definition) + assert.NoError(t, err, "failed to drop index") + doc = getDocument(t, ctx, view, searchName) + assert.NotNil(t, doc, "got empty document") + assert.Equal(t, searchName, doc.Lookup("name").StringValue(), "unmatched name") + expected, err := bson.Marshal(definition) + assert.NoError(t, err, "failed to marshal definition") + actual := doc.Lookup("latestDefinition").Value + assert.Equal(t, expected, actual, "unmatched definition") + }) + + t.Run("case 5: dropSearchIndex suppresses namespace not found errors", func(t *testing.T) { + ctx := context.Background() + + collection := newTestCollection(t, client) + defer collection.Drop(ctx) + + view := collection.SearchIndexes() + err = view.DropOne(ctx, "foo") + assert.NoError(t, err, "failed to drop index") + }) +}