diff --git a/Package.swift b/Package.swift index 812c0dd..2923dfa 100644 --- a/Package.swift +++ b/Package.swift @@ -26,7 +26,6 @@ let package = Package( ], dependencies: [ //.Package(url: "https://github.com/behrang/YamlSwift.git", majorVersion: 1), - .Package(url: "https://github.com/IBM-Swift/SwiftyJSON.git", majorVersion: 15) ] //testDependencies: [] ) diff --git a/Sources/CloudFoundryEnv/App.swift b/Sources/CloudFoundryEnv/App.swift index 5b97a30..c20b420 100644 --- a/Sources/CloudFoundryEnv/App.swift +++ b/Sources/CloudFoundryEnv/App.swift @@ -21,6 +21,89 @@ */ public struct App { + public class Builder { + var id: String? + var name: String? + var uris: [String]? + var version: String? + var instanceId: String? + var instanceIndex: Int? + var limits: Limits? + var port: Int? + var spaceId: String? + var startedAt: Date? + + init() {} + + func setId(id: String?) -> Builder { + self.id = id + return self + } + + func setName(name: String?) -> Builder { + self.name = name + return self + } + + func setUris(uris: [String]) -> Builder { + self.uris = uris + return self + } + + func setVersion(version: String?) -> Builder { + self.version = version + return self + } + + func setInstanceId(instanceId: String?) -> Builder { + self.instanceId = instanceId + return self + } + + func setInstanceIndex(instanceIndex: Int?) -> Builder { + self.instanceIndex = instanceIndex + return self + } + + func setLimits(limits: Limits) -> Builder { + self.limits = limits + return self + } + + func setPort(port: Int?) -> Builder { + self.port = port + return self + } + + func setSpaceId(spaceId: String?) -> Builder { + self.spaceId = spaceId + return self + } + + func setStartedAt(startedAt: Date?) -> Builder { + self.startedAt = startedAt + return self + } + + func build() -> App? { + guard let id = id, let name = name, + let uris = uris, let version = version, + let instanceId = instanceId, + let instanceIndex = instanceIndex, + let limits = limits, + let port = port, + let spaceId = spaceId, + let startedAt = startedAt else { + return nil + } + + let startedAtTs = startedAt.timeIntervalSince1970 + return App(id: id, name: name, uris: uris, version: version, instanceId: instanceId, + instanceIndex: instanceIndex, limits: limits, port: port, spaceId: spaceId, + startedAtTs: startedAtTs, startedAt: startedAt) + } + } + public struct Limits { let memory: Int let disk: Int @@ -49,7 +132,7 @@ public struct App { * Constructor. */ // swiftlint:disable function_parameter_count - public init(id: String, name: String, uris: [String], version: String, + private init(id: String, name: String, uris: [String], version: String, instanceId: String, instanceIndex: Int, limits: Limits, port: Int, spaceId: String, startedAtTs: TimeInterval, startedAt: Date) { // swiftlint:enable function_parameter_count diff --git a/Sources/CloudFoundryEnv/AppEnv.swift b/Sources/CloudFoundryEnv/AppEnv.swift index d5b4720..31c9512 100644 --- a/Sources/CloudFoundryEnv/AppEnv.swift +++ b/Sources/CloudFoundryEnv/AppEnv.swift @@ -1,37 +1,35 @@ /** - * Copyright IBM Corporation 2016 - * - * 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ +* Copyright IBM Corporation 2016 +* +* 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 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ import Foundation -import SwiftyJSON public struct AppEnv { - public let isLocal: Bool public let port: Int public let name: String? public let bind: String public let urls: [String] public let url: String - public let app: JSON - public let services: JSON + public let app: [String : Any] + public let services: [String : Any] /** * The vcap option property is ignored if not running locally. */ - public init(options: JSON) throws { + public init(options: [String : Any]) throws { // NSProcessInfo.processInfo().environment returns [String : String] let environmentVars = ProcessInfo.processInfo.environment let vcapApplication = environmentVars["VCAP_APPLICATION"] @@ -39,11 +37,11 @@ public struct AppEnv { // Get app app = try AppEnv.parseEnvVariable(isLocal: isLocal, environmentVars: environmentVars, - variableName: "VCAP_APPLICATION", varibleType: "application", options: options) + variableName: "VCAP_APPLICATION", variableType: "application", options: options) // Get services services = try AppEnv.parseEnvVariable(isLocal: isLocal, environmentVars: environmentVars, - variableName: "VCAP_SERVICES", varibleType: "services", options: options) + variableName: "VCAP_SERVICES", variableType: "services", options: options) // Get port port = try AppEnv.parsePort(environmentVars: environmentVars, app: app) @@ -52,7 +50,7 @@ public struct AppEnv { name = AppEnv.parseName(app: app, options: options) // Get bind (IP address of the application instance) - bind = app["host"].string ?? "0.0.0.0" + bind = app["host"] as? String ?? "0.0.0.0" // Get urls urls = AppEnv.parseURLs(isLocal: isLocal, app: app, port: port, options: options) @@ -65,10 +63,11 @@ public struct AppEnv { public func getApp() -> App? { // Get limits let limits: App.Limits - if let memory = app["limits"]["mem"].int, - let disk = app["limits"]["disk"].int, - let fds = app["limits"]["fds"].int { - limits = App.Limits(memory: memory, disk: disk, fds: fds) + if let limitsMap = app["limits"] as? [String : Int], + let memory = limitsMap["mem"], + let disk = limitsMap["disk"], + let fds = limitsMap["fds"] { + limits = App.Limits(memory: memory, disk: disk, fds: fds) } else { return nil } @@ -78,25 +77,19 @@ public struct AppEnv { // Create DateUtils instance let dateUtils = DateUtils() - guard - let name = app["application_name"].string, - let id = app["application_id"].string, - let version = app["version"].string, - let instanceId = app["instance_id"].string, - let instanceIndex = app["instance_index"].int, - let port = app["port"].int, - let startedAt: Date = dateUtils.convertStringToNSDate(dateString: app["started_at"].string), - let spaceId = app["space_id"].string else { - return nil - } - - let startedAtTs = startedAt.timeIntervalSince1970 - // App instance should only be created if all required variables exist - let appObj = App(id: id, name: name, uris: uris, version: version, - instanceId: instanceId, instanceIndex: instanceIndex, - limits: limits, port: port, spaceId: spaceId, - startedAtTs: startedAtTs, startedAt: startedAt) + let appObj = App.Builder() + .setId(id: app["application_id"] as? String) + .setName(name: app["application_name"] as? String) + .setUris(uris: uris) + .setVersion(version: app["version"] as? String) + .setInstanceId(instanceId: app["instance_id"] as? String) + .setInstanceIndex(instanceIndex: app["instance_index"] as? Int) + .setLimits(limits: limits) + .setPort(port: app["port"] as? Int) + .setSpaceId(spaceId: app["space_id"] as? String) + .setStartedAt(startedAt: dateUtils.convertStringToNSDate(dateString: app["started_at"] as? String)) + .build() return appObj } @@ -108,13 +101,17 @@ public struct AppEnv { public func getServices() -> [String:Service] { var results: [String:Service] = [:] for (_, servs) in services { - for service in servs.arrayValue { // as! [[String:AnyObject]] { - // A service must have a name and a label - if let name: String = service["name"].string, - let label: String = service["label"].string { - let tags = JSONUtils.convertJSONArrayToStringArray(json: service, fieldName: "tags") - results[name] = - Service(name: name, label: label, plan: service["plan"].string, tags: tags, credentials: service["credentials"]) + if let servsArray = servs as? [[String:Any]] { + for service in servsArray { + // A service must have a name and a label + if let name: String = service["name"] as? String, + let label: String = service["label"] as? String, + let tags: [String] = service["tags"] as? [String], + let plan: String = service["plan"] as? String, + let credentials : [String:Any] = service["credentials"] as? [String:Any] { + results[name] = + Service(name: name, label: label, plan: plan, tags: tags, credentials: credentials) + } } } } @@ -149,7 +146,7 @@ public struct AppEnv { } catch let error as NSError { print("Error code: \(error.code)") } - return nil + return nil } /** @@ -160,20 +157,20 @@ public struct AppEnv { * The replacements parameter is a JSON object with the properties found in * Foundation's URLComponents class. */ - public func getServiceURL(spec: String, replacements: JSON?) -> String? { - var substitutions: JSON = replacements ?? [:] + public func getServiceURL(spec: String, replacements: [String:Any]?) -> String? { + var substitutions: [String:Any] = replacements ?? [:] let service = getService(spec: spec) guard let credentials = service?.credentials else { return nil } guard let url: String = - credentials[substitutions["url"].string ?? "url"].string ?? credentials["uri"].string - else { + credentials[substitutions["url"] as? String ?? "url"] as? String ?? credentials["uri"] as? String + else { return nil } - substitutions.dictionaryObject?["url"] = nil + substitutions["url"] = nil guard var parsedURL = URLComponents(string: url) else { return nil } @@ -182,29 +179,29 @@ public struct AppEnv { // Before, we were just iterating over the keys in the JSON object, // but unfortunately the order of the keys returned were different on // OS X and Linux, which resulted in different outcomes. - if let user = substitutions["user"].string { - parsedURL.user = user + if let user = substitutions["user"] as? String { + parsedURL.user = user } - if let password = substitutions["password"].string { + if let password = substitutions["password"] as? String { parsedURL.password = password } - if let port = substitutions["port"].int { + if let port = substitutions["port"] as? Int { parsedURL.port = port } - if let host = substitutions["host"].string { + if let host = substitutions["host"] as? String { parsedURL.host = host } - if let scheme = substitutions["scheme"].string { - parsedURL.scheme = scheme + if let scheme = substitutions["scheme"] as? String { + parsedURL.scheme = scheme } - if let query = substitutions["query"].string { + if let query = substitutions["query"] as? String { parsedURL.query = query } - if let queryItems = substitutions["queryItems"].array { + if let queryItems = substitutions["queryItems"] as? [[String:Any]] { var urlQueryItems: [URLQueryItem] = [] for queryItem in queryItems { - if let name = queryItem["name"].string { - let urlQueryItem = URLQueryItem(name: name, value: queryItem["value"].string) + if let name = queryItem["name"] as? String { + let urlQueryItem = URLQueryItem(name: name, value: queryItem["value"] as? String) urlQueryItems.append(urlQueryItem) } } @@ -229,7 +226,7 @@ public struct AppEnv { * spec parameter, this method returns nil. In the case there is no credentials * property for the specified service, an empty JSON is returned. */ - public func getServiceCreds(spec: String) -> JSON? { + public func getServiceCreds(spec: String) -> [String:Any]? { guard let service = getService(spec: spec) else { return nil } @@ -244,27 +241,28 @@ public struct AppEnv { * Static method for parsing VCAP_APPLICATION and VCAP_SERVICES. */ private static func parseEnvVariable(isLocal: Bool, environmentVars: [String:String], - variableName: String, varibleType: String, options: JSON) throws - -> JSON { - // If environment variable is found, then let's use it - if let _ = environmentVars[variableName] { - if let json = JSONUtils.convertStringToJSON(text: environmentVars[variableName]) { - return json - } - throw CloudFoundryEnvError.InvalidValue("Environment variable \(variableName) is not a valid JSON string!") - } - // If environment variable was not found, let's query options - let envVariable = options["vcap"][varibleType] - if envVariable.null != nil { - return [:] + variableName: String, variableType: String, options: [String:Any]) throws + -> [String:Any] { + + // If environment variable is found, then let's use it + if let _ = environmentVars[variableName] { + if let json = JSONUtils.convertStringToJSON(text: environmentVars[variableName]) { + return json } - return envVariable + throw CloudFoundryEnvError.InvalidValue("Environment variable \(variableName) is not a valid JSON string!") + } + // If environment variable was not found, let's query options + if let vcap = options["vcap"] as? [String:Any], + let envVariable = vcap[variableType] as? [String:Any] { + return envVariable + } + return [:] } /** * Static method for parsing the port number. */ - private static func parsePort(environmentVars: [String:String], app: JSON) throws -> Int { + private static func parsePort(environmentVars: [String:String], app: [String : Any]) throws -> Int { let portString: String = environmentVars["PORT"] ?? environmentVars["CF_INSTANCE_PORT"] ?? environmentVars["VCAP_APP_PORT"] ?? "8090" @@ -288,8 +286,8 @@ public struct AppEnv { /** * Static method for parsing the name for the application. */ - private static func parseName(app: JSON, options: JSON) -> String? { - let name: String? = options["name"].string ?? app["name"].string + private static func parseName(app: [String:Any], options: [String:Any]) -> String? { + let name: String? = options["name"] as? String ?? app["name"] as? String // TODO: Add logic for parsing manifest.yml to get name // https://github.com/behrang/YamlSwift // http://stackoverflow.com/questions/24097826/read-and-write-data-from-text-file @@ -299,8 +297,8 @@ public struct AppEnv { /** * Static method for parsing the URLs for the application. */ - private static func parseURLs(isLocal: Bool, app: JSON, port: Int, - options: JSON) -> [String] { + private static func parseURLs(isLocal: Bool, app: [String : Any], port: Int, + options: [String:Any]) -> [String] { var uris: [String] = JSONUtils.convertJSONArrayToStringArray(json: app, fieldName: "uris") if isLocal { uris = ["localhost:\(port)"] @@ -310,10 +308,10 @@ public struct AppEnv { } } - let scheme: String = options["protocol"].string ?? (isLocal ? "http" : "https") + let scheme: String = options["protocol"] as? String ?? (isLocal ? "http" : "https") var urls: [String] = [] for uri in uris { - urls.append("\(scheme)://\(uri)"); + urls.append("\(scheme)://\(uri)"); } return urls } diff --git a/Sources/CloudFoundryEnv/CloudFoundryEnv.swift b/Sources/CloudFoundryEnv/CloudFoundryEnv.swift index bb45a55..0f529f4 100644 --- a/Sources/CloudFoundryEnv/CloudFoundryEnv.swift +++ b/Sources/CloudFoundryEnv/CloudFoundryEnv.swift @@ -14,15 +14,11 @@ * limitations under the License. **/ -import SwiftyJSON - /** * Functions as a factory to create instances of the AppEnv structure. */ public struct CloudFoundryEnv { - - public static func getAppEnv(options: JSON = [:]) throws -> AppEnv { + public static func getAppEnv(options: [String:Any] = [:]) throws -> AppEnv { return try AppEnv(options: options) } - } diff --git a/Sources/CloudFoundryEnv/JSONUtils.swift b/Sources/CloudFoundryEnv/JSONUtils.swift index ed70054..aceb943 100644 --- a/Sources/CloudFoundryEnv/JSONUtils.swift +++ b/Sources/CloudFoundryEnv/JSONUtils.swift @@ -15,7 +15,6 @@ **/ import Foundation -import SwiftyJSON /** * JSON utilities. @@ -25,22 +24,28 @@ public struct JSONUtils { /** * Converts the speficied string to a JSON object. */ - public static func convertStringToJSON(text: String?) -> JSON? { + public static func convertStringToJSON(text: String?) -> [String:Any]? { let data = text?.data(using: String.Encoding.utf8) guard let nsData = data else { print("Could not generate JSON object from string: \(text)") return nil } - let json = JSON(data: nsData) - return json + if let json = try? JSONSerialization.jsonObject(with: nsData) { + return (json as? [String:Any]) + } + return nil } /** - * Converts a JSON array element contained in a JSON object to an array of Strings. + * Converts an array element contained in a JSON object to an array of Strings. * The fieldName argument should state the name of the JSON property that contains - * the JSON array. + * the array. */ - public static func convertJSONArrayToStringArray(json: JSON, fieldName: String) -> [String] { - return json[fieldName].arrayValue.map { $0.stringValue } + public static func convertJSONArrayToStringArray(json: [String:Any], fieldName: String) -> [String] { + if let array = json[fieldName] as? [Any] { + return (array.map { String(describing: $0) }) + } + return [] } + } diff --git a/Sources/CloudFoundryEnv/Service.swift b/Sources/CloudFoundryEnv/Service.swift index ccf6eaa..c442f52 100644 --- a/Sources/CloudFoundryEnv/Service.swift +++ b/Sources/CloudFoundryEnv/Service.swift @@ -14,8 +14,6 @@ * limitations under the License. **/ -import SwiftyJSON - /** * See https://docs.run.pivotal.io/devguide/deploy-apps/environment-variable.html#VCAP-SERVICES. */ @@ -24,10 +22,10 @@ public struct Service { public let label: String public let plan : String public let tags: [String] - public let credentials: JSON? + public let credentials: [String:Any]? public init(name: String, label: String, plan: String?, tags: [String], - credentials: JSON?) { + credentials: [String:Any]?) { self.name = name self.label = label diff --git a/Tests/CloudFoundryEnvTests/MainTests.swift b/Tests/CloudFoundryEnvTests/MainTests.swift index 8285036..8708aae 100644 --- a/Tests/CloudFoundryEnvTests/MainTests.swift +++ b/Tests/CloudFoundryEnvTests/MainTests.swift @@ -22,7 +22,6 @@ import XCTest import Foundation -import SwiftyJSON @testable import CloudFoundryEnv @@ -45,11 +44,11 @@ class MainTests : XCTestCase { } let options = "{ \"vcap\": { \"application\": { \"limits\": { \"mem\": 128, \"disk\": 1024, \"fds\": 16384 }, \"application_id\": \"e582416a-9771-453f-8df1-7b467f6d78e4\", \"application_version\": \"e5e029d1-4a1a-4004-9f79-655d550183fb\", \"application_name\": \"swift-test\", \"application_uris\": [ \"swift-test.mybluemix.net\" ], \"version\": \"e5e029d1-4a1a-4004-9f79-655d550183fb\", \"name\": \"swift-test\", \"space_name\": \"dev\", \"space_id\": \"b15eb0bb-cbf3-43b6-bfbc-f76d495981e5\", \"uris\": [ \"swift-test.mybluemix.net\" ], \"users\": null, \"instance_id\": \"7d4f24cfba06462ba23d68aaf1d7354a\", \"instance_index\": 0, \"host\": \"0.0.0.0\", \"port\": 61263, \"started_at\": \"2016-03-04 02:43:07 +0000\", \"started_at_timestamp\": 1457059387, \"start\": \"2016-03-04 02:43:07 +0000\", \"state_timestamp\": 1457059387 }, \"services\": { \"cloudantNoSQLDB\": [ { \"name\": \"Cloudant NoSQL DB-kd\", \"label\": \"cloudantNoSQLDB\", \"tags\": [ \"data_management\", \"ibm_created\", \"ibm_dedicated_public\" ], \"plan\": \"Shared\", \"credentials\": { \"username\": \"09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix\", \"password\": \"06c19ae06b1915d8a6649df5901eca85e885182421ffa9ef89e14bbc1b76efd4\", \"host\": \"09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix.cloudant.com\", \"port\": 443, \"url\": \"https://09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix:06c19ae06b1915d8a6649df5901eca85e885182421ffa9ef89e14bbc1b76efd4@09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix.cloudant.com\" } } ] } } }" - var jsonOptions: JSON = [:] + var jsonOptions: [String:Any] = [:] override func setUp() { super.setUp() - jsonOptions = JSONUtils.convertStringToJSON(text: options) as JSON! + jsonOptions = JSONUtils.convertStringToJSON(text: options)! } override func tearDown() { @@ -251,30 +250,29 @@ class MainTests : XCTestCase { XCTAssertEqual(service.name, "Cloudant NoSQL DB-kd", "Service name should match.") XCTAssertEqual(service.label, "cloudantNoSQLDB", "Service label should match.") XCTAssertEqual(service.plan, "Shared", "Service plan should match.") - let tags = service.tags - XCTAssertEqual(tags.count, 3, "There should be 3 tags in the tags array.") - XCTAssertEqual(tags[0], "data_management", "Service tag #0 should match.") - XCTAssertEqual(tags[1], "ibm_created", "Serivce tag #1 should match.") - XCTAssertEqual(tags[2], "ibm_dedicated_public", "Serivce tag #2 should match.") - let credentials: JSON? = service.credentials + XCTAssertEqual(service.tags.count, 3, "There should be 3 tags in the tags array.") + XCTAssertEqual(service.tags[0], "data_management", "Service tag #0 should match.") + XCTAssertEqual(service.tags[1], "ibm_created", "Serivce tag #1 should match.") + XCTAssertEqual(service.tags[2], "ibm_dedicated_public", "Serivce tag #2 should match.") + let credentials: [String:Any]? = service.credentials XCTAssertNotNil(credentials) verifyServiceCreds(serviceCreds: credentials!) } - private func verifyServiceCreds(serviceCreds: JSON) { + private func verifyServiceCreds(serviceCreds: [String:Any]) { XCTAssertEqual(serviceCreds.count, 5, "There should be 5 elements in the credentials object.") for (key, value) in serviceCreds { switch key { case "password": - XCTAssertEqual(value, "06c19ae06b1915d8a6649df5901eca85e885182421ffa9ef89e14bbc1b76efd4", "Password in credentials object should match.") + XCTAssertEqual((value as! String), "06c19ae06b1915d8a6649df5901eca85e885182421ffa9ef89e14bbc1b76efd4", "Password in credentials object should match.") case "url": - XCTAssertEqual(value, "https://09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix:06c19ae06b1915d8a6649df5901eca85e885182421ffa9ef89e14bbc1b76efd4@09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix.cloudant.com", "URL in credentials object should match.") + XCTAssertEqual((value as! String), "https://09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix:06c19ae06b1915d8a6649df5901eca85e885182421ffa9ef89e14bbc1b76efd4@09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix.cloudant.com", "URL in credentials object should match.") case "port" : - XCTAssertEqual(value, 443, "Port in credentials object should match.") + XCTAssertEqual((value as! Int), 443, "Port in credentials object should match.") case "host": - XCTAssertEqual(value, "09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix.cloudant.com", "Host in credentials object should match.") + XCTAssertEqual((value as! String), "09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix.cloudant.com", "Host in credentials object should match.") case "username": - XCTAssertEqual(value, "09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix", "Username in credentials object should match.") + XCTAssertEqual((value as! String), "09ed7c8a-fae8-48ea-affa-0b44b2224ec0-bluemix", "Username in credentials object should match.") default: XCTFail("Unexpected key in credentials: \(key)") } diff --git a/Tests/CloudFoundryEnvTests/UtilsTests.swift b/Tests/CloudFoundryEnvTests/UtilsTests.swift index 4ac0a29..502a251 100644 --- a/Tests/CloudFoundryEnvTests/UtilsTests.swift +++ b/Tests/CloudFoundryEnvTests/UtilsTests.swift @@ -22,7 +22,6 @@ import XCTest import Foundation -import SwiftyJSON @testable import CloudFoundryEnv @@ -46,13 +45,13 @@ class UtilsTests : XCTestCase { //print("JSON object is: \(json)") //print("Type is \(json["users"].dynamicType)") //XCTAssertNil(json["users"] as? AnyObject) - XCTAssertEqual(json["users"], nil) - XCTAssertEqual(json["instance_id"], "7d4f24cfba06462ba23d68aaf1d7354a", "instance_id should match.") - XCTAssertEqual(json["instance_index"], 0, "instance_index should match.") - XCTAssertEqual(json["host"], "0.0.0.0", "host should match.") - XCTAssertEqual(json["port"], 61263, "port should match.") - XCTAssertEqual(json["started_at"], "2016-03-04 02:43:07 +0000", "started_at should match.") - XCTAssertEqual(json["started_at_timestamp"], 1457059387, "started_at_timestamp should match.") + XCTAssertEqual(json["users"] as? String, nil) + XCTAssertEqual(json["instance_id"] as? String, "7d4f24cfba06462ba23d68aaf1d7354a", "instance_id should match.") + XCTAssertEqual(json["instance_index"] as? Int, 0, "instance_index should match.") + XCTAssertEqual(json["host"] as? String, "0.0.0.0", "host should match.") + XCTAssertEqual(json["port"] as? Int, 61263, "port should match.") + XCTAssertEqual(json["started_at"] as? String, "2016-03-04 02:43:07 +0000", "started_at should match.") + XCTAssertEqual(json["started_at_timestamp"] as? Int, 1457059387, "started_at_timestamp should match.") } else { XCTFail("Could not generate JSON object!") } @@ -61,6 +60,7 @@ class UtilsTests : XCTestCase { func testConvertJSONArrayToStringArray() { let jsonStr = "{ \"tags\": [ \"data_management\", \"ibm_created\", \"ibm_dedicated_public\" ] }" if let json = JSONUtils.convertStringToJSON(text: jsonStr) { + // let strArray: [String] = (json["tags"] as? [String])! let strArray: [String] = JSONUtils.convertJSONArrayToStringArray(json: json, fieldName: "tags") XCTAssertEqual(strArray.count, 3, "There should be 3 elements in the string array.") UtilsTests.verifyElementInArrayExists(strArray: strArray, element: "data_management")