Skip to content

Commit

Permalink
Merge pull request #6 from cactuslab/feature/refactor
Browse files Browse the repository at this point in the history
Feature/refactor
  • Loading branch information
karlvr committed Oct 10, 2018
2 parents 8a1cc77 + 8af344a commit a317579
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 37 deletions.
17 changes: 17 additions & 0 deletions Example/Tests/Succulent/Tests_testIgnoredParametersForTrace.trace
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
HTTP-Trace-Version: 1.0
Generator: Succulent/1.0


Method: GET
Protocol-Version: HTTP/1.1
Protocol: http
Host: www.cactuslab.com
File: /query.txt?username=test&toBe=ignored
Response-Header:<<--EOF-2-
HTTP/1.1 200 OK
Content-Type: text/plain

--EOF-2-
Response-Body:<<--EOF-2-
Success for query
--EOF-2-
37 changes: 24 additions & 13 deletions Example/Tests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ class Tests: XCTestCase, SucculentTest {
override func setUp() {
super.setUp()

if let traceURL = self.traceUrl {
suc = Succulent(traceUrl: traceURL, baseUrl: nil, ignoreVersioningRequests: ["^/ignore_post.txt"])
} else {
suc = Succulent()
configureSucculent()

session = URLSession(configuration: .default)
}

func configureSucculent(ignoredParams: Set<String>? = nil, passThroughBaseUrl: URL? = nil) {
if let suc = suc {
suc.stop()
}
let conf = Configuration(port: nil, ignoreParameters: ignoredParams, ignoreVersioningRequests: ["^/ignore_post.txt"])
suc = Succulent(replayFrom: self.traceUrl, passThroughBaseUrl: passThroughBaseUrl, configuration: conf)

suc.start()

baseURL = URL(string: "http://localhost:\(suc.actualPort)")

session = URLSession(configuration: .default)
self.baseURL = URL(string: "http://localhost:\(suc.actualPort)")
}

/// The name of the trace file for the current test
Expand Down Expand Up @@ -70,7 +73,7 @@ class Tests: XCTestCase, SucculentTest {
}

func testIgnoredParameters() {
suc.ignoreParameters = ["ignoreMe"]
configureSucculent(ignoredParams: ["ignoreMe"])

GET("query.txt?username=test&ignoreMe=1209") { (data, response, error) in
XCTAssertEqual(String(data: data!, encoding: .utf8)!, "Success for query")
Expand All @@ -82,8 +85,16 @@ class Tests: XCTestCase, SucculentTest {
}
}

/// This tests a recording that was made without the ignoredParams that we’re going to run the replay with. So the recording contains query strings with the ignored param. We ensure that we can still match those requests.
func testIgnoredParametersForTrace() {
configureSucculent(ignoredParams: ["toBe"])
GET("query.txt?username=test&toBe=ignored") { (data, response, error) in
XCTAssertEqual(String(data: data!, encoding: .utf8)!, "Success for query")
}
}

func testIgnoreAllParameters() {
suc.ignoreParameters = ["ignore_me"]
configureSucculent(ignoredParams: ["ignore_me"])

GET("query.txt?ignore_me=12345") { (data, response, error) in
XCTAssertEqual(String(data: data!, encoding: .utf8)!, "Success for query")
Expand Down Expand Up @@ -192,7 +203,7 @@ class Tests: XCTestCase, SucculentTest {
}

func testPassThrough() {
suc.baseUrl = URL(string: "http://www.cactuslab.com/")
configureSucculent(ignoredParams: nil, passThroughBaseUrl: URL(string: "http://www.cactuslab.com/"))

GET("index.html") { (data, response, error) in
let string = String(data: data!, encoding: .utf8)!
Expand All @@ -201,7 +212,7 @@ class Tests: XCTestCase, SucculentTest {
}

func testPassThroughURLPreservation() {
suc.baseUrl = URL(string: "http://www.cactuslab.com/api/")
configureSucculent(ignoredParams: nil, passThroughBaseUrl: URL(string: "http://www.cactuslab.com/api/"))

GET("index.html") { (data, response, error) in
XCTAssertTrue(response?.url?.absoluteString == "http://cactuslab.com/api/index.html", "The responseURL was \(response?.url?.absoluteString ?? "nil")")
Expand Down Expand Up @@ -264,7 +275,7 @@ class Tests: XCTestCase, SucculentTest {
}

func testQueryStringOrder() {
suc.ignoreParameters = ["a"]
configureSucculent(ignoredParams: ["a"])

GET("query.txt?username=test&perPage=2&a=1") { (data, response, error) in
XCTAssertEqual(String(data: data!, encoding: .utf8)!, "Success for query")
Expand Down
2 changes: 1 addition & 1 deletion Example/Tests/TraceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class TraceTests: XCTestCase, SucculentTest {

recordingURL = self.recordUrl

suc = Succulent(recordUrl: recordingURL, baseUrl: URL(string: "http://cactuslab.com/")!)
suc = Succulent(recordTo: recordingURL, baseUrl: URL(string: "http://cactuslab.com/")!)
suc.start()

baseURL = URL(string: "http://localhost:\(suc.actualPort)")
Expand Down
70 changes: 47 additions & 23 deletions Succulent/Classes/Succulent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,39 @@
import Embassy
import Foundation

public struct Configuration {
///Specify the port that Succulent should listen on. Set to nil for Succulent to automatically choose a free port.
public var port: Int?
///A set of query string parameter names that should be ignored for the purposes of matching incoming requests to recorded requests.
public var ignoreParameters: Set<String>?
///An array of regular expression strings to match against incoming request paths; matches will not increase the Succulent version even if they use a mutating HTTP method.
public var ignoreVersioningRequests: [String]?

public init() {

}

public init(port: Int? = nil, ignoreParameters: Set<String>? = nil, ignoreVersioningRequests: [String]?) {
self.port = port
self.ignoreParameters = ignoreParameters
self.ignoreVersioningRequests = ignoreVersioningRequests
}
}

public class Succulent : NSObject, URLSessionTaskDelegate {

public var port: Int?
public private(set) var port: Int?
public var version = 0
public var baseUrl: URL?
public var recordUrl: URL? {
public private(set) var baseUrl: URL?
public private(set) var recordUrl: URL? {
didSet {
if let recordUrl = recordUrl {
//Throw away the previous trace
try? FileManager.default.removeItem(at: recordUrl)
}
}
}
public var ignoreParameters: Set<String>?
public private(set) var ignoreParameters: Set<String>?

public let router = Router()

Expand All @@ -48,27 +67,20 @@ public class Succulent : NSObject, URLSessionTaskDelegate {
private var currentTrace = NSMutableOrderedSet()
private var recordedKeys = Set<String>()
private var ignoreExpressions: [NSRegularExpression] = []

public override init() {
super.init()

createDefaultRouter()
}

public convenience init(traceUrl: URL, baseUrl: URL? = nil, ignoreVersioningRequests: [String] = []) {
self.init()
///Initialise Succulent in replay mode, with an optional trace file to replay from, a pass-through URL to use if a match if not found in the trace file, and configuration.
public convenience init(replayFrom traceUrl: URL?, passThroughBaseUrl baseUrl: URL? = nil, configuration: Configuration? = nil) {

self.init(configuration: configuration)
self.baseUrl = baseUrl
ignoreExpressions = ignoreVersioningRequests.map { (expression) -> NSRegularExpression in
return try! NSRegularExpression(pattern: expression, options: [])

if let traceUrl = traceUrl {
addTrace(url: traceUrl)
}

addTrace(url: traceUrl, ignoreVersioningRequests: ignoreVersioningRequests)
}

public convenience init(recordUrl: URL, baseUrl: URL) {
self.init()
public convenience init(recordTo recordUrl: URL, baseUrl: URL, configuration: Configuration? = nil) {
self.init(configuration: configuration)

defer {
/* Defer so that the didSet runs on recordUrl */
Expand All @@ -77,6 +89,21 @@ public class Succulent : NSObject, URLSessionTaskDelegate {
}
}

///Initialise Succulent in recording mode, with a URL to record the trace to and the base URL for the upstream server that we're recording.
private init(configuration: Configuration?) {
super.init()
if let configuration = configuration {
if let ignoreVersioningRequests = configuration.ignoreVersioningRequests {
ignoreExpressions = ignoreVersioningRequests.map { (expression) -> NSRegularExpression in
return try! NSRegularExpression(pattern: expression, options: [])
}
}
ignoreParameters = configuration.ignoreParameters
port = configuration.port
}
createDefaultRouter()
}

private func createDefaultRouter() {
router.add(".*").anyParams().block { (req, resultBlock) in
/* Increment version when we get the first GET after a mutating http method */
Expand Down Expand Up @@ -183,7 +210,7 @@ public class Succulent : NSObject, URLSessionTaskDelegate {
}

/// Load the trace file at the given URL and populate our traces ivar
private func addTrace(url: URL, ignoreVersioningRequests: [String]) {
private func addTrace(url: URL) {
if traces == nil {
traces = [String : Trace]()
}
Expand Down Expand Up @@ -333,9 +360,6 @@ public class Succulent : NSObject, URLSessionTaskDelegate {
self.loop.call {
switch result {
case .response(let res):
if res.containsHeader("Set-Cookie") {
print("Here we are with cooookies")
}
startResponse("\(res.status)", res.headers ?? [])

if let data = res.data {
Expand Down

0 comments on commit a317579

Please sign in to comment.