...

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

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

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package unified
     8  
     9  import (
    10  	"bytes"
    11  	"context"
    12  	"fmt"
    13  
    14  	"go.mongodb.org/mongo-driver/bson"
    15  	"go.mongodb.org/mongo-driver/internal/bsonutil"
    16  	"go.mongodb.org/mongo-driver/mongo/integration/mtest"
    17  	"go.mongodb.org/mongo-driver/mongo/options"
    18  	"go.mongodb.org/mongo-driver/mongo/readconcern"
    19  	"go.mongodb.org/mongo-driver/mongo/readpref"
    20  )
    21  
    22  type collectionData struct {
    23  	DatabaseName   string         `bson:"databaseName"`
    24  	CollectionName string         `bson:"collectionName"`
    25  	Documents      []bson.Raw     `bson:"documents"`
    26  	Options        *createOptions `bson:"createOptions"`
    27  }
    28  
    29  type createOptions struct {
    30  	Capped      *bool  `bson:"capped"`
    31  	SizeInBytes *int64 `bson:"size"`
    32  }
    33  
    34  // createCollection configures the collection represented by the receiver using the internal client. This function
    35  // first drops the collection and then creates it with specified options (if any) and inserts the seed data if needed.
    36  func (c *collectionData) createCollection(ctx context.Context) error {
    37  	db := mtest.GlobalClient().Database(c.DatabaseName, options.Database().SetWriteConcern(mtest.MajorityWc))
    38  	coll := db.Collection(c.CollectionName)
    39  	if err := coll.Drop(ctx); err != nil {
    40  		return fmt.Errorf("error dropping collection: %w", err)
    41  	}
    42  
    43  	// Explicitly create collection if Options are specified.
    44  	if c.Options != nil {
    45  		createOpts := options.CreateCollection()
    46  		if c.Options.Capped != nil {
    47  			createOpts = createOpts.SetCapped(*c.Options.Capped)
    48  		}
    49  		if c.Options.SizeInBytes != nil {
    50  			createOpts = createOpts.SetSizeInBytes(*c.Options.SizeInBytes)
    51  		}
    52  
    53  		if err := db.CreateCollection(ctx, c.CollectionName, createOpts); err != nil {
    54  			return fmt.Errorf("error creating collection: %w", err)
    55  		}
    56  	}
    57  
    58  	// If neither documents nor options are provided, still create the collection with write concern "majority".
    59  	if len(c.Documents) == 0 && c.Options == nil {
    60  		// The write concern has to be manually specified in the command document because RunCommand does not honor
    61  		// the database's write concern.
    62  		create := bson.D{
    63  			{"create", coll.Name()},
    64  			{"writeConcern", bson.D{
    65  				{"w", "majority"},
    66  			}},
    67  		}
    68  		if err := db.RunCommand(ctx, create).Err(); err != nil {
    69  			return fmt.Errorf("error creating collection: %w", err)
    70  		}
    71  		return nil
    72  	}
    73  
    74  	docs := bsonutil.RawToInterfaces(c.Documents...)
    75  	if _, err := coll.InsertMany(ctx, docs); err != nil {
    76  		return fmt.Errorf("error inserting data: %w", err)
    77  	}
    78  	return nil
    79  }
    80  
    81  // verifyContents asserts that the collection on the server represented by this collectionData instance contains the
    82  // expected documents.
    83  func (c *collectionData) verifyContents(ctx context.Context) error {
    84  	collOpts := options.Collection().
    85  		SetReadPreference(readpref.Primary()).
    86  		SetReadConcern(readconcern.Local())
    87  	coll := mtest.GlobalClient().Database(c.DatabaseName).Collection(c.CollectionName, collOpts)
    88  
    89  	cursor, err := coll.Find(ctx, bson.D{}, options.Find().SetSort(bson.M{"_id": 1}))
    90  	if err != nil {
    91  		return fmt.Errorf("Find error: %w", err)
    92  	}
    93  	defer cursor.Close(ctx)
    94  
    95  	var docs []bson.Raw
    96  	if err := cursor.All(ctx, &docs); err != nil {
    97  		return fmt.Errorf("cursor iteration error: %w", err)
    98  	}
    99  
   100  	// Verify the slice lengths are equal. This also covers the case of asserting that the collection is empty if
   101  	// c.Documents is an empty slice.
   102  	if len(c.Documents) != len(docs) {
   103  		return fmt.Errorf("expected %d documents but found %d: %v", len(c.Documents), len(docs), docs)
   104  	}
   105  
   106  	// We can't use verifyValuesMatch here because the rules for evaluating matches (e.g. flexible numeric comparisons
   107  	// and special $$ operators) do not apply when verifying collection outcomes. We have to permit variations in key
   108  	// order, though, so we sort documents before doing a byte-wise comparison.
   109  	for idx, expected := range c.Documents {
   110  		expected = sortDocument(expected)
   111  		actual := sortDocument(docs[idx])
   112  
   113  		if !bytes.Equal(expected, actual) {
   114  			return fmt.Errorf("document comparison error at index %d: expected %s, got %s", idx, expected, actual)
   115  		}
   116  	}
   117  	return nil
   118  }
   119  
   120  func (c *collectionData) namespace() string {
   121  	return fmt.Sprintf("%s.%s", c.DatabaseName, c.CollectionName)
   122  }
   123  

View as plain text