Skip to content

Commit

Permalink
Remove Route from RoutingKit (#82)
Browse files Browse the repository at this point in the history
* Remove Route from RoutingKit

* Update docs

* Add back circly.yml with just performance tests

* Add linux files & update circle file

* Remove linux test files & move to 5.1 + test discovery
  • Loading branch information
MrLotU authored and tanner0101 committed Dec 11, 2019
1 parent 39f0710 commit 6a8a163
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 90 deletions.
31 changes: 0 additions & 31 deletions Sources/RoutingKit/Route.swift

This file was deleted.

9 changes: 6 additions & 3 deletions Sources/RoutingKit/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ public protocol Router {
/// Type of value stored in routes. This will be returned by the router.
associatedtype Output

/// Registers a new `Route` to the `Router`.
/// Registers a new `Output` to the `Router` at a given path.
///
/// Extraneous information such as `userInfo` may be discarded.
mutating func register(route: Route<Output>)
/// - parameters:
/// - output: Output to register.
/// - path: Path to register output at.
///
mutating func register(_ output: Output, at path: [PathComponent])

/// Fetches output for a specific route.
///
Expand Down
8 changes: 4 additions & 4 deletions Sources/RoutingKit/TrieRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,24 @@ public final class TrieRouter<Output>: Router, CustomStringConvertible {
///
/// - parameters:
/// - route: `Route` to register to this router.
public func register(route: Route<Output>) {
public func register(_ output: Output, at path: [PathComponent]) {
// start at the root of the trie branch
var current = self.root

// for each dynamic path in the route get the appropriate
// child generating a new one if necessary
for component in route.path {
for component in path {
current = current.buildOrFetchChild(for: component, options: self.options)
}

// if this node already has output, we are overriding a route
if current.output != nil {
print("[Routing] Warning: Overriding route output at: \(route.path.string)")
print("[Routing] Warning: Overriding route output at: \(path.string)")
}

// after iterating over all path components, we can set the output
// on the current node
current.output = route.output
current.output = output
}

/// Routes a `path`, returning the best-matching output and collecting any dynamic parameters.
Expand Down
28 changes: 14 additions & 14 deletions Tests/RoutingKitTests/RouterPerformanceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ final class RouterPerformanceTests: XCTestCase {
guard performance(expected: 0.039) else { return }
let router = TrieRouter(String.self)
for letter in ["a", "b", "c", "d", "e" , "f", "g"] {
router.register(route: Route(path: [
router.register(letter, at:[
.constant(letter),
.parameter("\(letter)_id")
], output: letter))
])
}

measure {
Expand All @@ -24,10 +24,10 @@ final class RouterPerformanceTests: XCTestCase {
guard performance(expected: 0.050) else { return }
let router = TrieRouter.init(String.self, options: [.caseInsensitive])
for letter in ["a", "b", "c", "d", "e" , "f", "g"] {
router.register(route: Route(path: [
router.register(letter, at: [
.constant(letter),
.parameter("\(letter)_id")
], output: letter))
])
}

measure {
Expand All @@ -42,10 +42,10 @@ final class RouterPerformanceTests: XCTestCase {
guard performance(expected: 0.062) else { return }
let router = TrieRouter.init(String.self, options: [.caseInsensitive])
for letter in ["aaaaaaaa", "aaaaaaab", "aaaaaaac", "aaaaaaad", "aaaaaaae" , "aaaaaaaf", "aaaaaaag"] {
router.register(route: Route(path: [
router.register(letter, at: [
.constant(letter),
.parameter("\(letter)_id")
], output: letter))
])
}

measure {
Expand All @@ -60,10 +60,10 @@ final class RouterPerformanceTests: XCTestCase {
guard performance(expected: 0.063) else { return }
let router = TrieRouter.init(String.self, options: [.caseInsensitive])
for letter in ["aaaaaaaa", "aaaaaaab", "aaaaaaac", "aaaaaaad", "aaaaaaae" , "aaaaaaaf", "aaaaaaag"] {
router.register(route: Route(path: [
router.register(letter, at: [
.constant(letter),
.parameter("\(letter)_id")
], output: letter))
])
}

measure {
Expand All @@ -78,9 +78,9 @@ final class RouterPerformanceTests: XCTestCase {
guard performance(expected: 0.022) else { return }
let router = TrieRouter.init(String.self, options: [.caseInsensitive])
for letter in ["a"] {
router.register(route: Route(path: [
router.register(letter, at: [
.constant(letter)
], output: letter))
])
}

measure {
Expand All @@ -95,9 +95,9 @@ final class RouterPerformanceTests: XCTestCase {
guard performance(expected: 0.017) else { return }
let router = TrieRouter.init(String.self)
for letter in ["a"] {
router.register(route: Route(path: [
router.register(letter, at: [
.constant(letter)
], output: letter))
])
}

measure {
Expand All @@ -113,9 +113,9 @@ final class RouterPerformanceTests: XCTestCase {
guard performance(expected: 0.016) else { return }
let router = TrieRouter.init(String.self)
for letter in ["aaaaaaaaaaaaaa"] {
router.register(route: Route(path: [
router.register(letter, at: [
.constant(letter)
], output: letter))
])
}

measure {
Expand Down
63 changes: 25 additions & 38 deletions Tests/RoutingKitTests/RouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,36 @@ import XCTest

final class RouterTests: XCTestCase {
func testRouter() throws {
let route = Route(path: ["foo", "bar", "baz", ":user"], output: 42)
let router = TrieRouter(Int.self)
router.register(route: route)
router.register(42, at: ["foo", "bar", "baz", ":user"])
var params = Parameters()
XCTAssertEqual(router.route(path: ["foo", "bar", "baz", "Tanner"], parameters: &params), 42)
XCTAssertEqual(params.get("user"), "Tanner")
}

func testCaseSensitiveRouting() throws {
let route = Route<Int>(path: [.constant("path"), .constant("TO"), .constant("fOo")], output: 42)
let router = TrieRouter<Int>()
router.register(route: route)
router.register(42, at: [.constant("path"), .constant("TO"), .constant("fOo")])
var params = Parameters()
XCTAssertEqual(router.route(path: ["PATH", "tO", "FOo"], parameters: &params), nil)
XCTAssertEqual(router.route(path: ["path", "TO", "fOo"], parameters: &params), 42)
}

func testCaseInsensitiveRouting() throws {
let route = Route<Int>(path: [.constant("path"), .constant("TO"), .constant("fOo")], output: 42)
let router = TrieRouter<Int>(options: [.caseInsensitive])
router.register(route: route)
router.register(42, at: [.constant("path"), .constant("TO"), .constant("fOo")])
var params = Parameters()
XCTAssertEqual(router.route(path: ["PATH", "tO", "FOo"], parameters: &params), 42)
}

func testAnyRouting() throws {
let route0 = Route<Int>(path: [.constant("a"), .anything], output: 0)
let route1 = Route<Int>(path: [.constant("b"), .parameter("1"), .anything], output: 1)
let route2 = Route<Int>(path: [.constant("c"), .parameter("1"), .parameter("2"), .anything], output: 2)
let route3 = Route<Int>(path: [.constant("d"), .parameter("1"), .parameter("2")], output: 3)
let route4 = Route<Int>(path: [.constant("e"), .parameter("1"), .catchall], output: 4)
let route5 = Route<Int>(path: [.anything, .constant("e"), .parameter("1")], output: 5)

let router = TrieRouter<Int>()
router.register(route: route0)
router.register(route: route1)
router.register(route: route2)
router.register(route: route3)
router.register(route: route4)
router.register(route: route5)
router.register(0, at: [.constant("a"), .anything])
router.register(1, at: [.constant("b"), .parameter("1"), .anything])
router.register(2, at: [.constant("c"), .parameter("1"), .parameter("2"), .anything])
router.register(3, at: [.constant("d"), .parameter("1"), .parameter("2")])
router.register(4, at: [.constant("e"), .parameter("1"), .catchall])
router.register(5, at: [.anything, .constant("e"), .parameter("1")])

var params = Parameters()
XCTAssertEqual(router.route(path: ["a", "b"], parameters: &params), 0)
Expand All @@ -65,12 +55,9 @@ final class RouterTests: XCTestCase {
}

func testRouterSuffixes() throws {
let route1 = Route<Int>(path: [.constant("a")], output: 1)
let route2 = Route<Int>(path: [.constant("aa")], output: 2)

let router = TrieRouter<Int>(options: [.caseInsensitive])
router.register(route: route1)
router.register(route: route2)
router.register(1, at: [.constant("a")])
router.register(2, at: [.constant("aa")])

var params = Parameters()
XCTAssertEqual(router.route(path: ["a"], parameters: &params), 1)
Expand All @@ -79,26 +66,26 @@ final class RouterTests: XCTestCase {


func testDocBlock() throws {
let route = Route<Int>(path: ["users", ":user"], output: 42)
let router = TrieRouter<Int>()
router.register(route: route)
router.register(42, at: ["users", ":user"])

var params = Parameters()
XCTAssertEqual(router.route(path: ["users", "Tanner"], parameters: &params), 42)
XCTAssertEqual(params.get("user"), "Tanner")
}

func testDocs() throws {
let router = TrieRouter(Double.self)
router.register(route: Route(path: ["fun", "meaning_of_universe"], output: 42))
router.register(route: Route(path: ["fun", "leet"], output: 1337))
router.register(route: Route(path: ["math", "pi"], output: 3.14))
router.register(42, at: ["fun", "meaning_of_universe"])
router.register(1337, at: ["fun", "leet"])
router.register(3.14, at: ["math", "pi"])
var params = Parameters()
XCTAssertEqual(router.route(path: ["fun", "meaning_of_universe"], parameters: &params), 42)
}

func testDocs2() throws {
let router = TrieRouter(String.self)
router.register(route: Route(path: [.constant("users"), .parameter("user_id")], output: "show_user"))
router.register("show_user", at: [.constant("users"), .parameter("user_id")])

var params = Parameters()
_ = router.route(path: ["users", "42"], parameters: &params)
Expand All @@ -108,7 +95,7 @@ final class RouterTests: XCTestCase {
// https://github.com/vapor/routing/issues/64
func testParameterPercentDecoding() throws {
let router = TrieRouter(String.self)
router.register(route: Route(path: [.constant("a"), .parameter("b")], output: "c"))
router.register("c", at: [.constant("a"), .parameter("b")])
var params = Parameters()
XCTAssertEqual(router.route(path: ["a", "te%20st"], parameters: &params), "c")
XCTAssertEqual(params.get("b"), "te st")
Expand All @@ -117,10 +104,10 @@ final class RouterTests: XCTestCase {
// https://github.com/vapor/routing-kit/issues/74
func testCatchAllNested() throws {
let router = TrieRouter(String.self)
router.register(route: Route(path: [.catchall], output: "/**"))
router.register(route: Route(path: ["a", .catchall], output: "/a/**"))
router.register(route: Route(path: ["a", "b", .catchall], output: "/a/b/**"))
router.register(route: Route(path: ["a", "b"], output: "/a/b"))
router.register("/**", at: [.catchall])
router.register("/a/**", at: ["a", .catchall])
router.register("/a/b/**", at: ["a", "b", .catchall])
router.register("/a/b", at: ["a", "b"])
var params = Parameters()
XCTAssertEqual(router.route(path: ["a"], parameters: &params), "/**")
XCTAssertEqual(router.route(path: ["a", "b"], parameters: &params), "/a/b")
Expand All @@ -132,9 +119,9 @@ final class RouterTests: XCTestCase {

func testCatchAllPrecedence() throws {
let router = TrieRouter(String.self)
router.register(route: Route(path: ["v1", "test"], output: "a"))
router.register(route: Route(path: ["v1", .catchall], output: "b"))
router.register(route: Route(path: ["v1", .anything], output: "c"))
router.register("a", at: ["v1", "test"])
router.register("b", at: ["v1", .catchall])
router.register("c", at: ["v1", .anything])
var params = Parameters()
XCTAssertEqual(router.route(path: ["v1", "test"], parameters: &params), "a")
XCTAssertEqual(router.route(path: ["v1", "test", "foo"], parameters: &params), "b")
Expand Down
21 changes: 21 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: 2

jobs:
version: 2

jobs:
linux-performance:
docker:
- image: swift:5.1-bionic
steps:
- checkout
- run:
name: swift test
command: swift test --enable-test-discovery -c release --filter "RoutingKitTests.RouterPerformanceTests"

workflows:
version: 2

notify:
webhooks:
- url: https://bot-gh.vapor.codes/circle/result

0 comments on commit 6a8a163

Please sign in to comment.