1
2
3
4
5
6
7 package integtest
8
9 import (
10 "context"
11 "errors"
12 "fmt"
13 "math"
14 "os"
15 "reflect"
16 "strconv"
17 "strings"
18 "sync"
19 "testing"
20
21 "go.mongodb.org/mongo-driver/event"
22 "go.mongodb.org/mongo-driver/internal/require"
23 "go.mongodb.org/mongo-driver/mongo/description"
24 "go.mongodb.org/mongo-driver/mongo/options"
25 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
26 "go.mongodb.org/mongo-driver/x/mongo/driver"
27 "go.mongodb.org/mongo-driver/x/mongo/driver/connstring"
28 "go.mongodb.org/mongo-driver/x/mongo/driver/operation"
29 "go.mongodb.org/mongo-driver/x/mongo/driver/topology"
30 )
31
32 var connectionString *connstring.ConnString
33 var connectionStringOnce sync.Once
34 var connectionStringErr error
35 var liveTopology *topology.Topology
36 var liveTopologyOnce sync.Once
37 var liveTopologyErr error
38
39
40 func AddOptionsToURI(uri string, opts ...string) string {
41 if !strings.ContainsRune(uri, '?') {
42 if uri[len(uri)-1] != '/' {
43 uri += "/"
44 }
45
46 uri += "?"
47 } else {
48 uri += "&"
49 }
50
51 for _, opt := range opts {
52 uri += opt
53 }
54
55 return uri
56 }
57
58
59
60 func AddTLSConfigToURI(uri string) string {
61 caFile := os.Getenv("MONGO_GO_DRIVER_CA_FILE")
62 if len(caFile) == 0 {
63 return uri
64 }
65
66 return AddOptionsToURI(uri, "ssl=true&sslCertificateAuthorityFile=", caFile)
67 }
68
69
70
71 func AddCompressorToURI(uri string) string {
72 comp := os.Getenv("MONGO_GO_DRIVER_COMPRESSOR")
73 if len(comp) == 0 {
74 return uri
75 }
76
77 return AddOptionsToURI(uri, "compressors=", comp)
78 }
79
80
81 func AddTestServerAPIVersion(opts *options.ClientOptions) {
82 if os.Getenv("REQUIRE_API_VERSION") == "true" {
83 opts.SetServerAPIOptions(options.ServerAPI(driver.TestServerAPIVersion))
84 }
85 }
86
87
88 func MonitoredTopology(t *testing.T, dbName string, monitor *event.CommandMonitor) *topology.Topology {
89 uri, err := MongoDBURI()
90 if err != nil {
91 t.Fatal(err)
92 }
93 cfg, err := topology.NewConfig(options.Client().ApplyURI(uri).SetMonitor(monitor), nil)
94 if err != nil {
95 t.Fatal(err)
96 }
97
98 monitoredTopology, err := topology.New(cfg)
99 if err != nil {
100 t.Fatal(err)
101 } else {
102 _ = monitoredTopology.Connect()
103
104 err = operation.NewCommand(bsoncore.BuildDocument(nil, bsoncore.AppendInt32Element(nil, "dropDatabase", 1))).
105 Database(dbName).ServerSelector(description.WriteSelector()).Deployment(monitoredTopology).Execute(context.Background())
106
107 require.NoError(t, err)
108 }
109
110 return monitoredTopology
111 }
112
113
114 func Topology(t *testing.T) *topology.Topology {
115 uri, err := MongoDBURI()
116 require.NoError(t, err, "error constructing mongodb URI: %v", err)
117 cfg, err := topology.NewConfig(options.Client().ApplyURI(uri), nil)
118 require.NoError(t, err, "error constructing topology config: %v", err)
119
120 liveTopologyOnce.Do(func() {
121 var err error
122 liveTopology, err = topology.New(cfg)
123 if err != nil {
124 liveTopologyErr = err
125 } else {
126 _ = liveTopology.Connect()
127
128 err = operation.NewCommand(bsoncore.BuildDocument(nil, bsoncore.AppendInt32Element(nil, "dropDatabase", 1))).
129 Database(DBName(t)).ServerSelector(description.WriteSelector()).Deployment(liveTopology).Execute(context.Background())
130 require.NoError(t, err)
131 }
132 })
133
134 if liveTopologyErr != nil {
135 t.Fatal(liveTopologyErr)
136 }
137
138 return liveTopology
139 }
140
141
142 func TopologyWithCredential(t *testing.T, credential options.Credential) *topology.Topology {
143 uri, err := MongoDBURI()
144 if err != nil {
145 t.Fatalf("error constructing mongodb URI: %v", err)
146 }
147 cfg, err := topology.NewConfig(options.Client().ApplyURI(uri).SetAuth(credential), nil)
148 if err != nil {
149 t.Fatalf("error constructing topology config: %v", err)
150 }
151 topology, err := topology.New(cfg)
152 if err != nil {
153 t.Fatal("Could not construct topology")
154 }
155 err = topology.Connect()
156 if err != nil {
157 t.Fatal("Could not start topology connection")
158 }
159 return topology
160 }
161
162
163
164 func ColName(t *testing.T) string {
165
166 v := reflect.Indirect(reflect.ValueOf(t))
167 name := v.FieldByName("name")
168 return name.String()
169 }
170
171
172
173 func MongoDBURI() (string, error) {
174 uri := os.Getenv("MONGODB_URI")
175 if uri == "" {
176 uri = "mongodb://localhost:27017"
177 }
178
179 uri = AddTLSConfigToURI(uri)
180 uri = AddCompressorToURI(uri)
181 uri, err := AddServerlessAuthCredentials(uri)
182 return uri, err
183 }
184
185
186 func AddServerlessAuthCredentials(uri string) (string, error) {
187 if os.Getenv("SERVERLESS") != "serverless" {
188 return uri, nil
189 }
190 user := os.Getenv("SERVERLESS_ATLAS_USER")
191 if user == "" {
192 return "", fmt.Errorf("serverless expects SERVERLESS_ATLAS_USER to be set")
193 }
194 password := os.Getenv("SERVERLESS_ATLAS_PASSWORD")
195 if password == "" {
196 return "", fmt.Errorf("serverless expects SERVERLESS_ATLAS_PASSWORD to be set")
197 }
198
199 var scheme string
200
201 if strings.HasPrefix(uri, "mongodb+srv://") {
202 scheme = "mongodb+srv://"
203 } else if strings.HasPrefix(uri, "mongodb://") {
204 scheme = "mongodb://"
205 } else {
206 return "", errors.New(`scheme must be "mongodb" or "mongodb+srv"`)
207 }
208
209 uri = scheme + user + ":" + password + "@" + uri[len(scheme):]
210 return uri, nil
211 }
212
213
214 func ConnString(t *testing.T) *connstring.ConnString {
215 connectionStringOnce.Do(func() {
216 uri, err := MongoDBURI()
217 require.NoError(t, err, "error constructing mongodb URI: %v", err)
218
219 connectionString, err = connstring.ParseAndValidate(uri)
220 if err != nil {
221 connectionStringErr = err
222 }
223 })
224 if connectionStringErr != nil {
225 t.Fatal(connectionStringErr)
226 }
227
228 return connectionString
229 }
230
231 func GetConnString() (*connstring.ConnString, error) {
232 mongodbURI := os.Getenv("MONGODB_URI")
233 if mongodbURI == "" {
234 mongodbURI = "mongodb://localhost:27017"
235 }
236
237 mongodbURI = AddTLSConfigToURI(mongodbURI)
238
239 cs, err := connstring.ParseAndValidate(mongodbURI)
240 if err != nil {
241 return nil, err
242 }
243
244 return cs, nil
245 }
246
247
248 func DBName(t *testing.T) string {
249 return GetDBName(ConnString(t))
250 }
251
252 func GetDBName(cs *connstring.ConnString) string {
253 if cs.Database != "" {
254 return cs.Database
255 }
256
257 return fmt.Sprintf("mongo-go-driver-%d", os.Getpid())
258 }
259
260
261
262
263
264
265
266 func CompareVersions(t *testing.T, v1 string, v2 string) int {
267 n1 := strings.Split(v1, ".")
268 n2 := strings.Split(v2, ".")
269
270 for i := 0; i < int(math.Min(float64(len(n1)), float64(len(n2)))); i++ {
271 i1, err := strconv.Atoi(n1[i])
272 require.NoError(t, err)
273
274 i2, err := strconv.Atoi(n2[i])
275 require.NoError(t, err)
276
277 difference := i1 - i2
278 if difference != 0 {
279 return difference
280 }
281 }
282
283 return 0
284 }
285
View as plain text