From f316dd9aaa619ba24112859f6c49230ff0f78698 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 27 Mar 2020 13:54:33 +0100 Subject: [PATCH 1/2] Pull out Parser tests --- Tests/ArenaTests/ArenaTests.swift | 126 --------------------- Tests/ArenaTests/IntegrationTests.swift | 25 +++++ Tests/ArenaTests/ParserTests.swift | 143 ++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 126 deletions(-) create mode 100644 Tests/ArenaTests/ParserTests.swift diff --git a/Tests/ArenaTests/ArenaTests.swift b/Tests/ArenaTests/ArenaTests.swift index 40b816f..422771d 100644 --- a/Tests/ArenaTests/ArenaTests.swift +++ b/Tests/ArenaTests/ArenaTests.swift @@ -139,132 +139,6 @@ final class ArenaTests: XCTestCase { XCTAssertEqual(res.libNames, ["foo", "bar"]) } - func test_parse_version() throws { - XCTAssertEqual(Parser.version.run("1.2.3"), Match(result: Version(1, 2, 3), rest: "")) - XCTAssertEqual(Parser.version.run("1.2.3="), Match(result: Version(1, 2, 3), rest: "=")) - } - - func test_parse_requirement() throws { - XCTAssertEqual(Parser.exact.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: "")) - - XCTAssertEqual(Parser.from.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: "")) - - XCTAssertEqual(Parser.range.run("@1.2.3..<3.2.1"), Match(result: .range("1.2.3"..<"3.2.1"), rest: "")) - XCTAssertEqual(Parser.range.run("@1.2.3...3.2.1"), Match(result: .range("1.2.3"..<"3.2.2"), rest: "")) - - do { // combined - XCTAssertEqual(Parser.refSpec.run(""), Match(result: .noVersion, rest: "")) - XCTAssertEqual(Parser.refSpec.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: "")) - XCTAssertEqual(Parser.refSpec.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: "")) - XCTAssertEqual(Parser.refSpec.run("@1.2.3..<3.0.0"), Match(result: .range("1.2.3"..<"3.0.0"), rest: "")) - } - } - - func test_parse_url() throws { - XCTAssertEqual(Parser.url.run("https://github.com/foo/bar"), - Match(result: URL(string: "https://github.com/foo/bar"), rest: "")) - XCTAssertEqual(Parser.url.run("https://github.com/foo/bar@rest"), - Match(result: URL(string: "https://github.com/foo/bar"), rest: "@rest")) - XCTAssertEqual(Parser.url.run("http://github.com/foo/bar@rest"), - Match(result: URL(string: "http://github.com/foo/bar"), rest: "@rest")) - XCTAssertEqual(Parser.url.run("/foo/bar@rest"), - Match(result: URL(string: "file:///foo/bar"), rest: "@rest")) - XCTAssertEqual(Parser.url.run("file:///foo/bar@rest"), - Match(result: URL(string: "file:///foo/bar"), rest: "@rest")) - XCTAssertEqual(Parser.url.run("file:/foo/bar@rest"), - Match(result: URL(string: "file:///foo/bar"), rest: "@rest")) - } - - func test_parse_branchName() { - XCTAssertEqual(branchName.run("develop"), Match(result: "develop", rest: "")) - XCTAssertEqual(branchName.run("foo-bar"), Match(result: "foo-bar", rest: "")) - // disallowed - XCTAssertEqual(branchName.run("/foo"), Match(result: nil, rest: "/foo")) - XCTAssertEqual(branchName.run("foo."), Match(result: nil, rest: "foo.")) - XCTAssertEqual(branchName.run("foo/"), Match(result: nil, rest: "foo/")) - } - - func test_parse_branch() { - XCTAssertEqual(Parser.branch.run("@branch:develop"), Match(result: .branch("develop"), rest: "")) - } - - func test_parse_revision() { - XCTAssertEqual(Parser.revision.run("@revision:foo"), Match(result: .revision("foo"), rest: "")) - XCTAssertEqual(Parser.revision.run("@revision:7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), Match(result: .revision("7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), rest: "")) - XCTAssertEqual(Parser.revision.run("@revision:1.2.3-rc4"), Match(result: .revision("1.2.3-rc4"), rest: "")) - } - - func test_parse_dependency() throws { - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .noVersion), - rest: "")) - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@1.2.3"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .exact("1.2.3")), - rest: "")) - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .from("1.2.3")), - rest: "")) - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@1.2.3..<4.0.0"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .range("1.2.3"..<"4.0.0")), - rest: "")) - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@1.2.3...4.0.0"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .range("1.2.3"..<"4.0.1")), - rest: "")) - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:develop"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .branch("develop")), - rest: "")) - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:feature/a"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .branch("feature/a")), - rest: "")) - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:somerevision"), - Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, - requirement: .revision("somerevision")), - rest: "")) - - // local path dependency - XCTAssertEqual( - Parser.dependency.run("/foo/bar"), - Match(result: Dependency(url: URL(string: "file:///foo/bar")!, requirement: .path), rest: "")) - XCTAssertEqual( - Parser.dependency.run("./foo/bar"), - Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: "")) - XCTAssertEqual( - Parser.dependency.run("~/foo/bar"), - Match(result: Dependency(url: URL(string: "file://\(Path.home)/foo/bar")!, requirement: .path), rest: "")) - XCTAssertEqual( - Parser.dependency.run("foo/bar"), - Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: "")) - XCTAssertEqual( - Parser.dependency.run("../foo/bar"), - Match(result: Dependency(url: URL(string: "file://\(Path.cwd/"../foo/bar")")!, requirement: .path), rest: "")) - } - - func test_parse_dependency_errors() throws { - // unparsable trailing characters - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3trailingjunk"), - Match(result: nil, - rest: "https://github.com/foo/bar@from:1.2.3trailingjunk")) - // invalid version - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3..<2.0.0"), - Match(result: nil, - rest: "https://github.com/foo/bar@from:1.2.3..<2.0.0")) - // invalid branch - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:foo bar"), - Match(result: nil, - rest: "https://github.com/foo/bar@branch:foo bar")) - // invalid revision - XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:1.2.3 rc4"), - Match(result: nil, - rest: "https://github.com/foo/bar@revision:1.2.3 rc4")) - } - func test_dependency_package_clause() throws { do { let dep = Dependency(url: URL(string: "https://github.com/foo/bar")!, requirement: .branch("develop")) diff --git a/Tests/ArenaTests/IntegrationTests.swift b/Tests/ArenaTests/IntegrationTests.swift index 424b739..f106e57 100644 --- a/Tests/ArenaTests/IntegrationTests.swift +++ b/Tests/ArenaTests/IntegrationTests.swift @@ -72,5 +72,30 @@ class IntegrationTests: XCTestCase { } #endif + #if swift(>=5.2) + func test_git_protocol() throws { + try XCTSkipUnless(ProcessInfo().hostName == "luna.local", "fails on CI, only run locally") + + let arena = try Arena.parse([ + "git@github.com:finestructure/ArenaTest@0.0.3", + "--name=ArenaIntegrationTest", + "--force", + "--skip-open"]) + + let exp = self.expectation(description: "exp") + + let progress: ProgressUpdate = { stage, _ in + print("progress: \(stage)") + if stage == .completed { + exp.fulfill() + } + } + + try arena.run(progress: progress) + + wait(for: [exp], timeout: 10) + } + #endif + } diff --git a/Tests/ArenaTests/ParserTests.swift b/Tests/ArenaTests/ParserTests.swift new file mode 100644 index 0000000..86d32c2 --- /dev/null +++ b/Tests/ArenaTests/ParserTests.swift @@ -0,0 +1,143 @@ +// +// ParserTests.swift +// ArenaTests +// +// Created by Sven A. Schmidt on 27/03/2020. +// + +@testable import ArenaCore +import Path +import Parser +import Workspace +import XCTest + + +class ParserTests: XCTestCase { + + func test_parse_version() throws { + XCTAssertEqual(Parser.version.run("1.2.3"), Match(result: Version(1, 2, 3), rest: "")) + XCTAssertEqual(Parser.version.run("1.2.3="), Match(result: Version(1, 2, 3), rest: "=")) + } + + func test_parse_requirement() throws { + XCTAssertEqual(Parser.exact.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: "")) + + XCTAssertEqual(Parser.from.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: "")) + + XCTAssertEqual(Parser.range.run("@1.2.3..<3.2.1"), Match(result: .range("1.2.3"..<"3.2.1"), rest: "")) + XCTAssertEqual(Parser.range.run("@1.2.3...3.2.1"), Match(result: .range("1.2.3"..<"3.2.2"), rest: "")) + + do { // combined + XCTAssertEqual(Parser.refSpec.run(""), Match(result: .noVersion, rest: "")) + XCTAssertEqual(Parser.refSpec.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: "")) + XCTAssertEqual(Parser.refSpec.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: "")) + XCTAssertEqual(Parser.refSpec.run("@1.2.3..<3.0.0"), Match(result: .range("1.2.3"..<"3.0.0"), rest: "")) + } + } + + func test_parse_url() throws { + XCTAssertEqual(Parser.url.run("https://github.com/foo/bar"), + Match(result: URL(string: "https://github.com/foo/bar"), rest: "")) + XCTAssertEqual(Parser.url.run("https://github.com/foo/bar@rest"), + Match(result: URL(string: "https://github.com/foo/bar"), rest: "@rest")) + XCTAssertEqual(Parser.url.run("http://github.com/foo/bar@rest"), + Match(result: URL(string: "http://github.com/foo/bar"), rest: "@rest")) + XCTAssertEqual(Parser.url.run("/foo/bar@rest"), + Match(result: URL(string: "file:///foo/bar"), rest: "@rest")) + XCTAssertEqual(Parser.url.run("file:///foo/bar@rest"), + Match(result: URL(string: "file:///foo/bar"), rest: "@rest")) + XCTAssertEqual(Parser.url.run("file:/foo/bar@rest"), + Match(result: URL(string: "file:///foo/bar"), rest: "@rest")) + } + + func test_parse_branchName() { + XCTAssertEqual(branchName.run("develop"), Match(result: "develop", rest: "")) + XCTAssertEqual(branchName.run("foo-bar"), Match(result: "foo-bar", rest: "")) + // disallowed + XCTAssertEqual(branchName.run("/foo"), Match(result: nil, rest: "/foo")) + XCTAssertEqual(branchName.run("foo."), Match(result: nil, rest: "foo.")) + XCTAssertEqual(branchName.run("foo/"), Match(result: nil, rest: "foo/")) + } + + func test_parse_branch() { + XCTAssertEqual(Parser.branch.run("@branch:develop"), Match(result: .branch("develop"), rest: "")) + } + + func test_parse_revision() { + XCTAssertEqual(Parser.revision.run("@revision:foo"), Match(result: .revision("foo"), rest: "")) + XCTAssertEqual(Parser.revision.run("@revision:7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), Match(result: .revision("7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), rest: "")) + XCTAssertEqual(Parser.revision.run("@revision:1.2.3-rc4"), Match(result: .revision("1.2.3-rc4"), rest: "")) + } + + func test_parse_dependency() throws { + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .noVersion), + rest: "")) + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@1.2.3"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .exact("1.2.3")), + rest: "")) + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .from("1.2.3")), + rest: "")) + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@1.2.3..<4.0.0"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .range("1.2.3"..<"4.0.0")), + rest: "")) + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@1.2.3...4.0.0"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .range("1.2.3"..<"4.0.1")), + rest: "")) + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:develop"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .branch("develop")), + rest: "")) + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:feature/a"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .branch("feature/a")), + rest: "")) + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:somerevision"), + Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!, + requirement: .revision("somerevision")), + rest: "")) + + // local path dependency + XCTAssertEqual( + Parser.dependency.run("/foo/bar"), + Match(result: Dependency(url: URL(string: "file:///foo/bar")!, requirement: .path), rest: "")) + XCTAssertEqual( + Parser.dependency.run("./foo/bar"), + Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: "")) + XCTAssertEqual( + Parser.dependency.run("~/foo/bar"), + Match(result: Dependency(url: URL(string: "file://\(Path.home)/foo/bar")!, requirement: .path), rest: "")) + XCTAssertEqual( + Parser.dependency.run("foo/bar"), + Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: "")) + XCTAssertEqual( + Parser.dependency.run("../foo/bar"), + Match(result: Dependency(url: URL(string: "file://\(Path.cwd/"../foo/bar")")!, requirement: .path), rest: "")) + } + + func test_parse_dependency_errors() throws { + // unparsable trailing characters + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3trailingjunk"), + Match(result: nil, + rest: "https://github.com/foo/bar@from:1.2.3trailingjunk")) + // invalid version + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3..<2.0.0"), + Match(result: nil, + rest: "https://github.com/foo/bar@from:1.2.3..<2.0.0")) + // invalid branch + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:foo bar"), + Match(result: nil, + rest: "https://github.com/foo/bar@branch:foo bar")) + // invalid revision + XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:1.2.3 rc4"), + Match(result: nil, + rest: "https://github.com/foo/bar@revision:1.2.3 rc4")) + } + +} From a1c7ec086bd424ec24a1d2583e870f604fded815 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 27 Mar 2020 14:48:13 +0100 Subject: [PATCH 2/2] Fixes #37, fixes #35 --- Sources/ArenaCore/Parser+ext.swift | 4 ++-- Sources/ArenaCore/Scheme.swift | 8 ++++++++ Tests/ArenaTests/ParserTests.swift | 12 ++++++++++++ misc/run_tests.sh | 4 +++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Sources/ArenaCore/Parser+ext.swift b/Sources/ArenaCore/Parser+ext.swift index 7531c99..3eab109 100644 --- a/Sources/ArenaCore/Parser+ext.swift +++ b/Sources/ArenaCore/Parser+ext.swift @@ -71,7 +71,7 @@ extension Parser where A == RefSpec { extension Parser where A == Scheme { - static var aScheme: Parser { + static var scheme: Parser { oneOf(Scheme.allCases.map { string($0.rawValue).map { Scheme(rawValue: $0)! } } ) } } @@ -80,7 +80,7 @@ extension Parser where A == Scheme { extension Parser where A == Foundation.URL { static var url: Parser { zip( - Parser.aScheme, + Parser.scheme, prefix(upTo: "@").map(String.init) ).flatMap { (scheme, rest) in if let url = scheme.url(path: rest) { diff --git a/Sources/ArenaCore/Scheme.swift b/Sources/ArenaCore/Scheme.swift index 57df93e..afa646d 100644 --- a/Sources/ArenaCore/Scheme.swift +++ b/Sources/ArenaCore/Scheme.swift @@ -12,6 +12,7 @@ import Path enum Scheme: String, CaseIterable { case https = "https://" case http = "http://" + case git = "git@" case file = "file://" case nonstandardizedFile = "file:" case empty = "" @@ -20,6 +21,13 @@ enum Scheme: String, CaseIterable { switch self { case .https, .http, .file: return URL(string: rawValue + path) + case .git: + return URL(string: + "ssh://" + + rawValue + + path + .split(separator: ":", maxSplits: 1) + .joined(separator: "/")) case .nonstandardizedFile: return URL(string: Scheme.file.rawValue + path) case .empty: diff --git a/Tests/ArenaTests/ParserTests.swift b/Tests/ArenaTests/ParserTests.swift index 86d32c2..fb82cc2 100644 --- a/Tests/ArenaTests/ParserTests.swift +++ b/Tests/ArenaTests/ParserTests.swift @@ -121,6 +121,18 @@ class ParserTests: XCTestCase { Match(result: Dependency(url: URL(string: "file://\(Path.cwd/"../foo/bar")")!, requirement: .path), rest: "")) } + func test_parse_dependency_git_protocol() throws { + // git protocol + XCTAssertEqual(Parser.dependency.run("git@github.com:foo/bar.git"), + Match(result: Dependency(url: URL(string: "ssh://git@github.com/foo/bar.git")!, + requirement: .noVersion), + rest: "")) + XCTAssertEqual(Parser.dependency.run("git@github.com:foo/bar"), + Match(result: Dependency(url: URL(string: "ssh://git@github.com/foo/bar")!, + requirement: .noVersion), + rest: "")) + } + func test_parse_dependency_errors() throws { // unparsable trailing characters XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3trailingjunk"), diff --git a/misc/run_tests.sh b/misc/run_tests.sh index 7c6d906..db009dd 100755 --- a/misc/run_tests.sh +++ b/misc/run_tests.sh @@ -5,7 +5,9 @@ swift build for dep in "finestructure/Gala" \ "finestructure/Parser" \ "alamofire/alamofire" \ - "pointfreeco/swift-gen" + "pointfreeco/swift-gen" \ + "~/Projects/Parser" \ + "git@github.com:finestructure/parser" do echo "-------------------------" echo Test: $dep