Skip to content

Commit 18145aa

Browse files
authored
SWIFT-17: add evergreen linux support (#241)
- update evergreen config - install swift using swiftenv - add support for skipping tests by topology - add `find-cmake.sh` script - use patrick's new numeric helpers to avoid topology issues - ensure all tests of a commands response use `doubleValue` for `ok` - skip command monitoring tests on sharded topologies - reduce to a single mongos if multiple are provided - add 4.2 and 5.0 variants - disable macos tests until we can figure out how install without root permissions
1 parent f9caceb commit 18145aa

File tree

10 files changed

+231
-326
lines changed

10 files changed

+231
-326
lines changed

.evergreen/config.yml

Lines changed: 82 additions & 260 deletions
Large diffs are not rendered by default.

.evergreen/find-cmake.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/sh
2+
set -o xtrace # Write all commands first to stderr
3+
set -o errexit # Exit the script with error if any of the commands fail
4+
5+
find_cmake ()
6+
{
7+
if [ ! -z "$CMAKE" ]; then
8+
return 0
9+
elif [ -f "/Applications/cmake-3.2.2-Darwin-x86_64/CMake.app/Contents/bin/cmake" ]; then
10+
CMAKE="/Applications/cmake-3.2.2-Darwin-x86_64/CMake.app/Contents/bin/cmake"
11+
elif [ -f "/Applications/Cmake.app/Contents/bin/cmake" ]; then
12+
CMAKE="/Applications/Cmake.app/Contents/bin/cmake"
13+
elif [ -f "/opt/cmake/bin/cmake" ]; then
14+
CMAKE="/opt/cmake/bin/cmake"
15+
elif command -v cmake 2>/dev/null; then
16+
CMAKE=cmake
17+
elif uname -a | grep -iq 'x86_64 GNU/Linux'; then
18+
curl --retry 5 https://cmake.org/files/v3.11/cmake-3.11.0-Linux-x86_64.tar.gz -sS --max-time 120 --fail --output cmake.tar.gz
19+
mkdir cmake-3.11.0
20+
tar xzf cmake.tar.gz -C cmake-3.11.0 --strip-components=1
21+
CMAKE=$(pwd)/cmake-3.11.0/bin/cmake
22+
else
23+
# Some images have no cmake yet, BUILD-4922.
24+
echo "-- MAKE CMAKE --"
25+
curl --retry 5 https://cmake.org/files/v3.11/cmake-3.11.0.tar.gz -sS --max-time 120 --fail --output cmake.tar.gz
26+
tar xzf cmake.tar.gz
27+
cd cmake-3.11.0
28+
./bootstrap --prefix="${INSTALL_DIR}"
29+
make -j8
30+
make install
31+
cd ..
32+
CMAKE="${INSTALL_DIR}/bin/cmake"
33+
echo "-- DONE MAKING CMAKE --"
34+
fi
35+
}
36+
37+
find_cmake

.evergreen/install-dependencies.sh

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,33 @@
22
set -o xtrace # Write all commands first to stderr
33
set -o errexit # Exit the script with error if any of the commands fail
44

5-
DIR=$(dirname $0)
6-
# Functions to fetch MongoDB binaries
7-
. $DIR/download-mongodb.sh
8-
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
9-
10-
get_distro
11-
12-
# See .evergreen/download-mongodb.sh for most possible values
13-
case "$DISTRO" in
14-
cygwin*)
15-
echo "Install Windows dependencies"
16-
;;
17-
18-
darwin*)
19-
echo "Install macOS dependencies"
20-
;;
21-
22-
linux-rhel*)
23-
echo "Install RHEL dependencies"
24-
;;
25-
26-
linux-ubuntu*)
27-
echo "Install Ubuntu dependencies"
28-
# sudo apt-get install -y awscli || true
29-
;;
30-
31-
sunos*)
32-
echo "Install Solaris dependencies"
33-
# sudo /opt/csw/bin/pkgutil -y -i sasl_dev || true
34-
;;
35-
36-
*)
37-
echo "All other platforms..."
38-
;;
39-
esac
5+
# variables
6+
PROJECT_DIRECTORY=${PROJECT_DIRECTORY:-$PWD}
7+
SWIFT_VERSION=${SWIFT_VERSION:-4.2}
8+
INSTALL_DIR="${PROJECT_DIRECTORY}/opt"
9+
BUILD_DIR="${PROJECT_DIRECTORY}/libmongoc-build"
10+
EVG_DIR=$(dirname $0)
11+
12+
export SWIFTENV_ROOT="${INSTALL_DIR}/swiftenv"
13+
export PATH=/opt/cmake/bin:${SWIFTENV_ROOT}/bin:$PATH
14+
15+
# should be set by EVG eventuallty
16+
LIBMONGOC_VERSION="r1.13"
17+
18+
# find cmake and set the path to it in $CMAKE
19+
. $EVG_DIR/find-cmake.sh
20+
21+
# install libmongoc
22+
git clone --depth 1 -b "${LIBMONGOC_VERSION}" https://github.com/mongodb/mongo-c-driver "${BUILD_DIR}"
23+
cd "${BUILD_DIR}"
24+
$CMAKE -DCMAKE_INSTALL_PREFIX:PATH="${INSTALL_DIR}"
25+
make -j8 install
26+
cd "${PROJECT_DIRECTORY}"
27+
28+
# install swiftenv
29+
git clone --depth 1 https://github.com/kylef/swiftenv.git "${SWIFTENV_ROOT}"
30+
31+
# install swift
32+
33+
eval "$(swiftenv init -)"
34+
swiftenv install $SWIFT_VERSION

.evergreen/run-tests.sh

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,25 @@
22
set -o xtrace # Write all commands first to stderr
33
set -o errexit # Exit the script with error if any of the commands fail
44

5-
# Supported/used environment variables:
6-
# AUTH Set to enable authentication. Defaults to "noauth"
7-
# SSL Set to enable SSL. Defaults to "nossl"
8-
# MONGODB_URI Set the suggested connection MONGODB_URI (including credentials and topology info)
9-
# MARCH Machine Architecture. Defaults to lowercase uname -m
10-
11-
AUTH=${AUTH:-noauth}
12-
SSL=${SSL:-nossl}
13-
MONGODB_URI=${MONGODB_URI:-}
14-
5+
# variables
6+
PROJECT_DIRECTORY=${PROJECT_DIRECTORY:-$PWD}
7+
MONGODB_URI=${MONGODB_URI:-"NO_URI_PROVIDED"}
8+
SWIFT_VERSION=${SWIFT_VERSION:-4.2}
9+
INSTALL_DIR="${PROJECT_DIRECTORY}/opt"
10+
TOPOLOGY=${TOPOLOGY:-single}
1511
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
16-
[ -z "$MARCH" ] && MARCH=$(uname -m | tr '[:upper:]' '[:lower:]')
1712

18-
if [ "$AUTH" != "noauth" ]; then
19-
export MONGOC_TEST_USER="bob"
20-
export MONGOC_TEST_PASSWORD="pwd123"
21-
fi
13+
# enable swiftenv
14+
export SWIFTENV_ROOT="${INSTALL_DIR}/swiftenv"
15+
export PATH="${SWIFTENV_ROOT}/bin:$PATH"
16+
eval "$(swiftenv init -)"
17+
18+
# switch swift version, and run tests
19+
export PKG_CONFIG_PATH="${INSTALL_DIR}/lib/pkgconfig"
2220

23-
if [ "$SSL" != "nossl" ]; then
24-
export MONGOC_TEST_SSL_PEM_FILE="$DRIVERS_TOOLS/.evergreen/x509gen/client.pem"
25-
export MONGOC_TEST_SSL_CA_FILE="$DRIVERS_TOOLS/.evergreen/x509gen/ca.pem"
26-
fi
21+
# override where we look for libmongoc
22+
export LD_LIBRARY_PATH="${INSTALL_DIR}/lib"
23+
export DYLD_LIBRARY_PATH="${INSTALL_DIR}/lib"
2724

28-
echo "Running $AUTH tests over $SSL, connecting to $MONGODB_URI"
29-
make test
25+
swiftenv local $SWIFT_VERSION
26+
MONGODB_TOPOLOGY=${TOPOLOGY} MONGODB_URI=$MONGODB_URI make test

Tests/MongoSwiftTests/CommandMonitoringTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ final class CommandMonitoringTests: MongoSwiftTestCase {
1010
}
1111

1212
func testCommandMonitoring() throws {
13+
guard MongoSwiftTestCase.topologyType != .sharded else {
14+
print("Skipping test case because of unsupported topology type \(MongoSwiftTestCase.topologyType)")
15+
return
16+
}
17+
1318
let decoder = BSONDecoder()
1419
let client = try MongoClient(options: ClientOptions(eventMonitoring: true))
1520
client.enableMonitoring(forEvents: .commandMonitoring)

Tests/MongoSwiftTests/MongoCollectionTests.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,9 @@ final class MongoCollectionTests: MongoSwiftTestCase {
312312
func testDropIndexByModel() throws {
313313
let model = IndexModel(keys: ["cat": 1])
314314
expect(try self.coll.createIndex(model)).to(equal("cat_1"))
315-
expect(try self.coll.dropIndex(model)["ok"]).to(bsonEqual(1.0))
315+
316+
let res = try self.coll.dropIndex(model)
317+
expect((res["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
316318

317319
// now there should only be _id_ left
318320
let indexes = try coll.listIndexes()
@@ -324,7 +326,9 @@ final class MongoCollectionTests: MongoSwiftTestCase {
324326
func testDropIndexByKeys() throws {
325327
let model = IndexModel(keys: ["cat": 1])
326328
expect(try self.coll.createIndex(model)).to(equal("cat_1"))
327-
expect(try self.coll.dropIndex(["cat": 1])["ok"]).to(bsonEqual(1.0))
329+
330+
let res = try self.coll.dropIndex(["cat": 1])
331+
expect((res["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
328332

329333
// now there should only be _id_ left
330334
let indexes = try coll.listIndexes()
@@ -336,7 +340,9 @@ final class MongoCollectionTests: MongoSwiftTestCase {
336340
func testDropAllIndexes() throws {
337341
let model = IndexModel(keys: ["cat": 1])
338342
expect(try self.coll.createIndex(model)).to(equal("cat_1"))
339-
expect(try self.coll.dropIndexes()["ok"]).to(bsonEqual(1.0))
343+
344+
let res = try self.coll.dropIndexes()
345+
expect((res["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
340346

341347
// now there should only be _id_ left
342348
let indexes = try coll.listIndexes()

Tests/MongoSwiftTests/MongoDatabaseTests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ final class MongoDatabaseTests: MongoSwiftTestCase {
1212
let db = client.db(type(of: self).testDatabase)
1313

1414
let command: Document = ["create": self.getCollectionName(suffix: "1")]
15-
expect(try db.runCommand(command)).to(equal(["ok": 1.0]))
15+
let res = try db.runCommand(command)
16+
expect((res["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
1617
expect(try (Array(db.listCollections()) as [Document]).count).to(equal(1))
1718

1819
// create collection using createCollection

Tests/MongoSwiftTests/ReadWriteConcernTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,12 @@ final class ReadWriteConcernTests: MongoSwiftTestCase {
253253
// run command with a valid readConcern
254254
let options1 = RunCommandOptions(readConcern: ReadConcern(.local))
255255
let res1 = try db.runCommand(command, options: options1)
256-
expect(res1["ok"]).to(bsonEqual(1.0))
256+
expect((res1["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
257257

258258
// run command with an empty readConcern
259259
let options2 = RunCommandOptions(readConcern: ReadConcern())
260260
let res2 = try db.runCommand(command, options: options2)
261-
expect(res2["ok"]).to(bsonEqual(1.0))
261+
expect((res2["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
262262

263263
// running command with an invalid RC level should throw
264264
let options3 = RunCommandOptions(readConcern: ReadConcern("blah"))
@@ -299,12 +299,12 @@ final class ReadWriteConcernTests: MongoSwiftTestCase {
299299
// run command with a valid writeConcern
300300
let options1 = RunCommandOptions(writeConcern: wc1)
301301
let res1 = try db.runCommand(command, options: options1)
302-
expect(res1["ok"]).to(bsonEqual(1.0))
302+
expect((res1["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
303303

304304
// run command with an empty writeConcern
305305
let options2 = RunCommandOptions(writeConcern: wc2)
306306
let res2 = try db.runCommand(command, options: options2)
307-
expect(res2["ok"]).to(bsonEqual(1.0))
307+
expect((res2["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))
308308

309309
expect(try coll.insertOne(nextDoc(), options: InsertOneOptions(writeConcern: wc1))).toNot(throwError())
310310
expect(try coll.insertOne(nextDoc(), options: InsertOneOptions(writeConcern: wc3))).toNot(throwError())

Tests/MongoSwiftTests/SDAMMonitoringTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ final class SDAMTests: MongoSwiftTestCase {
2828
// https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/tests/monitoring/standalone.json
2929
// swiftlint:enable line_length
3030
func testMonitoring() throws {
31+
guard MongoSwiftTestCase.topologyType == .single else {
32+
print("Skipping test case because of unsupported topology type \(MongoSwiftTestCase.topologyType)")
33+
return
34+
}
35+
3136
let client = try MongoClient(options: ClientOptions(eventMonitoring: true))
3237
client.enableMonitoring(forEvents: .serverMonitoring)
3338

Tests/MongoSwiftTests/TestUtils.swift

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Foundation
2+
import mongoc
23
@testable import MongoSwift
34
import Nimble
45
import XCTest
@@ -37,10 +38,31 @@ class MongoSwiftTestCase: XCTestCase {
3738
/// If the environment variable does not exist, this will use a default of "mongodb://127.0.0.1/".
3839
static var connStr: String {
3940
if let connStr = ProcessInfo.processInfo.environment["MONGODB_URI"] {
41+
if self.topologyType == .sharded {
42+
guard let uri = mongoc_uri_new(connStr) else {
43+
return connStr
44+
}
45+
46+
defer {
47+
mongoc_uri_destroy(uri)
48+
}
49+
50+
guard let hosts = mongoc_uri_get_hosts(uri) else {
51+
return connStr
52+
}
53+
54+
let hostAndPort = withUnsafeBytes(of: hosts.pointee.host_and_port) { rawPtr -> String in
55+
let ptr = rawPtr.baseAddress!.assumingMemoryBound(to: CChar.self)
56+
return String(cString: ptr)
57+
}
58+
59+
return "mongodb://\(hostAndPort)/"
60+
}
61+
4062
return connStr
41-
} else {
42-
return "mongodb://127.0.0.1/"
4363
}
64+
65+
return "mongodb://127.0.0.1/"
4466
}
4567

4668
// indicates whether we are running on a 32-bit platform
@@ -55,6 +77,21 @@ class MongoSwiftTestCase: XCTestCase {
5577
}
5678
return name.replacingOccurrences(of: "[ \\+\\$]", with: "_", options: [.regularExpression])
5779
}
80+
81+
static var topologyType: TopologyDescription.TopologyType {
82+
guard let topology = ProcessInfo.processInfo.environment["MONGODB_TOPOLOGY"] else {
83+
return .single
84+
}
85+
86+
switch topology {
87+
case "sharded_cluster":
88+
return .sharded
89+
case "replica_set":
90+
return .replicaSetWithPrimary
91+
default:
92+
return .single
93+
}
94+
}
5895
}
5996

6097
extension MongoClient {

0 commit comments

Comments
 (0)