Skip to content

Commit

Permalink
GODRIVER-1844 export unified test runner (mongodb#607)
Browse files Browse the repository at this point in the history
  • Loading branch information
iwysiu authored and Mohammad Fahim Abrar committed Mar 17, 2022
1 parent cc6b4c6 commit 9eab6b5
Show file tree
Hide file tree
Showing 29 changed files with 958 additions and 916 deletions.
Expand Up @@ -21,9 +21,9 @@ const (
errorInterrupted int32 = 11601
)

// TerminateOpenSessions executes a killAllSessions command to ensure that sesssions left open on the server by a test
// terminateOpenSessions executes a killAllSessions command to ensure that sesssions left open on the server by a test
// do not cause future tests to hang.
func TerminateOpenSessions(ctx context.Context) error {
func terminateOpenSessions(ctx context.Context) error {
if mtest.CompareServerVersions(mtest.ServerVersion(), "3.6") < 0 {
return nil
}
Expand All @@ -48,10 +48,10 @@ func TerminateOpenSessions(ctx context.Context) error {
return runAgainstAllMongoses(ctx, commandFn)
}

// PerformDistinctWorkaround executes a non-transactional "distinct" command against each mongos in a sharded cluster.
func PerformDistinctWorkaround(ctx context.Context) error {
// performDistinctWorkaround executes a non-transactional "distinct" command against each mongos in a sharded cluster.
func performDistinctWorkaround(ctx context.Context) error {
commandFn := func(ctx context.Context, client *mongo.Client) error {
for _, coll := range Entities(ctx).Collections() {
for _, coll := range entities(ctx).collections() {
newColl := client.Database(coll.Database().Name()).Collection(coll.Name())
_, err := newColl.Distinct(ctx, "x", bson.D{})
if err != nil {
Expand All @@ -66,7 +66,7 @@ func PerformDistinctWorkaround(ctx context.Context) error {
return runAgainstAllMongoses(ctx, commandFn)
}

func RunCommandOnHost(ctx context.Context, host string, commandFn func(context.Context, *mongo.Client) error) error {
func runCommandOnHost(ctx context.Context, host string, commandFn func(context.Context, *mongo.Client) error) error {
clientOpts := options.Client().
ApplyURI(mtest.ClusterURI()).
SetHosts([]string{host})
Expand All @@ -83,7 +83,7 @@ func RunCommandOnHost(ctx context.Context, host string, commandFn func(context.C

func runAgainstAllMongoses(ctx context.Context, commandFn func(context.Context, *mongo.Client) error) error {
for _, host := range mtest.ClusterConnString().Hosts {
if err := RunCommandOnHost(ctx, host, commandFn); err != nil {
if err := runCommandOnHost(ctx, host, commandFn); err != nil {
return fmt.Errorf("error executing callback against host %q: %v", host, err)
}
}
Expand Down
Expand Up @@ -20,14 +20,14 @@ var (
emptyRawValue = bson.RawValue{}
)

func DocumentToRawValue(doc bson.Raw) bson.RawValue {
func documentToRawValue(doc bson.Raw) bson.RawValue {
return bson.RawValue{
Type: bsontype.EmbeddedDocument,
Value: doc,
}
}

func RemoveFieldsFromDocument(doc bson.Raw, keys ...string) bson.Raw {
func removeFieldsFromDocument(doc bson.Raw, keys ...string) bson.Raw {
newDoc := bsoncore.NewDocumentBuilder()
elems, _ := doc.Elements()

Expand All @@ -47,7 +47,7 @@ func RemoveFieldsFromDocument(doc bson.Raw, keys ...string) bson.Raw {
return bson.Raw(newDoc.Build())
}

func SortDocument(doc bson.Raw) bson.Raw {
func sortDocument(doc bson.Raw) bson.Raw {
elems, _ := doc.Elements()
keys := make([]string, 0, len(elems))
valuesMap := make(map[string]bson.RawValue)
Expand All @@ -66,11 +66,11 @@ func SortDocument(doc bson.Raw) bson.Raw {
return bson.Raw(sorted.Build())
}

func LookupString(doc bson.Raw, key string) string {
func lookupString(doc bson.Raw, key string) string {
return doc.Lookup(key).StringValue()
}

func MapKeys(m map[string]interface{}) []string {
func mapKeys(m map[string]interface{}) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
Expand Down
Expand Up @@ -13,15 +13,15 @@ import (
"go.mongodb.org/mongo-driver/mongo/options"
)

// GridFSBucketOptions is a wrapper for *options.BucketOptions. This type implements the bson.Unmarshaler interface to
// gridFSBucketOptions is a wrapper for *options.BucketOptions. This type implements the bson.Unmarshaler interface to
// convert BSON documents to a BucketOptions instance.
type GridFSBucketOptions struct {
type gridFSBucketOptions struct {
*options.BucketOptions
}

var _ bson.Unmarshaler = (*GridFSBucketOptions)(nil)
var _ bson.Unmarshaler = (*gridFSBucketOptions)(nil)

func (bo GridFSBucketOptions) UnmarshalBSON(data []byte) error {
func (bo gridFSBucketOptions) UnmarshalBSON(data []byte) error {
var temp struct {
Name *string `bson:"name"`
ChunkSize *int32 `bson:"chunkSizeBytes"`
Expand All @@ -31,10 +31,10 @@ func (bo GridFSBucketOptions) UnmarshalBSON(data []byte) error {
Extra map[string]interface{} `bson:",inline"`
}
if err := bson.Unmarshal(data, &temp); err != nil {
return fmt.Errorf("error unmarshalling to temporary GridFSBucketOptions object: %v", err)
return fmt.Errorf("error unmarshalling to temporary gridFSBucketOptions object: %v", err)
}
if len(temp.Extra) > 0 {
return fmt.Errorf("unrecognized fields for GridFSBucketOptions: %v", MapKeys(temp.Extra))
return fmt.Errorf("unrecognized fields for gridFSBucketOptions: %v", mapKeys(temp.Extra))
}

bo.BucketOptions = options.GridFSBucket()
Expand Down
Expand Up @@ -8,18 +8,18 @@ package unified

import "context"

func executeIterateUntilDocumentOrError(ctx context.Context, operation *Operation) (*OperationResult, error) {
stream, err := Entities(ctx).ChangeStream(operation.Object)
func executeIterateUntilDocumentOrError(ctx context.Context, operation *operation) (*operationResult, error) {
stream, err := entities(ctx).changeStream(operation.Object)
if err != nil {
return nil, err
}

for {
if stream.TryNext(ctx) {
return NewDocumentResult(stream.Current, nil), nil
return newDocumentResult(stream.Current, nil), nil
}
if stream.Err() != nil {
return NewErrorResult(stream.Err()), nil
return newErrorResult(stream.Err()), nil
}
}
}
Expand Up @@ -21,9 +21,9 @@ import (
"go.mongodb.org/mongo-driver/mongo/readconcern"
)

// ClientEntity is a wrapper for a mongo.Client object that also holds additional information required during test
// clientEntity is a wrapper for a mongo.Client object that also holds additional information required during test
// execution.
type ClientEntity struct {
type clientEntity struct {
*mongo.Client

recordEvents atomic.Value
Expand All @@ -33,8 +33,8 @@ type ClientEntity struct {
ignoredCommands map[string]struct{}
}

func NewClientEntity(ctx context.Context, entityOptions *EntityOptions) (*ClientEntity, error) {
entity := &ClientEntity{
func newClientEntity(ctx context.Context, entityOptions *entityOptions) (*clientEntity, error) {
entity := &clientEntity{
// The "configureFailPoint" command should always be ignored.
ignoredCommands: map[string]struct{}{
"configureFailPoint": {},
Expand Down Expand Up @@ -96,11 +96,11 @@ func NewClientEntity(ctx context.Context, entityOptions *EntityOptions) (*Client
return entity, nil
}

func (c *ClientEntity) StopListeningForEvents() {
func (c *clientEntity) StopListeningForEvents() {
c.setRecordEvents(false)
}

func (c *ClientEntity) StartedEvents() []*event.CommandStartedEvent {
func (c *clientEntity) startedEvents() []*event.CommandStartedEvent {
var events []*event.CommandStartedEvent
for _, evt := range c.started {
if _, ok := c.ignoredCommands[evt.CommandName]; !ok {
Expand All @@ -111,7 +111,7 @@ func (c *ClientEntity) StartedEvents() []*event.CommandStartedEvent {
return events
}

func (c *ClientEntity) SucceededEvents() []*event.CommandSucceededEvent {
func (c *clientEntity) succeededEvents() []*event.CommandSucceededEvent {
var events []*event.CommandSucceededEvent
for _, evt := range c.succeeded {
if _, ok := c.ignoredCommands[evt.CommandName]; !ok {
Expand All @@ -122,7 +122,7 @@ func (c *ClientEntity) SucceededEvents() []*event.CommandSucceededEvent {
return events
}

func (c *ClientEntity) FailedEvents() []*event.CommandFailedEvent {
func (c *clientEntity) failedEvents() []*event.CommandFailedEvent {
var events []*event.CommandFailedEvent
for _, evt := range c.failed {
if _, ok := c.ignoredCommands[evt.CommandName]; !ok {
Expand All @@ -133,29 +133,29 @@ func (c *ClientEntity) FailedEvents() []*event.CommandFailedEvent {
return events
}

func (c *ClientEntity) processStartedEvent(_ context.Context, evt *event.CommandStartedEvent) {
func (c *clientEntity) processStartedEvent(_ context.Context, evt *event.CommandStartedEvent) {
if c.getRecordEvents() {
c.started = append(c.started, evt)
}
}

func (c *ClientEntity) processSucceededEvent(_ context.Context, evt *event.CommandSucceededEvent) {
func (c *clientEntity) processSucceededEvent(_ context.Context, evt *event.CommandSucceededEvent) {
if c.getRecordEvents() {
c.succeeded = append(c.succeeded, evt)
}
}

func (c *ClientEntity) processFailedEvent(_ context.Context, evt *event.CommandFailedEvent) {
func (c *clientEntity) processFailedEvent(_ context.Context, evt *event.CommandFailedEvent) {
if c.getRecordEvents() {
c.failed = append(c.failed, evt)
}
}

func (c *ClientEntity) setRecordEvents(record bool) {
func (c *clientEntity) setRecordEvents(record bool) {
c.recordEvents.Store(record)
}

func (c *ClientEntity) getRecordEvents() bool {
func (c *clientEntity) getRecordEvents() bool {
return c.recordEvents.Load().(bool)
}

Expand Down
Expand Up @@ -20,18 +20,18 @@ import (

// This file contains helpers to execute client operations.

func executeCreateChangeStream(ctx context.Context, operation *Operation) (*OperationResult, error) {
func executeCreateChangeStream(ctx context.Context, operation *operation) (*operationResult, error) {
var watcher interface {
Watch(context.Context, interface{}, ...*options.ChangeStreamOptions) (*mongo.ChangeStream, error)
}
var err error

watcher, err = Entities(ctx).Client(operation.Object)
watcher, err = entities(ctx).client(operation.Object)
if err != nil {
watcher, err = Entities(ctx).Database(operation.Object)
watcher, err = entities(ctx).database(operation.Object)
}
if err != nil {
watcher, err = Entities(ctx).Collection(operation.Object)
watcher, err = entities(ctx).collection(operation.Object)
}
if err != nil {
return nil, fmt.Errorf("no client, database, or collection entity found with ID %q", operation.Object)
Expand Down Expand Up @@ -84,20 +84,20 @@ func executeCreateChangeStream(ctx context.Context, operation *Operation) (*Oper

stream, err := watcher.Watch(ctx, pipeline, opts)
if err != nil {
return NewErrorResult(err), nil
return newErrorResult(err), nil
}

if operation.ResultEntityID == nil {
return nil, fmt.Errorf("no entity name provided to store executeChangeStream result")
}
if err := Entities(ctx).AddChangeStreamEntity(*operation.ResultEntityID, stream); err != nil {
if err := entities(ctx).addChangeStreamEntity(*operation.ResultEntityID, stream); err != nil {
return nil, fmt.Errorf("error storing result as changeStream entity: %v", err)
}
return NewEmptyResult(), nil
return newEmptyResult(), nil
}

func executeListDatabases(ctx context.Context, operation *Operation) (*OperationResult, error) {
client, err := Entities(ctx).Client(operation.Object)
func executeListDatabases(ctx context.Context, operation *operation) (*operationResult, error) {
client, err := entities(ctx).client(operation.Object)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -126,7 +126,7 @@ func executeListDatabases(ctx context.Context, operation *Operation) (*Operation

res, err := client.ListDatabases(ctx, filter, opts)
if err != nil {
return NewErrorResult(err), nil
return newErrorResult(err), nil
}

specsArray := bsoncore.NewArrayBuilder()
Expand All @@ -143,5 +143,5 @@ func executeListDatabases(ctx context.Context, operation *Operation) (*Operation
AppendArray("databases", specsArray.Build()).
AppendInt64("totalSize", res.TotalSize).
Build()
return NewDocumentResult(raw, nil), nil
return newDocumentResult(raw, nil), nil
}
Expand Up @@ -19,15 +19,15 @@ import (
"go.mongodb.org/mongo-driver/mongo/readpref"
)

type CollectionData struct {
type collectionData struct {
DatabaseName string `bson:"databaseName"`
CollectionName string `bson:"collectionName"`
Documents []bson.Raw `bson:"documents"`
}

// CreateCollection configures the collection represented by the receiver using the internal client. This function
// createCollection configures the collection represented by the receiver using the internal client. This function
// first drops the collection and then creates it and inserts the seed data if needed.
func (c *CollectionData) CreateCollection(ctx context.Context) error {
func (c *collectionData) createCollection(ctx context.Context) error {
db := mtest.GlobalClient().Database(c.DatabaseName)
coll := db.Collection(c.CollectionName, options.Collection().SetWriteConcern(mtest.MajorityWc))
if err := coll.Drop(ctx); err != nil {
Expand Down Expand Up @@ -57,9 +57,9 @@ func (c *CollectionData) CreateCollection(ctx context.Context) error {
return nil
}

// VerifyContents asserts that the collection on the server represented by this CollectionData instance contains the
// verifyContents asserts that the collection on the server represented by this collectionData instance contains the
// expected documents.
func (c *CollectionData) VerifyContents(ctx context.Context) error {
func (c *collectionData) verifyContents(ctx context.Context) error {
collOpts := options.Collection().
SetReadPreference(readpref.Primary()).
SetReadConcern(readconcern.Local())
Expand All @@ -82,12 +82,12 @@ func (c *CollectionData) VerifyContents(ctx context.Context) error {
return fmt.Errorf("expected %d documents but found %d: %v", len(c.Documents), len(docs), docs)
}

// We can't use VerifyValuesMatch here because the rules for evaluating matches (e.g. flexible numeric comparisons
// We can't use verifyValuesMatch here because the rules for evaluating matches (e.g. flexible numeric comparisons
// and special $$ operators) do not apply when verifying collection outcomes. We have to permit variations in key
// order, though, so we sort documents before doing a byte-wise comparison.
for idx, expected := range c.Documents {
expected = SortDocument(expected)
actual := SortDocument(docs[idx])
expected = sortDocument(expected)
actual := sortDocument(docs[idx])

if !bytes.Equal(expected, actual) {
return fmt.Errorf("document comparison error at index %d: expected %s, got %s", idx, expected, actual)
Expand All @@ -96,6 +96,6 @@ func (c *CollectionData) VerifyContents(ctx context.Context) error {
return nil
}

func (c *CollectionData) Namespace() string {
func (c *collectionData) namespace() string {
return fmt.Sprintf("%s.%s", c.DatabaseName, c.CollectionName)
}

0 comments on commit 9eab6b5

Please sign in to comment.