diff --git a/Parser/.swiftpm/xcode/xcshareddata/xcbaselines/ParserTests.xcbaseline/5AEA6FC6-AD2F-413E-9746-2017D27E25CE.plist b/Parser/.swiftpm/xcode/xcshareddata/xcbaselines/ParserTests.xcbaseline/5AEA6FC6-AD2F-413E-9746-2017D27E25CE.plist
new file mode 100644
index 000000000..6f7946947
--- /dev/null
+++ b/Parser/.swiftpm/xcode/xcshareddata/xcbaselines/ParserTests.xcbaseline/5AEA6FC6-AD2F-413E-9746-2017D27E25CE.plist
@@ -0,0 +1,42 @@
+
+
+
+
+ classNames
+
+ RSSParserTests
+
+ testEMarleyPerformance()
+
+ com.apple.XCTPerformanceMetric_WallClockTime
+
+ baselineAverage
+ 0.000357
+ baselineIntegrationDisplayName
+ Local Baseline
+
+
+ testKatieFloydPerformance()
+
+ com.apple.XCTPerformanceMetric_WallClockTime
+
+ baselineAverage
+ 0.000964
+ baselineIntegrationDisplayName
+ Local Baseline
+
+
+ testScriptingNewsPerformance()
+
+ com.apple.XCTPerformanceMetric_WallClockTime
+
+ baselineAverage
+ 0.001750
+ baselineIntegrationDisplayName
+ Local Baseline
+
+
+
+
+
+
diff --git a/Parser/.swiftpm/xcode/xcshareddata/xcbaselines/ParserTests.xcbaseline/Info.plist b/Parser/.swiftpm/xcode/xcshareddata/xcbaselines/ParserTests.xcbaseline/Info.plist
new file mode 100644
index 000000000..762b35539
--- /dev/null
+++ b/Parser/.swiftpm/xcode/xcshareddata/xcbaselines/ParserTests.xcbaseline/Info.plist
@@ -0,0 +1,33 @@
+
+
+
+
+ runDestinationsByUUID
+
+ 5AEA6FC6-AD2F-413E-9746-2017D27E25CE
+
+ localComputer
+
+ busSpeedInMHz
+ 0
+ cpuCount
+ 1
+ cpuKind
+ Apple M1 Max
+ cpuSpeedInMHz
+ 0
+ logicalCPUCoresPerPackage
+ 10
+ modelCode
+ Mac13,1
+ physicalCPUCoresPerPackage
+ 10
+ platformIdentifier
+ com.apple.platform.macosx
+
+ targetArchitecture
+ arm64e
+
+
+
+
diff --git a/Parser/Sources/Swift/Feeds/FeedParser.swift b/Parser/Sources/Swift/Feeds/FeedParser.swift
index adf859a26..4c5eb3338 100644
--- a/Parser/Sources/Swift/Feeds/FeedParser.swift
+++ b/Parser/Sources/Swift/Feeds/FeedParser.swift
@@ -48,4 +48,29 @@ public struct FeedParser {
return nil
}
}
+
+ /// For unit tests measuring performance.
+ public static func parseSync(_ parserData: ParserData) throws -> ParsedFeed? {
+
+ let type = feedType(parserData)
+
+ switch type {
+
+ case .jsonFeed:
+ return try JSONFeedParser.parse(parserData)
+
+ case .rssInJSON:
+ return try RSSInJSONParser.parse(parserData)
+
+ case .rss:
+ return RSSParser.parse(parserData)
+
+ case .atom:
+ return AtomParser.parse(parserData)
+
+ case .unknown, .notAFeed:
+ return nil
+ }
+ }
+
}
diff --git a/Parser/Tests/ParserTests/AtomParserTests.swift b/Parser/Tests/ParserTests/AtomParserTests.swift
index 500f78c29..dc9fb89d9 100644
--- a/Parser/Tests/ParserTests/AtomParserTests.swift
+++ b/Parser/Tests/ParserTests/AtomParserTests.swift
@@ -16,7 +16,7 @@ class AtomParserTests: XCTestCase {
// 0.009 sec on my 2012 iMac.
let d = parserData("DaringFireball", "atom", "http://daringfireball.net/") //It’s actually an Atom feed
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
@@ -25,22 +25,22 @@ class AtomParserTests: XCTestCase {
// 0.003 sec on my 2012 iMac.
let d = parserData("allthis", "atom", "http://leancrew.com/all-this")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
- func testGettingHomePageLink() {
+ func testGettingHomePageLink() async {
let d = parserData("allthis", "atom", "http://leancrew.com/all-this")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertTrue(parsedFeed.homePageURL == "http://leancrew.com/all-this")
}
- func testDaringFireball() {
+ func testDaringFireball() async {
let d = parserData("DaringFireball", "atom", "http://daringfireball.net/") //It’s actually an Atom feed
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
@@ -65,12 +65,12 @@ class AtomParserTests: XCTestCase {
}
}
- func test4fsodonlineAttachments() {
+ func test4fsodonlineAttachments() async {
// Thanks to Marco for finding me some Atom podcast feeds. Apparently they’re super-rare.
let d = parserData("4fsodonline", "atom", "http://4fsodonline.blogspot.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
@@ -83,12 +83,12 @@ class AtomParserTests: XCTestCase {
}
}
- func testExpertOpinionENTAttachments() {
+ func testExpertOpinionENTAttachments() async {
// Another from Marco.
let d = parserData("expertopinionent", "atom", "http://expertopinionent.typepad.com/my-blog/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
diff --git a/Parser/Tests/ParserTests/JSONFeedParserTests.swift b/Parser/Tests/ParserTests/JSONFeedParserTests.swift
index 547fe646c..fc3af8e5e 100644
--- a/Parser/Tests/ParserTests/JSONFeedParserTests.swift
+++ b/Parser/Tests/ParserTests/JSONFeedParserTests.swift
@@ -16,7 +16,7 @@ class JSONFeedParserTests: XCTestCase {
// 0.001 sec on my 2012 iMac.
let d = parserData("inessential", "json", "http://inessential.com/")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
@@ -25,31 +25,31 @@ class JSONFeedParserTests: XCTestCase {
// 0.009 sec on my 2012 iMac.
let d = parserData("DaringFireball", "json", "http://daringfireball.net/")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
- func testGettingFaviconAndIconURLs() {
+ func testGettingFaviconAndIconURLs() async {
let d = parserData("DaringFireball", "json", "http://daringfireball.net/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssert(parsedFeed.faviconURL == "https://daringfireball.net/graphics/favicon-64.png")
XCTAssert(parsedFeed.iconURL == "https://daringfireball.net/graphics/apple-touch-icon.png")
}
- func testAllThis() {
+ func testAllThis() async {
let d = parserData("allthis", "json", "http://leancrew.com/allthis/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.items.count, 12)
}
- func testCurt() {
-
+ func testCurt() async {
+
let d = parserData("curt", "json", "http://curtclifton.net/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.items.count, 26)
@@ -64,23 +64,23 @@ class JSONFeedParserTests: XCTestCase {
XCTAssertTrue(didFindTwitterQuitterArticle)
}
- func testPixelEnvy() {
+ func testPixelEnvy() async {
let d = parserData("pxlnv", "json", "http://pxlnv.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.items.count, 20)
}
- func testRose() {
+ func testRose() async {
let d = parserData("rose", "json", "http://www.rosemaryorchard.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.items.count, 84)
}
- func test3960() {
+ func test3960() async {
let d = parserData("3960", "json", "http://journal.3960.org/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.items.count, 20)
XCTAssertEqual(parsedFeed.language, "de-DE")
@@ -89,9 +89,9 @@ class JSONFeedParserTests: XCTestCase {
}
}
- func testAuthors() {
+ func testAuthors() async {
let d = parserData("authors", "json", "https://example.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.items.count, 4)
let rootAuthors = Set([
diff --git a/Parser/Tests/ParserTests/RSSInJSONParserTests.swift b/Parser/Tests/ParserTests/RSSInJSONParserTests.swift
index c34fcd933..cbfce4d13 100644
--- a/Parser/Tests/ParserTests/RSSInJSONParserTests.swift
+++ b/Parser/Tests/ParserTests/RSSInJSONParserTests.swift
@@ -16,13 +16,13 @@ class RSSInJSONParserTests: XCTestCase {
// 0.003 sec on my 2012 iMac.
let d = parserData("ScriptingNews", "json", "http://scripting.com/")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
func testFeedLanguage() {
let d = parserData("ScriptingNews", "json", "http://scripting.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! FeedParser.parseSync(d)!
XCTAssertEqual(parsedFeed.language, "en-us")
}
}
diff --git a/Parser/Tests/ParserTests/RSSParserTests.swift b/Parser/Tests/ParserTests/RSSParserTests.swift
index 48cfadc77..c60229ca3 100644
--- a/Parser/Tests/ParserTests/RSSParserTests.swift
+++ b/Parser/Tests/ParserTests/RSSParserTests.swift
@@ -14,50 +14,54 @@ class RSSParserTests: XCTestCase {
func testScriptingNewsPerformance() {
// 0.004 sec on my 2012 iMac.
+ // 0.002 2022 Mac Studio
let d = parserData("scriptingNews", "rss", "http://scripting.com/")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
func testKatieFloydPerformance() {
// 0.004 sec on my 2012 iMac.
+ // 0.001 2022 Mac Studio
let d = parserData("KatieFloyd", "rss", "http://katiefloyd.com/")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
func testEMarleyPerformance() {
// 0.001 sec on my 2012 iMac.
+ // 0.0004 2022 Mac Studio
let d = parserData("EMarley", "rss", "https://medium.com/@emarley")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
func testMantonPerformance() {
// 0.002 sec on my 2012 iMac.
+ // 0.0006 2022 Mac Studio
let d = parserData("manton", "rss", "http://manton.org/")
self.measure {
- let _ = try! FeedParser.parse(d)
+ let _ = try! FeedParser.parseSync(d)
}
}
- func testNatashaTheRobot() {
+ func testNatashaTheRobot() async {
let d = parserData("natasha", "xml", "https://www.natashatherobot.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.items.count, 10)
}
- func testTheOmniShowAttachments() {
+ func testTheOmniShowAttachments() async {
let d = parserData("theomnishow", "rss", "https://theomnishow.omnigroup.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNotNil(article.attachments)
@@ -71,10 +75,10 @@ class RSSParserTests: XCTestCase {
}
}
- func testTheOmniShowUniqueIDs() {
+ func testTheOmniShowUniqueIDs() async {
let d = parserData("theomnishow", "rss", "https://theomnishow.omnigroup.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNotNil(article.uniqueID)
@@ -82,12 +86,12 @@ class RSSParserTests: XCTestCase {
}
}
- func testMacworldUniqueIDs() {
+ func testMacworldUniqueIDs() async {
// Macworld’s feed doesn’t have guids, so they should be calculated unique IDs.
let d = parserData("macworld", "rss", "https://www.macworld.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNotNil(article.uniqueID)
@@ -95,12 +99,12 @@ class RSSParserTests: XCTestCase {
}
}
- func testMacworldAuthors() {
+ func testMacworldAuthors() async {
// Macworld uses names instead of email addresses (despite the RSS spec saying they should be email addresses).
let d = parserData("macworld", "rss", "https://www.macworld.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
@@ -111,7 +115,7 @@ class RSSParserTests: XCTestCase {
}
}
- func testMonkeyDomGuids() {
+ func testMonkeyDomGuids() async {
// https://coding.monkeydom.de/posts.rss has a bug in the feed (at this writing):
// It has guids that are supposed to be permalinks, per the spec —
@@ -119,7 +123,7 @@ class RSSParserTests: XCTestCase {
// detect this situation, and every article in the feed should have a permalink.
let d = parserData("monkeydom", "rss", "https://coding.monkeydom.de/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNil(article.url)
@@ -127,31 +131,31 @@ class RSSParserTests: XCTestCase {
}
}
- func testEmptyContentEncoded() {
+ func testEmptyContentEncoded() async {
// The ATP feed (at the time of this writing) has some empty content:encoded elements. The parser should ignore those.
// https://github.com/brentsimmons/NetNewsWire/issues/529
let d = parserData("atp", "rss", "http://atp.fm/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNotNil(article.contentHTML)
}
}
- func testFeedKnownToHaveGuidsThatArentPermalinks() {
+ func testFeedKnownToHaveGuidsThatArentPermalinks() async {
let d = parserData("livemint", "xml", "https://www.livemint.com/rss/news")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNil(article.url)
}
}
- func testAuthorsWithTitlesInside() {
+ func testAuthorsWithTitlesInside() async {
// This feed uses atom authors, and we don’t want author/title to be used as item/title.
// https://github.com/brentsimmons/NetNewsWire/issues/943
let d = parserData("cloudblog", "rss", "https://cloudblog.withgoogle.com/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNotEqual(article.title, "Product Manager, Office of the CTO")
XCTAssertNotEqual(article.title, "Developer Programs Engineer")
@@ -159,19 +163,19 @@ class RSSParserTests: XCTestCase {
}
}
- func testTitlesWithInvalidFeedWithImageStructures() {
+ func testTitlesWithInvalidFeedWithImageStructures() async {
// This invalid feed has elements inside - s.
// 17 Jan 2021 bug report — we’re not parsing titles in this feed.
let d = parserData("aktuality", "rss", "https://www.aktuality.sk/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
for article in parsedFeed.items {
XCTAssertNotNil(article.title)
}
}
- func testFeedLanguage() {
+ func testFeedLanguage() async {
let d = parserData("manton", "rss", "http://manton.org/")
- let parsedFeed = try! FeedParser.parse(d)!
+ let parsedFeed = try! await FeedParser.parse(d)!
XCTAssertEqual(parsedFeed.language, "en-US")
}