File: //opt/go/pkg/mod/go.mongodb.org/
[email protected]/mongo/writeconcern/writeconcern_test.go
// Copyright (C) MongoDB, Inc. 2017-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 writeconcern_test
import (
"errors"
"testing"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/internal/assert"
"go.mongodb.org/mongo-driver/internal/require"
"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
func TestWriteConcernWithOptions(t *testing.T) {
t.Parallel()
t.Run("on nil WriteConcern", func(t *testing.T) {
t.Parallel()
var wc *writeconcern.WriteConcern
wc = wc.WithOptions(writeconcern.WMajority())
assert.Equal(t, "majority", wc.GetW().(string))
assert.False(t, wc.GetJ())
})
t.Run("on existing WriteConcern", func(t *testing.T) {
t.Parallel()
wc := writeconcern.New(writeconcern.W(1), writeconcern.J(true))
assert.Equal(t, 1, wc.GetW().(int))
assert.True(t, wc.GetJ())
wc = wc.WithOptions(writeconcern.WMajority())
assert.Equal(t, "majority", wc.GetW().(string))
assert.True(t, wc.GetJ())
})
t.Run("with multiple options", func(t *testing.T) {
t.Parallel()
wc := writeconcern.New(writeconcern.W(1), writeconcern.J(true))
assert.Equal(t, 1, wc.GetW().(int))
assert.True(t, wc.GetJ())
assert.Equal(t, time.Duration(0), wc.GetWTimeout())
wc = wc.WithOptions(writeconcern.WMajority(), writeconcern.WTimeout(time.Second))
assert.Equal(t, "majority", wc.GetW().(string))
assert.True(t, wc.GetJ())
assert.Equal(t, time.Second, wc.GetWTimeout())
})
}
func TestWriteConcern_MarshalBSONValue(t *testing.T) {
t.Parallel()
boolPtr := func(b bool) *bool { return &b }
testCases := []struct {
name string
wc *writeconcern.WriteConcern
wantType bsontype.Type
wantValue bson.D
wantError error
}{
{
name: "all fields",
wc: &writeconcern.WriteConcern{
W: "majority",
Journal: boolPtr(false),
WTimeout: 1 * time.Minute,
},
wantType: bson.TypeEmbeddedDocument,
wantValue: bson.D{
{Key: "w", Value: "majority"},
{Key: "j", Value: false},
{Key: "wtimeout", Value: int64(60_000)},
},
},
{
name: "string W",
wc: &writeconcern.WriteConcern{W: "majority"},
wantType: bson.TypeEmbeddedDocument,
wantValue: bson.D{{Key: "w", Value: "majority"}},
},
{
name: "int W",
wc: &writeconcern.WriteConcern{W: 1},
wantType: bson.TypeEmbeddedDocument,
wantValue: bson.D{{Key: "w", Value: int32(1)}},
},
{
name: "int32 W",
wc: &writeconcern.WriteConcern{W: int32(1)},
wantError: errors.New("WriteConcern.W must be a string or int, but is a int32"),
},
{
name: "bool W",
wc: &writeconcern.WriteConcern{W: false},
wantError: errors.New("WriteConcern.W must be a string or int, but is a bool"),
},
{
name: "W=0 and J=true",
wc: &writeconcern.WriteConcern{W: 0, Journal: boolPtr(true)},
wantError: writeconcern.ErrInconsistent,
},
{
name: "negative W",
wc: &writeconcern.WriteConcern{W: -1},
wantError: writeconcern.ErrNegativeW,
},
{
name: "negative WTimeout",
wc: &writeconcern.WriteConcern{W: 1, WTimeout: -1},
wantError: writeconcern.ErrNegativeWTimeout,
},
{
name: "empty",
wc: &writeconcern.WriteConcern{},
wantError: writeconcern.ErrEmptyWriteConcern,
},
{
name: "nil",
wc: nil,
wantError: writeconcern.ErrEmptyWriteConcern,
},
}
for _, tc := range testCases {
tc := tc // Capture range variable.
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
typ, b, err := tc.wc.MarshalBSONValue()
if tc.wantError != nil {
assert.Equal(t, tc.wantError, err, "expected and actual errors do not match")
return
}
require.NoError(t, err, "bson.MarshalValue error")
assert.Equal(t, tc.wantType, typ, "expected and actual BSON types do not match")
rv := bson.RawValue{
Type: typ,
Value: b,
}
var gotValue bson.D
err = rv.Unmarshal(&gotValue)
require.NoError(t, err, "error unmarshaling RawValue")
assert.Equal(t, tc.wantValue, gotValue, "expected and actual BSON values do not match")
})
}
}
func TestWriteConcern(t *testing.T) {
boolPtr := func(b bool) *bool { return &b }
testCases := []struct {
name string
wc *writeconcern.WriteConcern
wantAcknowledged bool
wantIsValid bool
}{
{
name: "Unacknowledged",
wc: writeconcern.Unacknowledged(),
wantAcknowledged: false,
wantIsValid: true,
},
{
name: "W1",
wc: writeconcern.W1(),
wantAcknowledged: true,
wantIsValid: true,
},
{
name: "Journaled",
wc: writeconcern.Journaled(),
wantAcknowledged: true,
wantIsValid: true,
},
{
name: "Majority",
wc: writeconcern.Majority(),
wantAcknowledged: true,
wantIsValid: true,
},
{
name: "{w: 0, j: true}",
wc: &writeconcern.WriteConcern{
W: 0,
Journal: boolPtr(true),
},
wantAcknowledged: true,
wantIsValid: false,
},
{
name: "{w: custom}",
wc: &writeconcern.WriteConcern{W: "custom"},
wantAcknowledged: true,
wantIsValid: true,
},
{
name: "nil",
wc: nil,
wantAcknowledged: true,
wantIsValid: true,
},
{
name: "invalid type",
wc: &writeconcern.WriteConcern{
W: struct{ Field string }{},
},
wantAcknowledged: true,
wantIsValid: false,
},
}
for _, tc := range testCases {
tc := tc // Capture range variable.
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t,
tc.wantAcknowledged,
tc.wc.Acknowledged(),
"expected and actual Acknowledged value are different")
assert.Equal(t,
tc.wantIsValid,
tc.wc.IsValid(),
"expected and actual IsValid value are different")
})
}
}