1
2
3
4
5
6
7 package integration
8
9 import (
10 "context"
11 "fmt"
12 "net"
13 "net/url"
14 "os/exec"
15 "strconv"
16 "testing"
17
18 "go.mongodb.org/mongo-driver/bson"
19 "go.mongodb.org/mongo-driver/event"
20 "go.mongodb.org/mongo-driver/internal/assert"
21 "go.mongodb.org/mongo-driver/internal/require"
22 "go.mongodb.org/mongo-driver/mongo"
23 "go.mongodb.org/mongo-driver/mongo/integration/mtest"
24 "go.mongodb.org/mongo-driver/mongo/options"
25 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
26 )
27
28 type mongocryptdProcess struct {
29 cmd *exec.Cmd
30 }
31
32
33 func (p *mongocryptdProcess) start(port int) error {
34 args := []string{
35 "mongocryptd",
36 "--port", strconv.Itoa(port),
37 }
38
39 p.cmd = exec.Command(args[0], args[1:]...)
40 p.cmd.Stderr = p.cmd.Stdout
41
42 return p.cmd.Start()
43 }
44
45
46 func (p *mongocryptdProcess) close() error {
47 if p.cmd.Process == nil {
48 return nil
49 }
50
51 if err := p.cmd.Process.Kill(); err != nil {
52 return fmt.Errorf("failed to terminate mongocryptd process: %w", err)
53 }
54
55
56 err := p.cmd.Process.Release()
57 if err != nil {
58 return fmt.Errorf("failed to release mongocryptd: %w", err)
59 }
60
61 return nil
62 }
63
64
65
66
67
68 func newTestSessionMongocryptdProseClient(mt *mtest.T) *mongo.Client {
69 const mongocryptdPort = 27022
70
71
72
73
74
75 cmdMonitor := &event.CommandMonitor{
76 Started: func(_ context.Context, evt *event.CommandStartedEvent) {
77 _, err := evt.Command.LookupErr("lsid")
78 assert.ErrorIs(mt, err, bsoncore.ErrElementNotFound)
79 },
80 }
81
82 uri := &url.URL{
83 Scheme: "mongodb",
84 Host: net.JoinHostPort("localhost", strconv.Itoa(mongocryptdPort)),
85 }
86
87 proc := mongocryptdProcess{}
88
89
90 err := proc.start(mongocryptdPort)
91 require.NoError(mt, err, "failed to create a mongocryptd process: %v", err)
92
93 mt.Cleanup(func() {
94 err := proc.close()
95 require.NoError(mt, err, "failed to close mongocryptd: %v", err)
96 })
97
98 clientOpts := options.
99 Client().
100 ApplyURI(uri.String()).
101 SetMonitor(cmdMonitor)
102
103 ctx := context.Background()
104
105 client, err := mongo.Connect(ctx, clientOpts)
106 require.NoError(mt, err, "could not connect to mongocryptd: %v", err)
107
108 return client
109
110 }
111
112 func TestSessionsMongocryptdProse(t *testing.T) {
113 mtOpts := mtest.NewOptions().
114 MinServerVersion("4.2").
115 Topologies(mtest.ReplicaSet, mtest.Sharded).
116 CreateCollection(false).
117 CreateClient(false)
118
119
120
121 mt := mtest.New(t, mtOpts)
122
123 proseTest18 := "18. implicit session is ignored if connection does not support sessions"
124 mt.RunOpts(proseTest18, mtOpts, func(mt *mtest.T) {
125 client := newTestSessionMongocryptdProseClient(mt)
126
127 mt.Cleanup(func() {
128 err := client.Disconnect(context.Background())
129 require.NoError(mt, err, "mongocryptd client could not disconnect: %v", err)
130 })
131
132 coll := client.Database("db").Collection("coll")
133
134
135
136 mt.RunOpts("read", mtOpts, func(_ *mtest.T) {
137 _ = coll.FindOne(context.Background(), bson.D{{"x", 1}})
138 })
139
140
141
142 mt.RunOpts("write", mtOpts, func(_ *mtest.T) {
143 _, _ = coll.InsertOne(context.Background(), bson.D{{"x", 1}})
144 })
145 })
146
147 proseTest19 := "19. explicit session raises an error if connection does not support sessions"
148 mt.RunOpts(proseTest19, mtOpts, func(mt *mtest.T) {
149 client := newTestSessionMongocryptdProseClient(mt)
150
151 mt.Cleanup(func() {
152 err := client.Disconnect(context.Background())
153 require.NoError(mt, err, "mongocryptd client could not disconnect: %v", err)
154 })
155
156
157
158 session, err := client.StartSession()
159 require.NoError(mt, err, "expected error to be nil, got %v", err)
160
161 defer session.EndSession(context.Background())
162
163 sessionCtx := mongo.NewSessionContext(context.TODO(), session)
164
165 err = session.StartTransaction()
166 require.NoError(mt, err, "expected error to be nil, got %v", err)
167
168 coll := client.Database("db").Collection("coll")
169
170
171
172 mt.RunOpts("read", mtOpts, func(mt *mtest.T) {
173
174
175 res := coll.FindOne(sessionCtx, bson.D{{"x", 1}})
176 assert.EqualError(mt, res.Err(), "current topology does not support sessions")
177 })
178
179
180
181 mt.RunOpts("write", mtOpts, func(mt *mtest.T) {
182
183
184 res := coll.FindOne(sessionCtx, bson.D{{"x", 1}})
185 assert.EqualError(mt, res.Err(), "current topology does not support sessions")
186 })
187 })
188 }
189
View as plain text