From dd96d4cb66f170beafb7944fea61a1ae404c23b4 Mon Sep 17 00:00:00 2001 From: Moritz Lang Date: Mon, 17 Aug 2020 11:58:35 +0200 Subject: [PATCH] [WIP] Downgrade to Swift 5.0 --- .github/workflows/ci.yaml | 14 +- .swiftformat | 4 +- Package.resolved | 4 +- Package.swift | 25 +- .../InstrumentationSystem.swift | 6 +- .../Instrumentation/MultiplexInstrument.swift | 2 +- .../HTTPHeadersCarrier.swift | 2 +- .../SpanAttribute+EndUser.swift | 2 + .../SpanAttribute+HTTPSemantics.swift | 2 + .../SpanAttribute+NetSemantics.swift | 2 + .../SpanAttribute+PeerSemantics.swift | 2 + .../ArgParser.swift | 2 +- .../BenchmarkCategory.swift | 0 .../BenchmarkTools.swift | 28 +- .../DriverUtils.swift | 46 ++-- .../README_SWIFT.md | 0 .../ExampleBenchmark.swift | 2 +- .../main.swift | 2 +- .../InstrumentationSystem+Tracing.swift | 4 +- .../NoOpTracingInstrument.swift | 8 +- Sources/TracingInstrumentation/Span.swift | 54 +++- .../TracingInstrumentation/Timestamp.swift | 12 +- .../TracingInstrument.swift | 2 +- .../InstrumentTests+XCTest.swift | 32 +++ .../InstrumentTests.swift | 10 +- .../InstrumentationSystemTests+XCTest.swift | 32 +++ Tests/LinuxMain.swift | 51 ++++ ...ontextInboundHTTPHandlerTests+XCTest.swift | 32 +++ ...ntextOutboundHTTPHandlerTests+XCTest.swift | 32 +++ .../NIOInstrumentationTests/FakeTracer.swift | 4 +- .../SpanAttributeSemanticsTests+XCTest.swift | 32 +++ .../SpanAttributeSemanticsTests.swift | 2 + .../SpanTests+XCTest.swift | 43 ++++ .../SpanTests.swift | 16 +- .../TimestampTests+XCTest.swift | 32 +++ .../TracedLockTests+XCTest.swift | 32 +++ .../TracedLockTests.swift | 2 +- .../TracingInstrumentTests+XCTest.swift | 33 +++ .../TracingInstrumentTests.swift | 2 +- UseCases/Package.resolved | 4 +- UseCases/Package.swift | 37 ++- .../ManualContextPropagation/main.swift | 34 +-- scripts/generate_linux_tests.rb | 241 ++++++++++++++++++ scripts/sanity.sh | 12 + 44 files changed, 805 insertions(+), 135 deletions(-) rename Sources/{SwiftBenchmarkTools => TracingBenchmarkTools}/ArgParser.swift (99%) rename Sources/{SwiftBenchmarkTools => TracingBenchmarkTools}/BenchmarkCategory.swift (100%) rename Sources/{SwiftBenchmarkTools => TracingBenchmarkTools}/BenchmarkTools.swift (90%) rename Sources/{SwiftBenchmarkTools => TracingBenchmarkTools}/DriverUtils.swift (95%) rename Sources/{SwiftBenchmarkTools => TracingBenchmarkTools}/README_SWIFT.md (100%) rename Sources/{Benchmarks => TracingBenchmarks}/ExampleBenchmark.swift (97%) rename Sources/{Benchmarks => TracingBenchmarks}/main.swift (97%) create mode 100644 Tests/InstrumentationTests/InstrumentTests+XCTest.swift create mode 100644 Tests/InstrumentationTests/InstrumentationSystemTests+XCTest.swift create mode 100644 Tests/LinuxMain.swift create mode 100644 Tests/NIOInstrumentationTests/BaggageContextInboundHTTPHandlerTests+XCTest.swift create mode 100644 Tests/NIOInstrumentationTests/BaggageContextOutboundHTTPHandlerTests+XCTest.swift create mode 100644 Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests+XCTest.swift create mode 100644 Tests/TracingInstrumentationTests/SpanTests+XCTest.swift create mode 100644 Tests/TracingInstrumentationTests/TimestampTests+XCTest.swift create mode 100644 Tests/TracingInstrumentationTests/TracedLockTests+XCTest.swift create mode 100644 Tests/TracingInstrumentationTests/TracingInstrumentTests+XCTest.swift create mode 100755 scripts/generate_linux_tests.rb diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 789c172..3a6a3cc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,18 +4,26 @@ on: [push, pull_request] jobs: unit-test: + strategy: + matrix: + # GitHub Actions replaces 5.0 with 5 so we have to be specific here + swift: [5.0.3, 5.1, 5.2] runs-on: ubuntu-latest - container: swift:5.2 + container: swift:${{ matrix.swift }} steps: - name: Checkout uses: actions/checkout@v1 - name: Resolve Swift dependencies run: swift package resolve - name: Build & Test - run: swift test -c release --enable-test-discovery + run: swift test compile-usecases: + strategy: + matrix: + # GitHub Actions replaces 5.0 with 5 so we have to be specific here + swift: [5.0.3, 5.1, 5.2] runs-on: ubuntu-latest - container: swift:5.2 + container: swift:${{ matrix.swift }} steps: - name: Checkout uses: actions/checkout@v1 diff --git a/.swiftformat b/.swiftformat index cbe55e4..5a16ed9 100644 --- a/.swiftformat +++ b/.swiftformat @@ -1,8 +1,10 @@ # file options ---swiftversion 5.2 +--swiftversion 5.0 --exclude .build --exclude UseCases/.build +--exclude Tests/LinuxMain.swift +--exclude **/*Tests+XCTest.swift # format options diff --git a/Package.resolved b/Package.resolved index 4f61489..6df32ef 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/slashmo/gsoc-swift-baggage-context.git", "state": { "branch": null, - "revision": "71ef1080972a1cac47ab80d995d6bdc370fb20f2", - "version": "0.2.0" + "revision": "744d984ac940535287cb036e44e6970c2a93f012", + "version": "0.3.0" } }, { diff --git a/Package.swift b/Package.swift index 796fffb..07b544b 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.2 +// swift-tools-version:5.0 import PackageDescription let package = Package( @@ -11,9 +11,8 @@ let package = Package( ], dependencies: [ .package( - name: "swift-baggage-context", url: "https://github.com/slashmo/gsoc-swift-baggage-context.git", - from: "0.2.0" + from: "0.3.0" ), .package(url: "https://github.com/apple/swift-nio.git", from: "2.17.0") ], @@ -24,7 +23,7 @@ let package = Package( .target( name: "Instrumentation", dependencies: [ - .product(name: "Baggage", package: "swift-baggage-context"), + "Baggage", ] ), .testTarget( @@ -37,7 +36,7 @@ let package = Package( .target( name: "TracingInstrumentation", dependencies: [ - "Instrumentation" + "Instrumentation", ] ), .testTarget( @@ -45,15 +44,15 @@ let package = Package( dependencies: [ "Instrumentation", "TracingInstrumentation", - .product(name: "BaggageLogging", package: "swift-baggage-context"), + "BaggageLogging", ] ), .target( name: "NIOInstrumentation", dependencies: [ - .product(name: "NIO", package: "swift-nio"), - .product(name: "NIOHTTP1", package: "swift-nio"), + "NIO", + "NIOHTTP1", "Instrumentation", ] ), @@ -73,7 +72,7 @@ let package = Package( .testTarget( name: "OpenTelemetryInstrumentationSupportTests", dependencies: [ - "OpenTelemetryInstrumentationSupport" + "OpenTelemetryInstrumentationSupport", ] ), @@ -81,14 +80,14 @@ let package = Package( // MARK: Performance / Benchmarks .target( - name: "Benchmarks", + name: "TracingBenchmarks", dependencies: [ - .product(name: "Baggage", package: "swift-baggage-context"), - "SwiftBenchmarkTools", + "Baggage", + "TracingBenchmarkTools", ] ), .target( - name: "SwiftBenchmarkTools", + name: "TracingBenchmarkTools", dependencies: [] ), ] diff --git a/Sources/Instrumentation/InstrumentationSystem.swift b/Sources/Instrumentation/InstrumentationSystem.swift index 55342ce..72f32d1 100644 --- a/Sources/Instrumentation/InstrumentationSystem.swift +++ b/Sources/Instrumentation/InstrumentationSystem.swift @@ -65,7 +65,7 @@ public enum InstrumentationSystem { /// /// Defaults to a no-op `Instrument` if `boostrap` wasn't called before. public static var instrument: Instrument { - self.lock.withReaderLock { self._instrument } + return self.lock.withReaderLock { self._instrument } } /// Get an `Instrument` instance of the given type. @@ -75,14 +75,14 @@ public enum InstrumentationSystem { /// - Parameter instrumentType: The type of `Instrument` you want to retrieve an instance for. /// - Returns: An `Instrument` instance of the given type or `nil` if no `Instrument` of that type has been bootstrapped. public static func instrument(of instrumentType: I.Type) -> I? where I: Instrument { - self._findInstrument(where: { $0 is I }) as? I + return self._findInstrument(where: { $0 is I }) as? I } } extension InstrumentationSystem { /// :nodoc: INTERNAL API: Do Not Use public static func _findInstrument(where predicate: (Instrument) -> Bool) -> Instrument? { - self.lock.withReaderLock { + return self.lock.withReaderLock { if let multiplex = self._instrument as? MultiplexInstrument { return multiplex.firstInstrument(where: predicate) } else if predicate(self._instrument) { diff --git a/Sources/Instrumentation/MultiplexInstrument.swift b/Sources/Instrumentation/MultiplexInstrument.swift index 2f22d53..f40b29e 100644 --- a/Sources/Instrumentation/MultiplexInstrument.swift +++ b/Sources/Instrumentation/MultiplexInstrument.swift @@ -29,7 +29,7 @@ public struct MultiplexInstrument { extension MultiplexInstrument { func firstInstrument(where predicate: (Instrument) -> Bool) -> Instrument? { - self.instruments.first(where: predicate) + return self.instruments.first(where: predicate) } } diff --git a/Sources/NIOInstrumentation/HTTPHeadersCarrier.swift b/Sources/NIOInstrumentation/HTTPHeadersCarrier.swift index e920ca7..a3c24ad 100644 --- a/Sources/NIOInstrumentation/HTTPHeadersCarrier.swift +++ b/Sources/NIOInstrumentation/HTTPHeadersCarrier.swift @@ -18,7 +18,7 @@ public struct HTTPHeadersExtractor: ExtractorProtocol { public init() {} public func extract(key: String, from headers: HTTPHeaders) -> String? { - headers.first(name: key) + return headers.first(name: key) } } diff --git a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+EndUser.swift b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+EndUser.swift index 937689e..2052700 100644 --- a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+EndUser.swift +++ b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+EndUser.swift @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=5.2) import TracingInstrumentation extension SpanAttributes { @@ -48,3 +49,4 @@ public struct EndUserAttributes: SpanAttributeNamespace { public var scope: SpanAttributeKey { "enduser.scope" } } } +#endif diff --git a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+HTTPSemantics.swift b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+HTTPSemantics.swift index 6fa1b32..036d80a 100644 --- a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+HTTPSemantics.swift +++ b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+HTTPSemantics.swift @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=5.2) import TracingInstrumentation extension SpanAttributes { @@ -98,3 +99,4 @@ public struct HTTPAttributes: SpanAttributeNamespace { public var serverClientIP: SpanAttributeKey { "http.client_ip" } } } +#endif diff --git a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+NetSemantics.swift b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+NetSemantics.swift index d206349..02a0594 100644 --- a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+NetSemantics.swift +++ b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+NetSemantics.swift @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=5.2) import TracingInstrumentation extension SpanAttributes { @@ -59,3 +60,4 @@ public struct NetAttributes: SpanAttributeNamespace { public var hostName: SpanAttributeKey { "net.host.name" } } } +#endif diff --git a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+PeerSemantics.swift b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+PeerSemantics.swift index 70cc8de..4cdf3a6 100644 --- a/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+PeerSemantics.swift +++ b/Sources/OpenTelemetryInstrumentationSupport/SpanAttribute+PeerSemantics.swift @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#if compiler(>=5.2) import TracingInstrumentation extension SpanAttributes { @@ -41,3 +42,4 @@ public struct PeerAttributes: SpanAttributeNamespace { public var service: SpanAttributeKey { "peer.service" } } } +#endif diff --git a/Sources/SwiftBenchmarkTools/ArgParser.swift b/Sources/TracingBenchmarkTools/ArgParser.swift similarity index 99% rename from Sources/SwiftBenchmarkTools/ArgParser.swift rename to Sources/TracingBenchmarkTools/ArgParser.swift index 2f41a1b..07f1189 100644 --- a/Sources/SwiftBenchmarkTools/ArgParser.swift +++ b/Sources/TracingBenchmarkTools/ArgParser.swift @@ -74,7 +74,7 @@ func checked( class ArgumentParser { private var result: U private var validOptions: [String] { - self.arguments.compactMap { $0.name } + return self.arguments.compactMap { $0.name } } private var arguments: [Argument] = [] diff --git a/Sources/SwiftBenchmarkTools/BenchmarkCategory.swift b/Sources/TracingBenchmarkTools/BenchmarkCategory.swift similarity index 100% rename from Sources/SwiftBenchmarkTools/BenchmarkCategory.swift rename to Sources/TracingBenchmarkTools/BenchmarkCategory.swift diff --git a/Sources/SwiftBenchmarkTools/BenchmarkTools.swift b/Sources/TracingBenchmarkTools/BenchmarkTools.swift similarity index 90% rename from Sources/SwiftBenchmarkTools/BenchmarkTools.swift rename to Sources/TracingBenchmarkTools/BenchmarkTools.swift index 5561a38..1c56807 100644 --- a/Sources/SwiftBenchmarkTools/BenchmarkTools.swift +++ b/Sources/TracingBenchmarkTools/BenchmarkTools.swift @@ -25,13 +25,13 @@ import Darwin extension BenchmarkCategory: CustomStringConvertible { public var description: String { - self.rawValue + return self.rawValue } } extension BenchmarkCategory: Comparable { public static func < (lhs: BenchmarkCategory, rhs: BenchmarkCategory) -> Bool { - lhs.rawValue < rhs.rawValue + return lhs.rawValue < rhs.rawValue } } @@ -54,7 +54,7 @@ public struct BenchmarkPlatformSet: OptionSet { } public static var allPlatforms: BenchmarkPlatformSet { - [.darwin, .linux] + return [.darwin, .linux] } } @@ -124,17 +124,17 @@ public struct BenchmarkInfo { /// Returns true if this benchmark should be run on the current platform. var shouldRun: Bool { - !self.unsupportedPlatforms.contains(.currentPlatform) + return !self.unsupportedPlatforms.contains(.currentPlatform) } } extension BenchmarkInfo: Comparable { public static func < (lhs: BenchmarkInfo, rhs: BenchmarkInfo) -> Bool { - lhs.name < rhs.name + return lhs.name < rhs.name } public static func == (lhs: BenchmarkInfo, rhs: BenchmarkInfo) -> Bool { - lhs.name == rhs.name + return lhs.name == rhs.name } } @@ -175,7 +175,7 @@ public func SRand() { } public func Random() -> Int64 { - lfsrRandomGenerator.randInt() + return lfsrRandomGenerator.randInt() } @inlinable // FIXME(inline-always) @@ -192,16 +192,16 @@ public func CheckResults( } } -public func False() -> Bool { false } +public func False() -> Bool { return false } /// This is a dummy protocol to test the speed of our protocol dispatch. public protocol SomeProtocol { func getValue() -> Int } struct MyStruct: SomeProtocol { init() {} - func getValue() -> Int { 1 } + func getValue() -> Int { return 1 } } -public func someProtocolFactory() -> SomeProtocol { MyStruct() } +public func someProtocolFactory() -> SomeProtocol { return MyStruct() } // Just consume the argument. // It's important that this function is in another module than the tests @@ -212,19 +212,19 @@ public func blackHole(_: T) {} // Return the passed argument without letting the optimizer know that. @inline(never) public func identity(_ x: T) -> T { - x + return x } // Return the passed argument without letting the optimizer know that. // It's important that this function is in another module than the tests // which are using it. @inline(never) -public func getInt(_ x: Int) -> Int { x } +public func getInt(_ x: Int) -> Int { return x } // The same for String. @inline(never) -public func getString(_ s: String) -> String { s } +public func getString(_ s: String) -> String { return s } // The same for Substring. @inline(never) -public func getSubstring(_ s: Substring) -> Substring { s } +public func getSubstring(_ s: Substring) -> Substring { return s } diff --git a/Sources/SwiftBenchmarkTools/DriverUtils.swift b/Sources/TracingBenchmarkTools/DriverUtils.swift similarity index 95% rename from Sources/SwiftBenchmarkTools/DriverUtils.swift rename to Sources/TracingBenchmarkTools/DriverUtils.swift index c5b717d..98a52be 100644 --- a/Sources/SwiftBenchmarkTools/DriverUtils.swift +++ b/Sources/TracingBenchmarkTools/DriverUtils.swift @@ -54,12 +54,12 @@ public struct BenchResults { return self.samples[index] } - var sampleCount: T { self.samples.count } - var min: T { self.samples.first! } - var max: T { self.samples.last! } - var mean: T { Int(self.stats.mean.rounded()) } - var sd: T { Int(self.stats.standardDeviation.rounded()) } - var median: T { self[0.5] } + var sampleCount: T { return self.samples.count } + var min: T { return self.samples.first! } + var max: T { return self.samples.last! } + var mean: T { return Int(self.stats.mean.rounded()) } + var sd: T { return Int(self.stats.standardDeviation.rounded()) } + var median: T { return self[0.5] } } public var registeredBenchmarks: [BenchmarkInfo] = [] @@ -135,14 +135,14 @@ struct TestConfig { // We support specifying multiple tags by splitting on comma, i.e.: // --tags=Array,Dictionary // --skip-tags=Array,Set,unstable,skip - Set( + return Set( try tags.split(separator: ",").map(String.init).map { try checked({ BenchmarkCategory(rawValue: $0) }, $0) } ) } func finiteDouble(value: String) -> Double? { - Double(value).flatMap { $0.isFinite ? $0 : nil } + return Double(value).flatMap { $0.isFinite ? $0 : nil } } // Configure the command line argument parser @@ -294,11 +294,11 @@ struct TestConfig { ) func byTags(b: BenchmarkInfo) -> Bool { - b.tags.isSuperset(of: tags) && + return b.tags.isSuperset(of: tags) && b.tags.isDisjoint(with: skipTags) } func byNamesOrIndices(b: BenchmarkInfo) -> Bool { - specifiedTests.contains(b.name) || + return specifiedTests.contains(b.name) || specifiedTests.contains(indices[b.name]!) } // !! "`allTests` have been assigned an index" return allTests @@ -311,8 +311,8 @@ struct Stats { var n: Int = 0 var S: Double = 0.0 var mean: Double = 0.0 - var variance: Double { self.n < 2 ? 0.0 : self.S / Double(self.n - 1) } - var standardDeviation: Double { self.variance.squareRoot() } + var variance: Double { return self.n < 2 ? 0.0 : self.S / Double(self.n - 1) } + var standardDeviation: Double { return self.variance.squareRoot() } static func collect(_ s: inout Stats, _ x: Int) { Stats.runningMeanVariance(&s, Double(x)) @@ -353,7 +353,7 @@ public final class Timer { } public func getTimeAsInt() -> UInt64 { - UInt64(getTime().tv_nsec) + return UInt64(getTime().tv_nsec) } public func diffTimeInNanoSeconds(from start: TimeT, to end: TimeT) -> UInt64 { @@ -378,11 +378,11 @@ public final class Timer { } public func getTime() -> TimeT { - mach_absolute_time() + return mach_absolute_time() } public func getTimeAsInt() -> UInt64 { - UInt64(getTime()) + return UInt64(getTime()) } public func diffTimeInNanoSeconds(from start: TimeT, to end: TimeT) -> UInt64 { @@ -393,10 +393,10 @@ public final class Timer { } extension UInt64 { - public var nanoseconds: Int { Int(self) } - public var microseconds: Int { Int(self / 1000) } - public var milliseconds: Int { Int(self / 1000 / 1000) } - public var seconds: Int { Int(self / 1000 / 1000 / 1000) } + public var nanoseconds: Int { return Int(self) } + public var microseconds: Int { return Int(self / 1000) } + public var milliseconds: Int { return Int(self / 1000 / 1000) } + public var seconds: Int { return Int(self / 1000 / 1000 / 1000) } } enum TimeUnit: String { @@ -420,7 +420,7 @@ enum TimeUnit: String { extension TimeUnit: CustomStringConvertible { public var description: String { - self.rawValue + return self.rawValue } } @@ -447,7 +447,7 @@ final class TestRunner { private static func getExecutedInstructions() -> UInt64 { // FIXME: there is a Linux PMC API you can use to get this, but it's // not quite so straightforward. - 0 + return 0 } #else @@ -460,7 +460,7 @@ final class TestRunner { // } // return u.ri_instructions // } else { - 0 + return 0 // } } #endif @@ -533,7 +533,7 @@ final class TestRunner { /// Time in nanoseconds spent running the last function var lastSampleTime: UInt64 { - timer.diffTimeInNanoSeconds(from: start, to: end) + return timer.diffTimeInNanoSeconds(from: start, to: end) } /// Measure the `fn` and return the average sample time per iteration (in c.timeUnit). diff --git a/Sources/SwiftBenchmarkTools/README_SWIFT.md b/Sources/TracingBenchmarkTools/README_SWIFT.md similarity index 100% rename from Sources/SwiftBenchmarkTools/README_SWIFT.md rename to Sources/TracingBenchmarkTools/README_SWIFT.md diff --git a/Sources/Benchmarks/ExampleBenchmark.swift b/Sources/TracingBenchmarks/ExampleBenchmark.swift similarity index 97% rename from Sources/Benchmarks/ExampleBenchmark.swift rename to Sources/TracingBenchmarks/ExampleBenchmark.swift index b2539c0..878f812 100644 --- a/Sources/Benchmarks/ExampleBenchmark.swift +++ b/Sources/TracingBenchmarks/ExampleBenchmark.swift @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -import SwiftBenchmarkTools +import TracingBenchmarkTools public let ExampleBenchmarks: [BenchmarkInfo] = [ BenchmarkInfo( diff --git a/Sources/Benchmarks/main.swift b/Sources/TracingBenchmarks/main.swift similarity index 97% rename from Sources/Benchmarks/main.swift rename to Sources/TracingBenchmarks/main.swift index b48840c..352bde0 100644 --- a/Sources/Benchmarks/main.swift +++ b/Sources/TracingBenchmarks/main.swift @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -import SwiftBenchmarkTools +import TracingBenchmarkTools assert({ print("===========================================================================") diff --git a/Sources/TracingInstrumentation/InstrumentationSystem+Tracing.swift b/Sources/TracingInstrumentation/InstrumentationSystem+Tracing.swift index 04b33d7..6e20e39 100644 --- a/Sources/TracingInstrumentation/InstrumentationSystem+Tracing.swift +++ b/Sources/TracingInstrumentation/InstrumentationSystem+Tracing.swift @@ -25,7 +25,7 @@ extension InstrumentationSystem { /// - Parameter instrumentType: The type of `Instrument` you want to retrieve an instance for. /// - Returns: An `Instrument` instance of the given type or `nil` if no `Instrument` of that type has been bootstrapped. public static func tracingInstrument(of instrumentType: T.Type) -> T? where T: TracingInstrument { - self._findInstrument(where: { $0 is T }) as? T + return self._findInstrument(where: { $0 is T }) as? T } /// Returns the `TracingInstrument` bootstrapped as part of the `InstrumentationSystem`. @@ -35,6 +35,6 @@ extension InstrumentationSystem { /// /// - Returns: A `TracingInstrument` if the system was bootstrapped with one, and `NoOpTracingInstrument` otherwise. public static var tracingInstrument: TracingInstrument { - (self._findInstrument(where: { $0 is TracingInstrument }) as? TracingInstrument) ?? NoOpTracingInstrument() + return (self._findInstrument(where: { $0 is TracingInstrument }) as? TracingInstrument) ?? NoOpTracingInstrument() } } diff --git a/Sources/TracingInstrumentation/NoOpTracingInstrument.swift b/Sources/TracingInstrumentation/NoOpTracingInstrument.swift index ee974d0..1bc6edd 100644 --- a/Sources/TracingInstrumentation/NoOpTracingInstrument.swift +++ b/Sources/TracingInstrumentation/NoOpTracingInstrument.swift @@ -22,7 +22,7 @@ public struct NoOpTracingInstrument: TracingInstrument { ofKind kind: SpanKind, at timestamp: Timestamp ) -> Span { - NoOpSpan() + return NoOpSpan() } public func forceFlush() {} @@ -51,13 +51,13 @@ public struct NoOpTracingInstrument: TracingInstrument { public let kind: SpanKind = .internal public var startTimestamp: Timestamp { - .now() + return .now() } public var endTimestamp: Timestamp? public var context: BaggageContext { - .init() + return .init() } public mutating func addLink(_ link: SpanLink) {} @@ -68,7 +68,7 @@ public struct NoOpTracingInstrument: TracingInstrument { public var attributes: SpanAttributes { get { - [:] + return [:] } set { // ignore diff --git a/Sources/TracingInstrumentation/Span.swift b/Sources/TracingInstrumentation/Span.swift index ae2888f..86b392d 100644 --- a/Sources/TracingInstrumentation/Span.swift +++ b/Sources/TracingInstrumentation/Span.swift @@ -132,6 +132,7 @@ public struct SpanAttributeKey: Hashable, ExpressibleByStringLiteral where T: } } +#if compiler(>=5.2) @dynamicMemberLookup public protocol SpanAttributeNamespace { /// Type that contains the nested attributes, e.g. HTTPAttributes which would contain `statusCode` and similar vars. @@ -176,6 +177,7 @@ extension SpanAttributeNamespace { SpanAttribute.__namespace[keyPath: dynamicMember] } } +#endif /// The value of an attribute used to describe a `Span` or `SpanEvent`. public enum SpanAttribute: Equatable { @@ -190,9 +192,11 @@ public enum SpanAttribute: Equatable { case array([SpanAttribute]) case stringConvertible(CustomStringConvertible) + #if compiler(>=5.2) /// This is a "magic value" that is used to enable the KeyPath based accessors to specific attributes. /// This value will never be stored or returned, and any attempt of doing so would WILL crash your application. case __namespace + #endif internal var anyValue: Any { switch self { @@ -208,8 +212,10 @@ public enum SpanAttribute: Equatable { return value case .stringConvertible(let value): return value + #if compiler(>=5.2) case .__namespace: fatalError("__namespace MUST NOT be stored not can be extracted from using anyValue") + #endif } } @@ -226,9 +232,12 @@ public enum SpanAttribute: Equatable { (.double, _), (.bool, _), (.array, _), - (.stringConvertible, _), - (.__namespace, _): + (.stringConvertible, _): return false + #if compiler(>=5.2) + case (.__namespace, _): + return false + #endif } } } @@ -239,31 +248,31 @@ public protocol SpanAttributeConvertible { extension String: SpanAttributeConvertible { public func toSpanAttribute() -> SpanAttribute { - .string(self) + return .string(self) } } extension Int: SpanAttributeConvertible { public func toSpanAttribute() -> SpanAttribute { - .int(self) + return .int(self) } } extension Double: SpanAttributeConvertible { public func toSpanAttribute() -> SpanAttribute { - .double(self) + return .double(self) } } extension Bool: SpanAttributeConvertible { public func toSpanAttribute() -> SpanAttribute { - .bool(self) + return .bool(self) } } extension Array: SpanAttributeConvertible where Element: SpanAttributeConvertible { public func toSpanAttribute() -> SpanAttribute { - .array(self.map { $0.toSpanAttribute() }) + return .array(self.map { $0.toSpanAttribute() }) } } @@ -274,7 +283,7 @@ extension SpanAttribute: ExpressibleByStringLiteral { } extension SpanAttribute: ExpressibleByStringInterpolation { - public init(stringInterpolation value: Self.StringInterpolation) { + public init(stringInterpolation value: SpanAttribute.StringInterpolation) { self = .string("\(value)") } } @@ -303,6 +312,7 @@ extension SpanAttribute: ExpressibleByArrayLiteral { } } +#if compiler(>=5.2) /// A collection of `SpanAttribute`s. @dynamicMemberLookup public struct SpanAttributes: Equatable { @@ -353,7 +363,33 @@ public struct SpanAttributes: Equatable { where Namespace: SpanAttributeNamespace { SpanAttribute.__namespace[keyPath: dynamicMember] } +} +#else +public struct SpanAttributes: Equatable { + private var _attributes = [String: SpanAttribute]() + + /// Create a set of attributes by wrapping the given dictionary. + /// - Parameter attributes: The attributes dictionary to wrap. + public init(_ attributes: [String: SpanAttribute]) { + self._attributes = attributes + } + + /// Accesses the `SpanAttribute` with the given name for reading and writing. + /// + /// - Parameter name: The name of the attribute used to identify the attribute. + /// - Returns: The `SpanAttribute` identified by the given name, or `nil` if it's not present. + public subscript(_ name: String) -> SpanAttribute? { + get { + return self._attributes[name] + } + set { + self._attributes[name] = newValue + } + } +} +#endif +extension SpanAttributes { /// Calls the given callback for each attribute stored in this collection. /// - Parameter callback: The function to call for each attribute. public func forEach(_ callback: (String, SpanAttribute) -> Void) { @@ -362,7 +398,7 @@ public struct SpanAttributes: Equatable { /// Returns true if the collection contains no attributes. public var isEmpty: Bool { - self._attributes.isEmpty + return self._attributes.isEmpty } } diff --git a/Sources/TracingInstrumentation/Timestamp.swift b/Sources/TracingInstrumentation/Timestamp.swift index cfc8b39..287f18f 100644 --- a/Sources/TracingInstrumentation/Timestamp.swift +++ b/Sources/TracingInstrumentation/Timestamp.swift @@ -25,17 +25,17 @@ public struct Timestamp: Comparable, CustomStringConvertible { /// Microseconds since Epoch public var microsSinceEpoch: Int64 { - Int64(bitPattern: self.time.rawValue) / -1000 + return Int64(bitPattern: self.time.rawValue) / -1000 } /// Milliseconds since Epoch public var millisSinceEpoch: Int64 { - Int64(bitPattern: self.time.rawValue) / -1_000_000 + return Int64(bitPattern: self.time.rawValue) / -1_000_000 } /// Returns the current time. public static func now() -> Timestamp { - self.init(time: .now()) + return self.init(time: .now()) } /// A time in the distant future. @@ -53,14 +53,14 @@ public struct Timestamp: Comparable, CustomStringConvertible { } public var description: String { - "Timestamp(\(self.time.rawValue))" + return "Timestamp(\(self.time.rawValue))" } public static func < (lhs: Timestamp, rhs: Timestamp) -> Bool { - lhs.time < rhs.time + return lhs.time < rhs.time } public static func == (lhs: Timestamp, rhs: Timestamp) -> Bool { - lhs.time == rhs.time + return lhs.time == rhs.time } } diff --git a/Sources/TracingInstrumentation/TracingInstrument.swift b/Sources/TracingInstrumentation/TracingInstrument.swift index 0f6b188..1e5ca3d 100644 --- a/Sources/TracingInstrumentation/TracingInstrument.swift +++ b/Sources/TracingInstrumentation/TracingInstrument.swift @@ -53,6 +53,6 @@ extension TracingInstrument { ofKind kind: SpanKind = .internal, at timestamp: Timestamp = .now() ) -> Span { - self.startSpan(named: operationName, context: context, ofKind: kind, at: timestamp) + return self.startSpan(named: operationName, context: context, ofKind: kind, at: timestamp) } } diff --git a/Tests/InstrumentationTests/InstrumentTests+XCTest.swift b/Tests/InstrumentationTests/InstrumentTests+XCTest.swift new file mode 100644 index 0000000..889bd8c --- /dev/null +++ b/Tests/InstrumentationTests/InstrumentTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// InstrumentTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension InstrumentTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (InstrumentTests) -> () throws -> Void)] { + return [ + ("testMultiplexInvokesAllInstruments", testMultiplexInvokesAllInstruments), + ] + } +} + diff --git a/Tests/InstrumentationTests/InstrumentTests.swift b/Tests/InstrumentationTests/InstrumentTests.swift index 6ae9201..6a897c7 100644 --- a/Tests/InstrumentationTests/InstrumentTests.swift +++ b/Tests/InstrumentationTests/InstrumentTests.swift @@ -47,7 +47,7 @@ private struct DictionaryInjector: InjectorProtocol { private struct DictionaryExtractor: ExtractorProtocol { func extract(key: String, from dictionary: [String: String]) -> String? { - dictionary[key] + return dictionary[key] } } @@ -68,7 +68,7 @@ private final class FirstFakeTracer: Instrument { Injector: InjectorProtocol, Carrier == Injector.Carrier { guard let traceID = context[TraceIDKey.self] else { return } - injector.inject(traceID, forKey: Self.headerName, into: &carrier) + injector.inject(traceID, forKey: FirstFakeTracer.headerName, into: &carrier) } func extract( @@ -77,7 +77,7 @@ private final class FirstFakeTracer: Instrument { where Extractor: ExtractorProtocol, Carrier == Extractor.Carrier { - let traceID = extractor.extract(key: Self.headerName, from: carrier) ?? Self.defaultTraceID + let traceID = extractor.extract(key: FirstFakeTracer.headerName, from: carrier) ?? FirstFakeTracer.defaultTraceID context[TraceIDKey.self] = traceID } } @@ -99,7 +99,7 @@ private final class SecondFakeTracer: Instrument { Injector: InjectorProtocol, Carrier == Injector.Carrier { guard let traceID = context[TraceIDKey.self] else { return } - injector.inject(traceID, forKey: Self.headerName, into: &carrier) + injector.inject(traceID, forKey: SecondFakeTracer.headerName, into: &carrier) } func extract( @@ -108,7 +108,7 @@ private final class SecondFakeTracer: Instrument { where Extractor: ExtractorProtocol, Carrier == Extractor.Carrier { - let traceID = extractor.extract(key: Self.headerName, from: carrier) ?? Self.defaultTraceID + let traceID = extractor.extract(key: SecondFakeTracer.headerName, from: carrier) ?? SecondFakeTracer.defaultTraceID context[TraceIDKey.self] = traceID } } diff --git a/Tests/InstrumentationTests/InstrumentationSystemTests+XCTest.swift b/Tests/InstrumentationTests/InstrumentationSystemTests+XCTest.swift new file mode 100644 index 0000000..c28e7b2 --- /dev/null +++ b/Tests/InstrumentationTests/InstrumentationSystemTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// InstrumentationSystemTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension InstrumentationSystemTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (InstrumentationSystemTests) -> () throws -> Void)] { + return [ + ("testItProvidesAccessToASingletonInstrument", testItProvidesAccessToASingletonInstrument), + ] + } +} + diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 0000000..8db2330 --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// LinuxMain.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +#if os(Linux) || os(FreeBSD) + @testable import InstrumentationTests + @testable import NIOInstrumentationTests + @testable import OpenTelemetryInstrumentationSupportTests + @testable import TracingInstrumentationTests + +// This protocol is necessary to we can call the 'run' method (on an existential of this protocol) +// without the compiler noticing that we're calling a deprecated function. +// This hack exists so we can deprecate individual tests which test deprecated functionality without +// getting a compiler warning... +protocol LinuxMainRunner { func run() } +class LinuxMainRunnerImpl: LinuxMainRunner { + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + func run() { + XCTMain([ + testCase(BaggageContextInboundHTTPHandlerTests.allTests), + testCase(BaggageContextOutboundHTTPHandlerTests.allTests), + testCase(InstrumentTests.allTests), + testCase(InstrumentationSystemTests.allTests), + testCase(SpanAttributeSemanticsTests.allTests), + testCase(SpanTests.allTests), + testCase(TimestampTests.allTests), + testCase(TracedLockTests.allTests), + testCase(TracingInstrumentTests.allTests), + ]) + } +} +(LinuxMainRunnerImpl() as LinuxMainRunner).run() +#endif diff --git a/Tests/NIOInstrumentationTests/BaggageContextInboundHTTPHandlerTests+XCTest.swift b/Tests/NIOInstrumentationTests/BaggageContextInboundHTTPHandlerTests+XCTest.swift new file mode 100644 index 0000000..6d70848 --- /dev/null +++ b/Tests/NIOInstrumentationTests/BaggageContextInboundHTTPHandlerTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// BaggageContextInboundHTTPHandlerTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension BaggageContextInboundHTTPHandlerTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (BaggageContextInboundHTTPHandlerTests) -> () throws -> Void)] { + return [ + ("testForwardsHTTPHeadersToInstrumentationMiddleware", testForwardsHTTPHeadersToInstrumentationMiddleware), + ] + } +} + diff --git a/Tests/NIOInstrumentationTests/BaggageContextOutboundHTTPHandlerTests+XCTest.swift b/Tests/NIOInstrumentationTests/BaggageContextOutboundHTTPHandlerTests+XCTest.swift new file mode 100644 index 0000000..79f1c64 --- /dev/null +++ b/Tests/NIOInstrumentationTests/BaggageContextOutboundHTTPHandlerTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// BaggageContextOutboundHTTPHandlerTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension BaggageContextOutboundHTTPHandlerTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (BaggageContextOutboundHTTPHandlerTests) -> () throws -> Void)] { + return [ + ("testUsesInstrumentationMiddlewareToInjectHTTPHeadersFromContext", testUsesInstrumentationMiddlewareToInjectHTTPHeadersFromContext), + ] + } +} + diff --git a/Tests/NIOInstrumentationTests/FakeTracer.swift b/Tests/NIOInstrumentationTests/FakeTracer.swift index 1157ace..643888c 100644 --- a/Tests/NIOInstrumentationTests/FakeTracer.swift +++ b/Tests/NIOInstrumentationTests/FakeTracer.swift @@ -31,7 +31,7 @@ final class FakeTracer: Instrument { Injector: InjectorProtocol, Carrier == Injector.Carrier { guard let traceID = context[TraceIDKey.self] else { return } - injector.inject(traceID, forKey: Self.headerName, into: &carrier) + injector.inject(traceID, forKey: FakeTracer.headerName, into: &carrier) } func extract( @@ -40,7 +40,7 @@ final class FakeTracer: Instrument { where Extractor: ExtractorProtocol, Carrier == Extractor.Carrier { - let traceID = extractor.extract(key: Self.headerName, from: carrier) ?? Self.defaultTraceID + let traceID = extractor.extract(key: FakeTracer.headerName, from: carrier) ?? FakeTracer.defaultTraceID context[TraceIDKey.self] = traceID } } diff --git a/Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests+XCTest.swift b/Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests+XCTest.swift new file mode 100644 index 0000000..66d893f --- /dev/null +++ b/Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// SpanAttributeSemanticsTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension SpanAttributeSemanticsTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (SpanAttributeSemanticsTests) -> () throws -> Void)] { + return [ + ("testDynamicMemberLookup", testDynamicMemberLookup), + ] + } +} + diff --git a/Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests.swift b/Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests.swift index ebaba8f..3f860e2 100644 --- a/Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests.swift +++ b/Tests/OpenTelemetryInstrumentationSupportTests/SpanAttributeSemanticsTests.swift @@ -19,6 +19,7 @@ import XCTest final class SpanAttributeSemanticsTests: XCTestCase { func testDynamicMemberLookup() { + #if compiler(>=5.2) var attributes: SpanAttributes = [:] attributes.http.method = "GET" @@ -32,5 +33,6 @@ final class SpanAttributeSemanticsTests: XCTestCase { attributes.endUser.id = "steve" XCTAssertEqual(attributes.endUser.id, "steve") + #endif } } diff --git a/Tests/TracingInstrumentationTests/SpanTests+XCTest.swift b/Tests/TracingInstrumentationTests/SpanTests+XCTest.swift new file mode 100644 index 0000000..51e8557 --- /dev/null +++ b/Tests/TracingInstrumentationTests/SpanTests+XCTest.swift @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// SpanTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension SpanTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (SpanTests) -> () throws -> Void)] { + return [ + ("testAddingEventCreatesCopy", testAddingEventCreatesCopy), + ("testSpanEventIsExpressibleByStringLiteral", testSpanEventIsExpressibleByStringLiteral), + ("testSpanAttributeIsExpressibleByStringLiteral", testSpanAttributeIsExpressibleByStringLiteral), + ("testSpanAttributeIsExpressibleByStringInterpolation", testSpanAttributeIsExpressibleByStringInterpolation), + ("testSpanAttributeIsExpressibleByIntegerLiteral", testSpanAttributeIsExpressibleByIntegerLiteral), + ("testSpanAttributeIsExpressibleByFloatLiteral", testSpanAttributeIsExpressibleByFloatLiteral), + ("testSpanAttributeIsExpressibleByBooleanLiteral", testSpanAttributeIsExpressibleByBooleanLiteral), + ("testSpanAttributeIsExpressibleByArrayLiteral", testSpanAttributeIsExpressibleByArrayLiteral), + ("testSpanAttributesUX", testSpanAttributesUX), + ("testSpanAttributesCustomValue", testSpanAttributesCustomValue), + ("testSpanAttributesAreIterable", testSpanAttributesAreIterable), + ("testSpanParentConvenience", testSpanParentConvenience), + ] + } +} + diff --git a/Tests/TracingInstrumentationTests/SpanTests.swift b/Tests/TracingInstrumentationTests/SpanTests.swift index d09f601..1dc53b6 100644 --- a/Tests/TracingInstrumentationTests/SpanTests.swift +++ b/Tests/TracingInstrumentationTests/SpanTests.swift @@ -105,6 +105,7 @@ final class SpanTests: XCTestCase { } func testSpanAttributesUX() { + #if compiler(>=5.2) var attributes: SpanAttributes = [:] // normally we can use just the span attribute values, and it is not type safe or guided in any way: @@ -128,9 +129,11 @@ final class SpanTests: XCTestCase { XCTAssertEqual(attributes.name, SpanAttribute.string("kappa")) XCTAssertEqual(attributes.name, "kappa") XCTAssertEqual(attributes.sampleHttp.statusCode, 200) + #endif } func testSpanAttributesCustomValue() { + #if compiler(>=5.2) var attributes: SpanAttributes = [:] // normally we can use just the span attribute values, and it is not type safe or guided in any way: @@ -139,6 +142,7 @@ final class SpanTests: XCTestCase { XCTAssertEqual(attributes["http.custom_value"], SpanAttribute.stringConvertible(CustomAttributeValue())) XCTAssertEqual(String(reflecting: attributes.sampleHttp.customType), "Optional(CustomAttributeValue())") XCTAssertEqual(attributes.sampleHttp.customType, CustomAttributeValue()) + #endif } func testSpanAttributesAreIterable() { @@ -149,7 +153,7 @@ final class SpanTests: XCTestCase { dictionary[name] = attribute } - guard case .int = dictionary["0"], case .bool = dictionary["1"], case .string = dictionary["2"] else { + guard case .some(.int) = dictionary["0"], case .some(.bool) = dictionary["1"], case .some(.string) = dictionary["2"] else { XCTFail("Expected all attributes to be copied to the dictionary.") return } @@ -175,13 +179,19 @@ final class SpanTests: XCTestCase { onEnd: { _ in } ) + #if compiler(>=5.2) var attributes = SpanAttributes() attributes.sampleHttp.statusCode = 418 + #else + let attributes = SpanAttributes() + #endif child.addLink(parent, attributes: attributes) XCTAssertEqual(child.links.count, 1) XCTAssertEqual(child.links[0].context[TestBaggageContextKey.self], "test") + #if compiler(>=5.2) XCTAssertEqual(child.links[0].attributes.sampleHttp.statusCode, 418) + #endif } } @@ -190,10 +200,11 @@ final class SpanTests: XCTestCase { extension SpanAttribute { var name: SpanAttributeKey { - "name" + return "name" } } +#if compiler(>=5.2) extension SpanAttributes { public var sampleHttp: HTTPAttributes { get { @@ -238,6 +249,7 @@ public struct CustomAttributeValue: Equatable, CustomStringConvertible, SpanAttr "CustomAttributeValue()" } } +#endif private struct TestBaggageContextKey: BaggageContextKey { typealias Value = String diff --git a/Tests/TracingInstrumentationTests/TimestampTests+XCTest.swift b/Tests/TracingInstrumentationTests/TimestampTests+XCTest.swift new file mode 100644 index 0000000..4fcdf99 --- /dev/null +++ b/Tests/TracingInstrumentationTests/TimestampTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// TimestampTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension TimestampTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (TimestampTests) -> () throws -> Void)] { + return [ + ("test_timestamp_now", test_timestamp_now), + ] + } +} + diff --git a/Tests/TracingInstrumentationTests/TracedLockTests+XCTest.swift b/Tests/TracingInstrumentationTests/TracedLockTests+XCTest.swift new file mode 100644 index 0000000..dcc1406 --- /dev/null +++ b/Tests/TracingInstrumentationTests/TracedLockTests+XCTest.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// TracedLockTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension TracedLockTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (TracedLockTests) -> () throws -> Void)] { + return [ + ("test_tracesLockedTime", test_tracesLockedTime), + ] + } +} + diff --git a/Tests/TracingInstrumentationTests/TracedLockTests.swift b/Tests/TracingInstrumentationTests/TracedLockTests.swift index 24f7b91..c56c2ac 100644 --- a/Tests/TracingInstrumentationTests/TracedLockTests.swift +++ b/Tests/TracingInstrumentationTests/TracedLockTests.swift @@ -60,7 +60,7 @@ private final class TracedLockPrintlnTracer: TracingInstrument { ofKind kind: SpanKind, at timestamp: Timestamp ) -> Span { - TracedLockPrintlnSpan( + return TracedLockPrintlnSpan( operationName: operationName, startTimestamp: timestamp, kind: kind, diff --git a/Tests/TracingInstrumentationTests/TracingInstrumentTests+XCTest.swift b/Tests/TracingInstrumentationTests/TracingInstrumentTests+XCTest.swift new file mode 100644 index 0000000..2dcefd3 --- /dev/null +++ b/Tests/TracingInstrumentationTests/TracingInstrumentTests+XCTest.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// TracingInstrumentTests+XCTest.swift +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + +extension TracingInstrumentTests { + + @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings") + static var allTests : [(String, (TracingInstrumentTests) -> () throws -> Void)] { + return [ + ("testPlayground", testPlayground), + ("testItProvidesAccessToATracingInstrument", testItProvidesAccessToATracingInstrument), + ] + } +} + diff --git a/Tests/TracingInstrumentationTests/TracingInstrumentTests.swift b/Tests/TracingInstrumentationTests/TracingInstrumentTests.swift index 45432b1..9caf0e4 100644 --- a/Tests/TracingInstrumentationTests/TracingInstrumentTests.swift +++ b/Tests/TracingInstrumentationTests/TracingInstrumentTests.swift @@ -176,7 +176,7 @@ typealias HTTPHeaders = [(String, String)] struct HTTPHeadersExtractor: ExtractorProtocol { func extract(key: String, from headers: HTTPHeaders) -> String? { - headers.first(where: { $0.0 == key })?.1 + return headers.first(where: { $0.0 == key })?.1 } } diff --git a/UseCases/Package.resolved b/UseCases/Package.resolved index 439af58..d5cbc8b 100644 --- a/UseCases/Package.resolved +++ b/UseCases/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/slashmo/gsoc-swift-baggage-context.git", "state": { "branch": null, - "revision": "71ef1080972a1cac47ab80d995d6bdc370fb20f2", - "version": "0.2.0" + "revision": "744d984ac940535287cb036e44e6970c2a93f012", + "version": "0.3.0" } }, { diff --git a/UseCases/Package.swift b/UseCases/Package.swift index 2d9f169..378113f 100644 --- a/UseCases/Package.swift +++ b/UseCases/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.2 +// swift-tools-version:5.0 import PackageDescription let package = Package( @@ -10,38 +10,37 @@ let package = Package( .executable(name: "InstrumentsAppTracing", targets: ["InstrumentsAppTracing"]), ], dependencies: [ - .package(name: "gsoc-swift-tracing", path: "../"), + .package(path: "../"), .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.1.1"), .package(url: "https://github.com/apple/swift-nio.git", from: "2.9.0"), .package( - name: "swift-baggage-context", url: "https://github.com/slashmo/gsoc-swift-baggage-context.git", - from: "0.2.0" + from: "0.3.0" ), ], targets: [ .target(name: "ManualContextPropagation", dependencies: [ - .product(name: "Instrumentation", package: "gsoc-swift-tracing"), - .product(name: "Baggage", package: "swift-baggage-context"), + "Instrumentation", + "Baggage", ]), .target(name: "ManualAsyncHTTPClient", dependencies: [ - .product(name: "Instrumentation", package: "gsoc-swift-tracing"), - .product(name: "NIOInstrumentation", package: "gsoc-swift-tracing"), - .product(name: "AsyncHTTPClient", package: "async-http-client"), - .product(name: "NIO", package: "swift-nio"), - .product(name: "Baggage", package: "swift-baggage-context"), + "Instrumentation", + "NIOInstrumentation", + "AsyncHTTPClient", + "NIO", + "Baggage", ]), .target(name: "HTTPEndToEnd", dependencies: [ - .product(name: "TracingInstrumentation", package: "gsoc-swift-tracing"), - .product(name: "NIOInstrumentation", package: "gsoc-swift-tracing"), - .product(name: "AsyncHTTPClient", package: "async-http-client"), - .product(name: "NIO", package: "swift-nio"), - .product(name: "Baggage", package: "swift-baggage-context"), - .product(name: "BaggageLogging", package: "swift-baggage-context"), + "TracingInstrumentation", + "NIOInstrumentation", + "AsyncHTTPClient", + "NIO", + "Baggage", + "BaggageLogging", ]), .target(name: "InstrumentsAppTracing", dependencies: [ - .product(name: "Instrumentation", package: "gsoc-swift-tracing"), - .product(name: "TracingInstrumentation", package: "gsoc-swift-tracing"), + "Instrumentation", + "TracingInstrumentation", ]), ] ) diff --git a/UseCases/Sources/ManualContextPropagation/main.swift b/UseCases/Sources/ManualContextPropagation/main.swift index bea90a4..0d659bb 100644 --- a/UseCases/Sources/ManualContextPropagation/main.swift +++ b/UseCases/Sources/ManualContextPropagation/main.swift @@ -15,25 +15,13 @@ import Baggage import Foundation import Instrumentation -// MARK: - Demo - -let server = FakeHTTPServer(instrument: FakeTracer()) { context, _, client in - print("=== Perform subsequent request ===") - let outgoingRequest = FakeHTTPRequest(path: "/other-service", headers: [("Content-Type", "application/json")]) - client.performRequest(context, request: outgoingRequest) - return FakeHTTPResponse() -} - -print("=== Receive HTTP request on server ===") -server.receive(FakeHTTPRequest(path: "/", headers: [])) - // MARK: - Fake HTTP Server typealias HTTPHeaders = [(String, String)] struct HTTPHeadersExtractor: ExtractorProtocol { func extract(key: String, from headers: HTTPHeaders) -> String? { - headers.first(where: { $0.0 == key })?.1 + return headers.first(where: { $0.0 == key })?.1 } } @@ -65,7 +53,7 @@ struct FakeHTTPServer { func receive(_ request: FakeHTTPRequest) { var context = BaggageContext() - print("\(String(describing: Self.self)): Extracting context values from request headers into context") + print("\(String(describing: FakeHTTPRequest.self)): Extracting context values from request headers into context") self.instrument.extract(request.headers, into: &context, using: HTTPHeadersExtractor()) _ = self.catchAllHandler(context, request, self.client) } @@ -82,7 +70,7 @@ struct FakeHTTPClient { func performRequest(_ context: BaggageContext, request: FakeHTTPRequest) { var request = request - print("\(String(describing: Self.self)): Injecting context values into request headers") + print("\(String(describing: FakeHTTPClient.self)): Injecting context values into request headers") self.instrument.inject(context, into: &request.headers, using: HTTPHeadersInjector()) print(request) } @@ -103,14 +91,26 @@ private final class FakeTracer: Instrument { Injector: InjectorProtocol, Carrier == Injector.Carrier { guard let traceID = context[TraceIDKey.self] else { return } - injector.inject(traceID, forKey: Self.headerName, into: &carrier) + injector.inject(traceID, forKey: FakeTracer.headerName, into: &carrier) } func extract(_ carrier: Carrier, into context: inout BaggageContext, using extractor: Extractor) where Extractor: ExtractorProtocol, Carrier == Extractor.Carrier { - let traceID = extractor.extract(key: Self.headerName, from: carrier) ?? Self.defaultTraceID + let traceID = extractor.extract(key: FakeTracer.headerName, from: carrier) ?? FakeTracer.defaultTraceID context[TraceIDKey.self] = traceID } } + +// MARK: - Demo + +let server = FakeHTTPServer(instrument: FakeTracer()) { context, _, client in + print("=== Perform subsequent request ===") + let outgoingRequest = FakeHTTPRequest(path: "/other-service", headers: [("Content-Type", "application/json")]) + client.performRequest(context, request: outgoingRequest) + return FakeHTTPResponse() +} + +print("=== Receive HTTP request on server ===") +server.receive(FakeHTTPRequest(path: "/", headers: [])) diff --git a/scripts/generate_linux_tests.rb b/scripts/generate_linux_tests.rb new file mode 100755 index 0000000..efb524b --- /dev/null +++ b/scripts/generate_linux_tests.rb @@ -0,0 +1,241 @@ +#!/usr/bin/env ruby + +# +# process_test_files.rb +# +# Copyright 2016 Tony Stone +# +# 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. +# +# Created by Tony Stone on 5/4/16. +# +require 'getoptlong' +require 'fileutils' +require 'pathname' + +include FileUtils + +# +# This ruby script will auto generate LinuxMain.swift and the +XCTest.swift extension files for Swift Package Manager on Linux platforms. +# +# See https://github.com/apple/swift-corelibs-xctest/blob/master/Documentation/Linux.md +# +def header(fileName) + string = <<-eos +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Tracing open source project +// +// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// +// +// +import XCTest +/// +/// NOTE: This file was generated by generate_linux_tests.rb +/// +/// Do NOT edit this file directly as it will be regenerated automatically when needed. +/// + eos + + string + .sub('', File.basename(fileName)) + .sub('', Time.now.to_s) +end + +def createExtensionFile(fileName, classes) + extensionFile = fileName.sub! '.swift', '+XCTest.swift' + print 'Creating file: ' + extensionFile + "\n" + + File.open(extensionFile, 'w') do |file| + file.write header(extensionFile) + file.write "\n" + + for classArray in classes + file.write 'extension ' + classArray[0] + " {\n\n" + file.write ' @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings")' +"\n" + file.write ' static var allTests : [(String, (' + classArray[0] + ") -> () throws -> Void)] {\n" + file.write " return [\n" + + for funcName in classArray[1] + file.write ' ("' + funcName + '", ' + funcName + "),\n" + end + + file.write " ]\n" + file.write " }\n" + file.write "}\n\n" + end + end +end + +def createLinuxMain(testsDirectory, allTestSubDirectories, files) + fileName = testsDirectory + '/LinuxMain.swift' + print 'Creating file: ' + fileName + "\n" + + File.open(fileName, 'w') do |file| + file.write header(fileName) + file.write "\n" + + file.write "#if os(Linux) || os(FreeBSD)\n" + for testSubDirectory in allTestSubDirectories.sort { |x, y| x <=> y } + file.write ' @testable import ' + testSubDirectory + "\n" + end + file.write "\n" + file.write "// This protocol is necessary to we can call the 'run' method (on an existential of this protocol)\n" + file.write "// without the compiler noticing that we're calling a deprecated function.\n" + file.write "// This hack exists so we can deprecate individual tests which test deprecated functionality without\n" + file.write "// getting a compiler warning...\n" + file.write "protocol LinuxMainRunner { func run() }\n" + file.write "class LinuxMainRunnerImpl: LinuxMainRunner {\n" + file.write ' @available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings")' + "\n" + file.write " func run() {\n" + file.write " XCTMain([\n" + + testCases = [] + for classes in files + for classArray in classes + testCases << classArray[0] + end + end + + for testCase in testCases.sort { |x, y| x <=> y } + file.write ' testCase(' + testCase + ".allTests),\n" + end + file.write " ])\n" + file.write " }\n" + file.write "}\n" + file.write "(LinuxMainRunnerImpl() as LinuxMainRunner).run()\n" + file.write "#endif\n" + end +end + +def parseSourceFile(fileName) + puts 'Parsing file: ' + fileName + "\n" + + classes = [] + currentClass = nil + inIfLinux = false + inElse = false + ignore = false + + # + # Read the file line by line + # and parse to find the class + # names and func names + # + File.readlines(fileName).each do |line| + if inIfLinux + if /\#else/.match(line) + inElse = true + ignore = true + else + if /\#end/.match(line) + inElse = false + inIfLinux = false + ignore = false + end + end + else + if /\#if[ \t]+os\(Linux\)/.match(line) + inIfLinux = true + ignore = false + end + end + + next if ignore + # Match class or func + match = line[/class[ \t]+[a-zA-Z0-9_]*(?=[ \t]*:[ \t]*XCTestCase)|func[ \t]+test[a-zA-Z0-9_]*(?=[ \t]*\(\))/, 0] + if match + + if match[/class/, 0] == 'class' + className = match.sub(/^class[ \t]+/, '') + # + # Create a new class / func structure + # and add it to the classes array. + # + currentClass = [className, []] + classes << currentClass + else # Must be a func + funcName = match.sub(/^func[ \t]+/, '') + # + # Add each func name the the class / func + # structure created above. + # + currentClass[1] << funcName + end + end + end + classes +end + +# +# Main routine +# +# + +testsDirectory = 'Tests' + +options = GetoptLong.new(['--tests-dir', GetoptLong::OPTIONAL_ARGUMENT]) +options.quiet = true + +begin + options.each do |option, value| + case option + when '--tests-dir' + testsDirectory = value + end + end +rescue GetoptLong::InvalidOption +end + +allTestSubDirectories = [] +allFiles = [] + +Dir[testsDirectory + '/*'].each do |subDirectory| + next unless File.directory?(subDirectory) + directoryHasClasses = false + Dir[subDirectory + '/*Test{s,}.swift'].each do |fileName| + next unless File.file? fileName + fileClasses = parseSourceFile(fileName) + + # + # If there are classes in the + # test source file, create an extension + # file for it. + # + next unless fileClasses.count > 0 + createExtensionFile(fileName, fileClasses) + directoryHasClasses = true + allFiles << fileClasses + end + + if directoryHasClasses + allTestSubDirectories << Pathname.new(subDirectory).split.last.to_s + end +end + +# +# Last step is the create a LinuxMain.swift file that +# references all the classes and funcs in the source files. +# +if allFiles.count > 0 + createLinuxMain(testsDirectory, allTestSubDirectories, allFiles) +end +# eof diff --git a/scripts/sanity.sh b/scripts/sanity.sh index 4feaed0..4a2bdef 100755 --- a/scripts/sanity.sh +++ b/scripts/sanity.sh @@ -15,6 +15,18 @@ set -eu here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +printf "=> Checking linux tests... " +FIRST_OUT="$(git status --porcelain)" +ruby "$here/../scripts/generate_linux_tests.rb" > /dev/null +SECOND_OUT="$(git status --porcelain)" +if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then + printf "\033[0;31mmissing changes!\033[0m\n" + git --no-pager diff + exit 1 +else + printf "\033[0;32mokay.\033[0m\n" +fi + bash $here/validate_license_headers.sh bash $here/validate_format.sh bash $here/validate_naming.sh