浏览代码

Enable Swift 6 language mode for more modules (#1985)

Motivation:

v2 will support Swift 6 only. We should enable the Swift 6 language mode
across all v2 modules. This has mostly been done already for non-test
modules. This change enables it for test modules as well.

Modifications:

Enable Swift 6 language mode and existential any for test modules
Result:

Closer to fully supporting Swift 6 language mode
George Barnett 1 年之前
父节点
当前提交
aa5f4a8967
共有 25 个文件被更改,包括 191 次插入189 次删除
  1. 7 7
      Package@swift-6.swift
  2. 3 0
      Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift
  3. 6 9
      Sources/GRPCCore/Metadata.swift
  4. 5 2
      Sources/GRPCCore/Streaming/RPCAsyncSequence.swift
  5. 1 1
      Sources/GRPCCore/Streaming/RPCWriter.swift
  6. 7 4
      Sources/GRPCHTTP2Core/Internal/Timer.swift
  7. 1 1
      Sources/InteroperabilityTests/InteroperabilityTestCase.swift
  8. 85 85
      Tests/GRPCCodeGenTests/Internal/Renderer/TextBasedRendererTests.swift
  9. 19 7
      Tests/GRPCCoreTests/Call/Server/Internal/ServerRPCExecutorTestSupport/ServerRPCExecutorTestHarness.swift
  10. 7 7
      Tests/GRPCCoreTests/Streaming/Internal/BufferedStreamTests.swift
  11. 2 3
      Tests/GRPCCoreTests/Test Utilities/Coding+JSON.swift
  12. 1 1
      Tests/GRPCCoreTests/Test Utilities/RPCWriter+Utilities.swift
  13. 2 2
      Tests/GRPCCoreTests/Test Utilities/Transport/AnyTransport.swift
  14. 1 1
      Tests/GRPCCoreTests/Test Utilities/Transport/StreamCountingTransport.swift
  15. 1 1
      Tests/GRPCCoreTests/Test Utilities/XCTest+Utilities.swift
  16. 1 13
      Tests/GRPCHTTP2CoreTests/Client/Connection/Connection+Equatable.swift
  17. 2 2
      Tests/GRPCHTTP2CoreTests/Client/Connection/ConnectionTests.swift
  18. 1 1
      Tests/GRPCHTTP2CoreTests/Client/Connection/LoadBalancers/LoadBalancerTest.swift
  19. 13 11
      Tests/GRPCHTTP2CoreTests/Client/Connection/Utilities/ConnectionTest.swift
  20. 4 4
      Tests/GRPCHTTP2CoreTests/Client/Connection/Utilities/NameResolvers.swift
  21. 3 3
      Tests/GRPCHTTP2CoreTests/Client/Connection/Utilities/TestServer.swift
  22. 0 5
      Tests/GRPCHTTP2CoreTests/GRPCStreamStateMachineTests.swift
  23. 17 17
      Tests/GRPCHTTP2CoreTests/Internal/TimerTests.swift
  24. 1 1
      Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift
  25. 1 1
      Tests/GRPCHTTP2TransportTests/Test Utilities/HTTP2StatusCodeServer.swift

+ 7 - 7
Package@swift-6.swift

@@ -366,7 +366,7 @@ extension Target {
         .atomics,
         .protobuf,
       ],
-      swiftSettings: [.swiftLanguageVersion(.v5)]
+      swiftSettings: [.swiftLanguageVersion(.v6), .enableUpcomingFeature("ExistentialAny")]
     )
   }
 
@@ -377,7 +377,7 @@ extension Target {
         .grpcCore,
         .grpcInProcessTransport
       ],
-      swiftSettings: [.swiftLanguageVersion(.v5)]
+      swiftSettings: [.swiftLanguageVersion(.v6), .enableUpcomingFeature("ExistentialAny")]
     )
   }
 
@@ -390,7 +390,7 @@ extension Target {
         .nioCore,
         .grpcInterceptors
       ],
-      swiftSettings: [.swiftLanguageVersion(.v5)]
+      swiftSettings: [.swiftLanguageVersion(.v6), .enableUpcomingFeature("ExistentialAny")]
     )
   }
 
@@ -404,7 +404,7 @@ extension Target {
         .nioEmbedded,
         .nioTestUtils,
       ],
-      swiftSettings: [.swiftLanguageVersion(.v5)]
+      swiftSettings: [.swiftLanguageVersion(.v6), .enableUpcomingFeature("ExistentialAny")]
     )
   }
 
@@ -417,7 +417,7 @@ extension Target {
         .grpcHTTP2TransportNIOTransportServices,
         .grpcProtobuf
       ],
-      swiftSettings: [.swiftLanguageVersion(.v5)]
+      swiftSettings: [.swiftLanguageVersion(.v6), .enableUpcomingFeature("ExistentialAny")]
     )
   }
 
@@ -427,7 +427,7 @@ extension Target {
       dependencies: [
         .grpcCodeGen
       ],
-      swiftSettings: [.swiftLanguageVersion(.v5)]
+      swiftSettings: [.swiftLanguageVersion(.v6), .enableUpcomingFeature("ExistentialAny")]
     )
   }
 
@@ -464,7 +464,7 @@ extension Target {
         .interoperabilityTests,
         .grpcCore
       ],
-      swiftSettings: [.swiftLanguageVersion(.v5), .enableUpcomingFeature("ExistentialAny")]
+      swiftSettings: [.swiftLanguageVersion(.v6), .enableUpcomingFeature("ExistentialAny")]
     )
   }
 

+ 3 - 0
Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift

@@ -104,6 +104,9 @@ final class StringCodeWriter {
   func nextLineAppendsToLastLine() { nextWriteAppendsToLastLine = true }
 }
 
+@available(*, unavailable)
+extension TextBasedRenderer: Sendable {}
+
 /// A renderer that uses string interpolation and concatenation
 /// to convert the provided structure code into raw string form.
 struct TextBasedRenderer: RendererProtocol {

+ 6 - 9
Sources/GRPCCore/Metadata.swift

@@ -289,12 +289,11 @@ extension Metadata: RandomAccessCollection {
 }
 
 extension Metadata {
-
   /// A sequence of metadata values for a given key.
-  public struct Values: Sequence {
+  public struct Values: Sequence, Sendable {
 
     /// An iterator for all metadata ``Value``s associated with a given key.
-    public struct Iterator: IteratorProtocol {
+    public struct Iterator: IteratorProtocol, Sendable {
       private var metadataIterator: Metadata.Iterator
       private let key: String
 
@@ -339,12 +338,11 @@ extension Metadata {
 extension Metadata {
 
   /// A sequence of metadata string values for a given key.
-  public struct StringValues: Sequence {
-
+  public struct StringValues: Sequence, Sendable {
     /// An iterator for all string values associated with a given key.
     ///
     /// This iterator will only return values originally stored as strings for a given key.
-    public struct Iterator: IteratorProtocol {
+    public struct Iterator: IteratorProtocol, Sendable {
       private var values: Values.Iterator
 
       init(values: Values) {
@@ -388,15 +386,14 @@ extension Metadata {
 }
 
 extension Metadata {
-
   /// A sequence of metadata binary values for a given key.
-  public struct BinaryValues: Sequence {
+  public struct BinaryValues: Sequence, Sendable {
 
     /// An iterator for all binary data values associated with a given key.
     ///
     /// This iterator will return values originally stored as binary data for a given key, and will also try to
     /// decode values stored as strings as if they were base64-encoded strings.
-    public struct Iterator: IteratorProtocol {
+    public struct Iterator: IteratorProtocol, Sendable {
       private var values: Values.Iterator
 
       init(values: Values) {

+ 5 - 2
Sources/GRPCCore/Streaming/RPCAsyncSequence.swift

@@ -16,9 +16,12 @@
 
 /// A type-erasing `AsyncSequence`.
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
-public struct RPCAsyncSequence<Element, Failure: Error>: AsyncSequence, @unchecked Sendable {
+public struct RPCAsyncSequence<
+  Element: Sendable,
+  Failure: Error
+>: AsyncSequence, @unchecked Sendable {
   // @unchecked Sendable is required because 'any' doesn't support composition with primary
-  // associated types. (see: https://github.com/swiftlang/swift/issue/63877)
+  // associated types. (see: https://github.com/swiftlang/swift/issues/63877)
   //
   // To work around that limitation the 'init' requires that the async sequence being wrapped
   // is 'Sendable' but that constraint must be dropped internally. This is safe, the compiler just

+ 1 - 1
Sources/GRPCCore/Streaming/RPCWriter.swift

@@ -16,7 +16,7 @@
 
 /// A type-erasing ``RPCWriterProtocol``.
 @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
-public struct RPCWriter<Element>: Sendable, RPCWriterProtocol {
+public struct RPCWriter<Element: Sendable>: Sendable, RPCWriterProtocol {
   private let writer: any RPCWriterProtocol<Element>
 
   /// Creates an ``RPCWriter`` by wrapping the `other` writer.

+ 7 - 4
Sources/GRPCHTTP2Core/Internal/Timer.swift

@@ -16,7 +16,7 @@
 
 import NIOCore
 
-struct Timer {
+package struct Timer {
   /// The delay to wait before running the task.
   private let delay: TimeAmount
   /// The task to run, if scheduled.
@@ -38,14 +38,17 @@ struct Timer {
     }
   }
 
-  init(delay: TimeAmount, repeat: Bool = false) {
+  package init(delay: TimeAmount, repeat: Bool = false) {
     self.delay = delay
     self.task = nil
     self.repeat = `repeat`
   }
 
   /// Schedule a task on the given `EventLoop`.
-  mutating func schedule(on eventLoop: any EventLoop, work: @escaping @Sendable () throws -> Void) {
+  package mutating func schedule(
+    on eventLoop: any EventLoop,
+    work: @escaping @Sendable () throws -> Void
+  ) {
     self.task?.cancel()
 
     if self.repeat {
@@ -60,7 +63,7 @@ struct Timer {
   }
 
   /// Cancels the task, if one was scheduled.
-  mutating func cancel() {
+  package mutating func cancel() {
     self.task?.cancel()
     self.task = nil
   }

+ 1 - 1
Sources/InteroperabilityTests/InteroperabilityTestCase.swift

@@ -48,7 +48,7 @@ public protocol InteroperabilityTest {
 /// Note: Tests for compression have not been implemented yet as compression is
 /// not supported. Once the API which allows for compression will be implemented
 /// these tests should be added.
-public enum InteroperabilityTestCase: String, CaseIterable {
+public enum InteroperabilityTestCase: String, CaseIterable, Sendable {
   case emptyUnary = "empty_unary"
   case largeUnary = "large_unary"
   case clientCompressedUnary = "client_compressed_unary"

+ 85 - 85
Tests/GRPCCodeGenTests/Internal/Renderer/TextBasedRendererTests.swift

@@ -41,7 +41,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         Also, bar
         """#
       ),
-      renderedBy: TextBasedRenderer.renderComment,
+      renderedBy: { $0.renderComment(_:) },
       rendersAs: #"""
         // Generated by foo
         //
@@ -56,7 +56,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         Also, bar
         """#
       ),
-      renderedBy: TextBasedRenderer.renderComment,
+      renderedBy: { $0.renderComment(_:) },
       rendersAs: #"""
         /// Generated by foo
         ///
@@ -65,14 +65,14 @@ final class Test_TextBasedRenderer: XCTestCase {
     )
     try _test(
       .mark("Lorem ipsum", sectionBreak: false),
-      renderedBy: TextBasedRenderer.renderComment,
+      renderedBy: { $0.renderComment(_:) },
       rendersAs: #"""
         // MARK: Lorem ipsum
         """#
     )
     try _test(
       .mark("Lorem ipsum", sectionBreak: true),
-      renderedBy: TextBasedRenderer.renderComment,
+      renderedBy: { $0.renderComment(_:) },
       rendersAs: #"""
         // MARK: - Lorem ipsum
         """#
@@ -83,7 +83,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         Generated by foo\r\nAlso, bar
         """
       ),
-      renderedBy: TextBasedRenderer.renderComment,
+      renderedBy: { $0.renderComment(_:) },
       rendersAs: #"""
         // Generated by foo
         // Also, bar
@@ -91,14 +91,14 @@ final class Test_TextBasedRenderer: XCTestCase {
     )
     try _test(
       .preFormatted("/// Lorem ipsum\n"),
-      renderedBy: TextBasedRenderer.renderComment,
+      renderedBy: { $0.renderComment(_:) },
       rendersAs: """
         /// Lorem ipsum
         """
     )
     try _test(
       .preFormatted("/// Lorem ipsum\n\n/// Lorem ipsum\n"),
-      renderedBy: TextBasedRenderer.renderComment,
+      renderedBy: { $0.renderComment(_:) },
       rendersAs: """
         /// Lorem ipsum
 
@@ -108,10 +108,10 @@ final class Test_TextBasedRenderer: XCTestCase {
   }
 
   func testImports() throws {
-    try _test(nil, renderedBy: TextBasedRenderer.renderImports, rendersAs: "")
+    try _test(nil, renderedBy: { $0.renderImports(_:) }, rendersAs: "")
     try _test(
       [ImportDescription(moduleName: "Foo"), ImportDescription(moduleName: "Bar")],
-      renderedBy: TextBasedRenderer.renderImports,
+      renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
         import Foo
         import Bar
@@ -119,14 +119,14 @@ final class Test_TextBasedRenderer: XCTestCase {
     )
     try _test(
       [ImportDescription(moduleName: "Foo", spi: "Secret")],
-      renderedBy: TextBasedRenderer.renderImports,
+      renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
         @_spi(Secret) import Foo
         """#
     )
     try _test(
       [ImportDescription(moduleName: "Foo", preconcurrency: .onOS(["Bar", "Baz"]))],
-      renderedBy: TextBasedRenderer.renderImports,
+      renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
         #if os(Bar) || os(Baz)
         @preconcurrency import Foo
@@ -140,7 +140,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         ImportDescription(moduleName: "Foo", preconcurrency: .always),
         ImportDescription(moduleName: "Bar", spi: "Secret", preconcurrency: .always),
       ],
-      renderedBy: TextBasedRenderer.renderImports,
+      renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
         @preconcurrency import Foo
         @preconcurrency @_spi(Secret) import Bar
@@ -186,7 +186,7 @@ final class Test_TextBasedRenderer: XCTestCase {
           item: ImportDescription.Item(kind: .func, name: "PreconcurrencyBar")
         ),
       ],
-      renderedBy: TextBasedRenderer.renderImports,
+      renderedBy: { $0.renderImports(_:) },
       rendersAs: #"""
         import typealias Foo.Bar
         import struct Foo.Baz
@@ -205,28 +205,28 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testAccessModifiers() throws {
     try _test(
       .public,
-      renderedBy: TextBasedRenderer.renderedAccessModifier,
+      renderedBy: { $0.renderedAccessModifier(_:) },
       rendersAs: #"""
         public
         """#
     )
     try _test(
       .internal,
-      renderedBy: TextBasedRenderer.renderedAccessModifier,
+      renderedBy: { $0.renderedAccessModifier(_:) },
       rendersAs: #"""
         internal
         """#
     )
     try _test(
       .fileprivate,
-      renderedBy: TextBasedRenderer.renderedAccessModifier,
+      renderedBy: { $0.renderedAccessModifier(_:) },
       rendersAs: #"""
         fileprivate
         """#
     )
     try _test(
       .private,
-      renderedBy: TextBasedRenderer.renderedAccessModifier,
+      renderedBy: { $0.renderedAccessModifier(_:) },
       rendersAs: #"""
         private
         """#
@@ -236,35 +236,35 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testLiterals() throws {
     try _test(
       .string("hi"),
-      renderedBy: TextBasedRenderer.renderLiteral,
+      renderedBy: { $0.renderLiteral(_:) },
       rendersAs: #"""
         "hi"
         """#
     )
     try _test(
       .string("this string: \"foo\""),
-      renderedBy: TextBasedRenderer.renderLiteral,
+      renderedBy: { $0.renderLiteral(_:) },
       rendersAs: #"""
         #"this string: "foo""#
         """#
     )
     try _test(
       .nil,
-      renderedBy: TextBasedRenderer.renderLiteral,
+      renderedBy: { $0.renderLiteral(_:) },
       rendersAs: #"""
         nil
         """#
     )
     try _test(
       .array([]),
-      renderedBy: TextBasedRenderer.renderLiteral,
+      renderedBy: { $0.renderLiteral(_:) },
       rendersAs: #"""
         []
         """#
     )
     try _test(
       .array([.literal(.nil)]),
-      renderedBy: TextBasedRenderer.renderLiteral,
+      renderedBy: { $0.renderLiteral(_:) },
       rendersAs: #"""
         [
             nil
@@ -273,7 +273,7 @@ final class Test_TextBasedRenderer: XCTestCase {
     )
     try _test(
       .array([.literal(.nil), .literal(.nil)]),
-      renderedBy: TextBasedRenderer.renderLiteral,
+      renderedBy: { $0.renderLiteral(_:) },
       rendersAs: #"""
         [
             nil,
@@ -286,21 +286,21 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testExpression() throws {
     try _test(
       .literal(.nil),
-      renderedBy: TextBasedRenderer.renderExpression,
+      renderedBy: { $0.renderExpression(_:) },
       rendersAs: #"""
         nil
         """#
     )
     try _test(
       .identifierPattern("foo"),
-      renderedBy: TextBasedRenderer.renderExpression,
+      renderedBy: { $0.renderExpression(_:) },
       rendersAs: #"""
         foo
         """#
     )
     try _test(
       .memberAccess(.init(left: .identifierPattern("foo"), right: "bar")),
-      renderedBy: TextBasedRenderer.renderExpression,
+      renderedBy: { $0.renderExpression(_:) },
       rendersAs: #"""
         foo.bar
         """#
@@ -312,7 +312,7 @@ final class Test_TextBasedRenderer: XCTestCase {
           arguments: [.init(label: nil, expression: .identifierPattern("foo"))]
         )
       ),
-      renderedBy: TextBasedRenderer.renderExpression,
+      renderedBy: { $0.renderExpression(_:) },
       rendersAs: #"""
         callee(foo)
         """#
@@ -322,14 +322,14 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testDeclaration() throws {
     try _test(
       .variable(kind: .let, left: "foo"),
-      renderedBy: TextBasedRenderer.renderDeclaration,
+      renderedBy: { $0.renderDeclaration(_:) },
       rendersAs: #"""
         let foo
         """#
     )
     try _test(
       .extension(.init(onType: "String", declarations: [])),
-      renderedBy: TextBasedRenderer.renderDeclaration,
+      renderedBy: { $0.renderDeclaration(_:) },
       rendersAs: #"""
         extension String {
         }
@@ -337,35 +337,35 @@ final class Test_TextBasedRenderer: XCTestCase {
     )
     try _test(
       .struct(.init(name: "Foo")),
-      renderedBy: TextBasedRenderer.renderDeclaration,
+      renderedBy: { $0.renderDeclaration(_:) },
       rendersAs: #"""
         struct Foo {}
         """#
     )
     try _test(
       .protocol(.init(name: "Foo")),
-      renderedBy: TextBasedRenderer.renderDeclaration,
+      renderedBy: { $0.renderDeclaration(_:) },
       rendersAs: #"""
         protocol Foo {}
         """#
     )
     try _test(
       .enum(.init(name: "Foo")),
-      renderedBy: TextBasedRenderer.renderDeclaration,
+      renderedBy: { $0.renderDeclaration(_:) },
       rendersAs: #"""
         enum Foo {}
         """#
     )
     try _test(
       .typealias(.init(name: "foo", existingType: .member(["Foo", "Bar"]))),
-      renderedBy: TextBasedRenderer.renderDeclaration,
+      renderedBy: { $0.renderDeclaration(_:) },
       rendersAs: #"""
         typealias foo = Foo.Bar
         """#
     )
     try _test(
       .function(FunctionDescription.init(kind: .function(name: "foo"), body: [])),
-      renderedBy: TextBasedRenderer.renderDeclaration,
+      renderedBy: { $0.renderDeclaration(_:) },
       rendersAs: #"""
         func foo() {}
         """#
@@ -375,21 +375,21 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testFunctionKind() throws {
     try _test(
       .initializer,
-      renderedBy: TextBasedRenderer.renderedFunctionKind,
+      renderedBy: { $0.renderedFunctionKind(_:) },
       rendersAs: #"""
         init
         """#
     )
     try _test(
       .function(name: "funky"),
-      renderedBy: TextBasedRenderer.renderedFunctionKind,
+      renderedBy: { $0.renderedFunctionKind(_:) },
       rendersAs: #"""
         func funky
         """#
     )
     try _test(
       .function(name: "funky", isStatic: true),
-      renderedBy: TextBasedRenderer.renderedFunctionKind,
+      renderedBy: { $0.renderedFunctionKind(_:) },
       rendersAs: #"""
         static func funky
         """#
@@ -399,14 +399,14 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testFunctionKeyword() throws {
     try _test(
       .throws,
-      renderedBy: TextBasedRenderer.renderedFunctionKeyword,
+      renderedBy: { $0.renderedFunctionKeyword(_:) },
       rendersAs: #"""
         throws
         """#
     )
     try _test(
       .async,
-      renderedBy: TextBasedRenderer.renderedFunctionKeyword,
+      renderedBy: { $0.renderedFunctionKeyword(_:) },
       rendersAs: #"""
         async
         """#
@@ -416,35 +416,35 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testParameter() throws {
     try _test(
       .init(label: "l", name: "n", type: .member("T"), defaultValue: .literal(.nil)),
-      renderedBy: TextBasedRenderer.renderParameter,
+      renderedBy: { $0.renderParameter(_:) },
       rendersAs: #"""
         l n: T = nil
         """#
     )
     try _test(
       .init(label: nil, name: "n", type: .member("T"), defaultValue: .literal(.nil)),
-      renderedBy: TextBasedRenderer.renderParameter,
+      renderedBy: { $0.renderParameter(_:) },
       rendersAs: #"""
         _ n: T = nil
         """#
     )
     try _test(
       .init(label: "l", name: nil, type: .member("T"), defaultValue: .literal(.nil)),
-      renderedBy: TextBasedRenderer.renderParameter,
+      renderedBy: { $0.renderParameter(_:) },
       rendersAs: #"""
         l: T = nil
         """#
     )
     try _test(
       .init(label: nil, name: nil, type: .member("T"), defaultValue: .literal(.nil)),
-      renderedBy: TextBasedRenderer.renderParameter,
+      renderedBy: { $0.renderParameter(_:) },
       rendersAs: #"""
         _: T = nil
         """#
     )
     try _test(
       .init(label: nil, name: nil, type: .member("T"), defaultValue: nil),
-      renderedBy: TextBasedRenderer.renderParameter,
+      renderedBy: { $0.renderParameter(_:) },
       rendersAs: #"""
         _: T
         """#
@@ -461,7 +461,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         whereClause: WhereClause(requirements: [.conformance("R", "Sendable")]),
         body: []
       ),
-      renderedBy: TextBasedRenderer.renderFunction,
+      renderedBy: { $0.renderFunction(_:) },
       rendersAs: #"""
         public func f<R>() where R: Sendable {}
         """#
@@ -477,7 +477,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         ]),
         body: []
       ),
-      renderedBy: TextBasedRenderer.renderFunction,
+      renderedBy: { $0.renderFunction(_:) },
       rendersAs: #"""
         public func f<R, T>() where R: Sendable, T: Encodable {}
         """#
@@ -487,7 +487,7 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testFunction() throws {
     try _test(
       .init(accessModifier: .public, kind: .function(name: "f"), parameters: [], body: []),
-      renderedBy: TextBasedRenderer.renderFunction,
+      renderedBy: { $0.renderFunction(_:) },
       rendersAs: #"""
         public func f() {}
         """#
@@ -499,7 +499,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         parameters: [.init(label: "a", name: "b", type: .member("C"), defaultValue: nil)],
         body: []
       ),
-      renderedBy: TextBasedRenderer.renderFunction,
+      renderedBy: { $0.renderFunction(_:) },
       rendersAs: #"""
         public func f(a b: C) {}
         """#
@@ -514,7 +514,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         ],
         body: []
       ),
-      renderedBy: TextBasedRenderer.renderFunction,
+      renderedBy: { $0.renderFunction(_:) },
       rendersAs: #"""
         public func f(
             a b: C,
@@ -529,7 +529,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         keywords: [.async, .throws],
         returnType: .identifierType(TypeName.string)
       ),
-      renderedBy: TextBasedRenderer.renderFunction,
+      renderedBy: { $0.renderFunction(_:) },
       rendersAs: #"""
         func f() async throws -> Swift.String
         """#
@@ -539,7 +539,7 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testIdentifiers() throws {
     try _test(
       .pattern("foo"),
-      renderedBy: TextBasedRenderer.renderIdentifier,
+      renderedBy: { $0.renderIdentifier(_:) },
       rendersAs: #"""
         foo
         """#
@@ -549,14 +549,14 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testMemberAccess() throws {
     try _test(
       .init(left: .identifierPattern("foo"), right: "bar"),
-      renderedBy: TextBasedRenderer.renderMemberAccess,
+      renderedBy: { $0.renderMemberAccess(_:) },
       rendersAs: #"""
         foo.bar
         """#
     )
     try _test(
       .init(left: nil, right: "bar"),
-      renderedBy: TextBasedRenderer.renderMemberAccess,
+      renderedBy: { $0.renderMemberAccess(_:) },
       rendersAs: #"""
         .bar
         """#
@@ -566,14 +566,14 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testFunctionCallArgument() throws {
     try _test(
       .init(label: "foo", expression: .identifierPattern("bar")),
-      renderedBy: TextBasedRenderer.renderFunctionCallArgument,
+      renderedBy: { $0.renderFunctionCallArgument(_:) },
       rendersAs: #"""
         foo: bar
         """#
     )
     try _test(
       .init(label: nil, expression: .identifierPattern("bar")),
-      renderedBy: TextBasedRenderer.renderFunctionCallArgument,
+      renderedBy: { $0.renderFunctionCallArgument(_:) },
       rendersAs: #"""
         bar
         """#
@@ -583,7 +583,7 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testFunctionCall() throws {
     try _test(
       .functionCall(.init(calledExpression: .identifierPattern("callee"))),
-      renderedBy: TextBasedRenderer.renderExpression,
+      renderedBy: { $0.renderExpression(_:) },
       rendersAs: #"""
         callee()
         """#
@@ -595,7 +595,7 @@ final class Test_TextBasedRenderer: XCTestCase {
           arguments: [.init(label: "foo", expression: .identifierPattern("bar"))]
         )
       ),
-      renderedBy: TextBasedRenderer.renderExpression,
+      renderedBy: { $0.renderExpression(_:) },
       rendersAs: #"""
         callee(foo: bar)
         """#
@@ -610,7 +610,7 @@ final class Test_TextBasedRenderer: XCTestCase {
           ]
         )
       ),
-      renderedBy: TextBasedRenderer.renderExpression,
+      renderedBy: { $0.renderExpression(_:) },
       rendersAs: #"""
         callee(
             foo: bar,
@@ -627,7 +627,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         onType: "Info",
         declarations: [.variable(kind: .let, left: "foo", type: .member("Int"))]
       ),
-      renderedBy: TextBasedRenderer.renderExtension,
+      renderedBy: { $0.renderExtension(_:) },
       rendersAs: #"""
         public extension Info {
             let foo: Int
@@ -639,28 +639,28 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testDeprecation() throws {
     try _test(
       .init(),
-      renderedBy: TextBasedRenderer.renderDeprecation,
+      renderedBy: { $0.renderDeprecation(_:) },
       rendersAs: #"""
         @available(*, deprecated)
         """#
     )
     try _test(
       .init(message: "some message"),
-      renderedBy: TextBasedRenderer.renderDeprecation,
+      renderedBy: { $0.renderDeprecation(_:) },
       rendersAs: #"""
         @available(*, deprecated, message: "some message")
         """#
     )
     try _test(
       .init(renamed: "newSymbol(param:)"),
-      renderedBy: TextBasedRenderer.renderDeprecation,
+      renderedBy: { $0.renderDeprecation(_:) },
       rendersAs: #"""
         @available(*, deprecated, renamed: "newSymbol(param:)")
         """#
     )
     try _test(
       .init(message: "some message", renamed: "newSymbol(param:)"),
-      renderedBy: TextBasedRenderer.renderDeprecation,
+      renderedBy: { $0.renderDeprecation(_:) },
       rendersAs: #"""
         @available(*, deprecated, message: "some message", renamed: "newSymbol(param:)")
         """#
@@ -675,7 +675,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         .init(os: .watchOS, version: "8.1.2"),
         .init(os: .tvOS, version: "15.0.2"),
       ]),
-      renderedBy: TextBasedRenderer.renderAvailability,
+      renderedBy: { $0.renderAvailability(_:) },
       rendersAs: #"""
         @available(macOS 12.0, iOS 13.1.2, watchOS 8.1.2, tvOS 15.0.2, *)
         """#
@@ -685,14 +685,14 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testBindingKind() throws {
     try _test(
       .var,
-      renderedBy: TextBasedRenderer.renderedBindingKind,
+      renderedBy: { $0.renderedBindingKind(_:) },
       rendersAs: #"""
         var
         """#
     )
     try _test(
       .let,
-      renderedBy: TextBasedRenderer.renderedBindingKind,
+      renderedBy: { $0.renderedBindingKind(_:) },
       rendersAs: #"""
         let
         """#
@@ -709,7 +709,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         type: .init(TypeName.string),
         right: .literal(.string("bar"))
       ),
-      renderedBy: TextBasedRenderer.renderVariable,
+      renderedBy: { $0.renderVariable(_:) },
       rendersAs: #"""
         public static let foo: Swift.String = "bar"
         """#
@@ -723,7 +723,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         type: nil,
         right: nil
       ),
-      renderedBy: TextBasedRenderer.renderVariable,
+      renderedBy: { $0.renderVariable(_:) },
       rendersAs: #"""
         internal var foo
         """#
@@ -735,7 +735,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         type: .init(TypeName.int),
         getter: [CodeBlock.expression(.literal(.int(42)))]
       ),
-      renderedBy: TextBasedRenderer.renderVariable,
+      renderedBy: { $0.renderVariable(_:) },
       rendersAs: #"""
         var foo: Swift.Int {
             42
@@ -750,7 +750,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         getter: [CodeBlock.expression(.literal(.int(42)))],
         getterEffects: [.throws]
       ),
-      renderedBy: TextBasedRenderer.renderVariable,
+      renderedBy: { $0.renderVariable(_:) },
       rendersAs: #"""
         var foo: Swift.Int {
             get throws {
@@ -764,7 +764,7 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testStruct() throws {
     try _test(
       .init(name: "Structy"),
-      renderedBy: TextBasedRenderer.renderStruct,
+      renderedBy: { $0.renderStruct(_:) },
       rendersAs: #"""
         struct Structy {}
         """#
@@ -774,7 +774,7 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testProtocol() throws {
     try _test(
       .init(name: "Protocoly"),
-      renderedBy: TextBasedRenderer.renderProtocol,
+      renderedBy: { $0.renderProtocol(_:) },
       rendersAs: #"""
         protocol Protocoly {}
         """#
@@ -784,7 +784,7 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testEnum() throws {
     try _test(
       .init(name: "Enumy"),
-      renderedBy: TextBasedRenderer.renderEnum,
+      renderedBy: { $0.renderEnum(_:) },
       rendersAs: #"""
         enum Enumy {}
         """#
@@ -794,14 +794,14 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testCodeBlockItem() throws {
     try _test(
       .declaration(.variable(kind: .let, left: "foo")),
-      renderedBy: TextBasedRenderer.renderCodeBlockItem,
+      renderedBy: { $0.renderCodeBlockItem(_:) },
       rendersAs: #"""
         let foo
         """#
     )
     try _test(
       .expression(.literal(.nil)),
-      renderedBy: TextBasedRenderer.renderCodeBlockItem,
+      renderedBy: { $0.renderCodeBlockItem(_:) },
       rendersAs: #"""
         nil
         """#
@@ -814,7 +814,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         comment: .inline("- MARK: Section"),
         item: .declaration(.variable(kind: .let, left: "foo"))
       ),
-      renderedBy: TextBasedRenderer.renderCodeBlock,
+      renderedBy: { $0.renderCodeBlock(_:) },
       rendersAs: #"""
         // - MARK: Section
         let foo
@@ -822,7 +822,7 @@ final class Test_TextBasedRenderer: XCTestCase {
     )
     try _test(
       .init(comment: nil, item: .declaration(.variable(kind: .let, left: "foo"))),
-      renderedBy: TextBasedRenderer.renderCodeBlock,
+      renderedBy: { $0.renderCodeBlock(_:) },
       rendersAs: #"""
         let foo
         """#
@@ -832,14 +832,14 @@ final class Test_TextBasedRenderer: XCTestCase {
   func testTypealias() throws {
     try _test(
       .init(name: "inty", existingType: .member("Int")),
-      renderedBy: TextBasedRenderer.renderTypealias,
+      renderedBy: { $0.renderTypealias(_:) },
       rendersAs: #"""
         typealias inty = Int
         """#
     )
     try _test(
       .init(accessModifier: .private, name: "inty", existingType: .member("Int")),
-      renderedBy: TextBasedRenderer.renderTypealias,
+      renderedBy: { $0.renderTypealias(_:) },
       rendersAs: #"""
         private typealias inty = Int
         """#
@@ -853,7 +853,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         imports: [.init(moduleName: "Foo")],
         codeBlocks: [.init(comment: nil, item: .declaration(.struct(.init(name: "Bar"))))]
       ),
-      renderedBy: TextBasedRenderer.renderFile,
+      renderedBy: { $0.renderFile(_:) },
       rendersAs: #"""
         // hi
 
@@ -876,7 +876,7 @@ final class Test_TextBasedRenderer: XCTestCase {
           )
         ]
       ),
-      renderedBy: TextBasedRenderer.renderFile,
+      renderedBy: { $0.renderFile(_:) },
       rendersAs: #"""
         // hi
 
@@ -891,7 +891,7 @@ final class Test_TextBasedRenderer: XCTestCase {
 
     try _test(
       .array([.literal(.nil), .literal(.nil)]),
-      renderedBy: TextBasedRenderer.renderLiteral,
+      renderedBy: { $0.renderLiteral(_:) },
       rendersAs: #"""
         [
            nil,
@@ -909,7 +909,7 @@ final class Test_TextBasedRenderer: XCTestCase {
         getter: [CodeBlock.expression(.literal(.int(42)))],
         getterEffects: [.throws]
       ),
-      renderedBy: TextBasedRenderer.renderVariable,
+      renderedBy: { $0.renderVariable(_:) },
       rendersAs: #"""
         var foo: Swift.Int {
              get throws {
@@ -928,7 +928,7 @@ extension Test_TextBasedRenderer {
     _ input: Input,
     renderedBy renderClosure: (TextBasedRenderer) -> ((Input) -> String),
     rendersAs output: String,
-    file: StaticString = #file,
+    file: StaticString = #filePath,
     line: UInt = #line,
     indentation: Int = 4
   ) throws {
@@ -940,7 +940,7 @@ extension Test_TextBasedRenderer {
     _ input: Input,
     renderedBy renderClosure: (TextBasedRenderer) -> ((Input) -> Void),
     rendersAs output: String,
-    file: StaticString = #file,
+    file: StaticString = #filePath,
     line: UInt = #line,
     indentation: Int = 4
   ) throws {

+ 19 - 7
Tests/GRPCCoreTests/Call/Server/Internal/ServerRPCExecutorTestSupport/ServerRPCExecutorTestHarness.swift

@@ -19,7 +19,7 @@ import XCTest
 
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
 struct ServerRPCExecutorTestHarness {
-  struct ServerHandler<Input, Output>: Sendable {
+  struct ServerHandler<Input: Sendable, Output: Sendable>: Sendable {
     let fn: @Sendable (ServerRequest.Stream<Input>) async throws -> ServerResponse.Stream<Output>
 
     init(
@@ -53,8 +53,12 @@ struct ServerRPCExecutorTestHarness {
     handler: @escaping @Sendable (
       ServerRequest.Stream<Input>
     ) async throws -> ServerResponse.Stream<Output>,
-    producer: @escaping (RPCWriter<RPCRequestPart>.Closable) async throws -> Void,
-    consumer: @escaping (RPCAsyncSequence<RPCResponsePart, any Error>) async throws -> Void
+    producer: @escaping @Sendable (
+      RPCWriter<RPCRequestPart>.Closable
+    ) async throws -> Void,
+    consumer: @escaping @Sendable (
+      RPCAsyncSequence<RPCResponsePart, any Error>
+    ) async throws -> Void
   ) async throws {
     try await self.execute(
       deserializer: deserializer,
@@ -69,8 +73,12 @@ struct ServerRPCExecutorTestHarness {
     deserializer: some MessageDeserializer<Input>,
     serializer: some MessageSerializer<Output>,
     handler: ServerHandler<Input, Output>,
-    producer: @escaping (RPCWriter<RPCRequestPart>.Closable) async throws -> Void,
-    consumer: @escaping (RPCAsyncSequence<RPCResponsePart, any Error>) async throws -> Void
+    producer: @escaping @Sendable (
+      RPCWriter<RPCRequestPart>.Closable
+    ) async throws -> Void,
+    consumer: @escaping @Sendable (
+      RPCAsyncSequence<RPCResponsePart, any Error>
+    ) async throws -> Void
   ) async throws {
     let input = RPCAsyncSequence.makeBackpressuredStream(
       of: RPCRequestPart.self,
@@ -111,8 +119,12 @@ struct ServerRPCExecutorTestHarness {
 
   func execute(
     handler: ServerHandler<[UInt8], [UInt8]> = .echo,
-    producer: @escaping (RPCWriter<RPCRequestPart>.Closable) async throws -> Void,
-    consumer: @escaping (RPCAsyncSequence<RPCResponsePart, any Error>) async throws -> Void
+    producer: @escaping @Sendable (
+      RPCWriter<RPCRequestPart>.Closable
+    ) async throws -> Void,
+    consumer: @escaping @Sendable (
+      RPCAsyncSequence<RPCResponsePart, any Error>
+    ) async throws -> Void
   ) async throws {
     try await self.execute(
       deserializer: IdentityDeserializer(),

+ 7 - 7
Tests/GRPCCoreTests/Streaming/Internal/BufferedStreamTests.swift

@@ -590,7 +590,7 @@ final class BufferedStreamTests: XCTestCase {
       of: Int.self,
       backPressureStrategy: .watermark(low: 0, high: 0)
     )
-    let (producerStream, producerContinuation) = AsyncThrowingStream<Void, Error>.makeStream()
+    let (producerStream, producerContinuation) = AsyncThrowingStream<Void, any Error>.makeStream()
     var iterator = stream.makeAsyncIterator()
 
     source?.write(1) {
@@ -688,7 +688,7 @@ final class BufferedStreamTests: XCTestCase {
       backPressureStrategy: .watermark(low: 1, high: 2)
     )
 
-    let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()
+    let (producerStream, producerSource) = AsyncThrowingStream<Void, any Error>.makeStream()
 
     try await source.write(1)
 
@@ -749,7 +749,7 @@ final class BufferedStreamTests: XCTestCase {
     )
     var iterator = stream.makeAsyncIterator()
 
-    let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()
+    let (producerStream, producerSource) = AsyncThrowingStream<Void, any Error>.makeStream()
 
     let writeResult = try { try source.write(1) }()
 
@@ -779,7 +779,7 @@ final class BufferedStreamTests: XCTestCase {
     )
     var iterator = stream.makeAsyncIterator()
 
-    let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()
+    let (producerStream, producerSource) = AsyncThrowingStream<Void, any Error>.makeStream()
 
     let writeResult = try { try source.write(1) }()
 
@@ -809,7 +809,7 @@ final class BufferedStreamTests: XCTestCase {
     )
     var iterator = stream.makeAsyncIterator()
 
-    let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()
+    let (producerStream, producerSource) = AsyncThrowingStream<Void, any Error>.makeStream()
 
     let writeResult = try { try source.write(1) }()
 
@@ -843,7 +843,7 @@ final class BufferedStreamTests: XCTestCase {
       backPressureStrategy: .watermark(low: 1, high: 2)
     )
 
-    let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()
+    let (producerStream, producerSource) = AsyncThrowingStream<Void, any Error>.makeStream()
 
     try await source.write(1)
 
@@ -877,7 +877,7 @@ final class BufferedStreamTests: XCTestCase {
       backPressureStrategy: .watermark(low: 1, high: 2)
     )
 
-    let (producerStream, producerSource) = AsyncThrowingStream<Void, Error>.makeStream()
+    let (producerStream, producerSource) = AsyncThrowingStream<Void, any Error>.makeStream()
 
     try await source.write(1)
 

+ 2 - 3
Tests/GRPCCoreTests/Test Utilities/Coding+JSON.swift

@@ -19,12 +19,10 @@ import struct Foundation.Data
 import class Foundation.JSONDecoder
 import class Foundation.JSONEncoder
 
-private let jsonEncoder = JSONEncoder()
-private let jsonDecoder = JSONDecoder()
-
 struct JSONSerializer<Message: Codable>: MessageSerializer {
   func serialize(_ message: Message) throws -> [UInt8] {
     do {
+      let jsonEncoder = JSONEncoder()
       return try Array(jsonEncoder.encode(message))
     } catch {
       throw RPCError(code: .internalError, message: "Can't serialize message to JSON. \(error)")
@@ -35,6 +33,7 @@ struct JSONSerializer<Message: Codable>: MessageSerializer {
 struct JSONDeserializer<Message: Codable>: MessageDeserializer {
   func deserialize(_ serializedMessageBytes: [UInt8]) throws -> Message {
     do {
+      let jsonDecoder = JSONDecoder()
       return try jsonDecoder.decode(Message.self, from: Data(serializedMessageBytes))
     } catch {
       throw RPCError(code: .internalError, message: "Can't deserialze message from JSON. \(error)")

+ 1 - 1
Tests/GRPCCoreTests/Test Utilities/RPCWriter+Utilities.swift

@@ -41,7 +41,7 @@ private struct FailOnWrite<Element>: RPCWriterProtocol {
 }
 
 @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
-private struct AsyncStreamGatheringWriter<Element>: RPCWriterProtocol {
+private struct AsyncStreamGatheringWriter<Element: Sendable>: RPCWriterProtocol {
   let continuation: AsyncStream<Element>.Continuation
 
   init(continuation: AsyncStream<Element>.Continuation) {

+ 2 - 2
Tests/GRPCCoreTests/Test Utilities/Transport/AnyTransport.swift

@@ -25,7 +25,7 @@ struct AnyClientTransport: ClientTransport, Sendable {
     @Sendable (
       _ method: MethodDescriptor,
       _ options: CallOptions,
-      _ body: (RPCStream<Inbound, Outbound>) async throws -> Any
+      _ body: (RPCStream<Inbound, Outbound>) async throws -> (any Sendable)
     ) async throws -> Any
   private let _connect: @Sendable () async throws -> Void
   private let _close: @Sendable () -> Void
@@ -36,7 +36,7 @@ struct AnyClientTransport: ClientTransport, Sendable {
     self._retryThrottle = { transport.retryThrottle }
     self._withStream = { descriptor, options, closure in
       try await transport.withStream(descriptor: descriptor, options: options) { stream in
-        try await closure(stream) as Any
+        try await closure(stream) as (any Sendable)
       }
     }
 

+ 1 - 1
Tests/GRPCCoreTests/Test Utilities/Transport/StreamCountingTransport.swift

@@ -94,7 +94,7 @@ struct StreamCountingServerTransport: ServerTransport, Sendable {
   }
 
   func listen(
-    _ streamHandler: @escaping (RPCStream<Inbound, Outbound>) async -> Void
+    _ streamHandler: @escaping @Sendable (RPCStream<Inbound, Outbound>) async -> Void
   ) async throws {
     try await self.transport.listen { stream in
       self._acceptedStreams.wrappingIncrement(ordering: .sequentiallyConsistent)

+ 1 - 1
Tests/GRPCCoreTests/Test Utilities/XCTest+Utilities.swift

@@ -28,7 +28,7 @@ func XCTAssertDescription(
 @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
 func XCTAssertThrowsErrorAsync<T>(
   _ expression: () async throws -> T,
-  errorHandler: (Error) -> Void
+  errorHandler: (any Error) -> Void
 ) async {
   do {
     _ = try await expression()

+ 1 - 13
Tests/GRPCHTTP2CoreTests/Client/Connection/Connection+Equatable.swift

@@ -18,18 +18,7 @@ import GRPCCore
 import GRPCHTTP2Core
 
 // Equatable conformance for these types is 'best effort', this is sufficient for testing but not
-// for general use. As such the conformance is added in the test module and must be declared
-// as a `@retroactive` conformance.
-#if compiler(>=6.0)
-@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
-extension Connection.Event: @retroactive Equatable {}
-@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
-extension Connection.CloseReason: @retroactive Equatable {}
-
-extension ClientConnectionEvent: @retroactive Equatable {}
-extension ClientConnectionEvent.CloseReason: @retroactive Equatable {}
-
-#else
+// for general use.
 @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
 extension Connection.Event: Equatable {}
 @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
@@ -37,7 +26,6 @@ extension Connection.CloseReason: Equatable {}
 
 extension ClientConnectionEvent: Equatable {}
 extension ClientConnectionEvent.CloseReason: Equatable {}
-#endif
 
 @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
 extension Connection.Event {

+ 2 - 2
Tests/GRPCHTTP2CoreTests/Client/Connection/ConnectionTests.swift

@@ -204,9 +204,9 @@ final class ConnectionTests: XCTestCase {
 
 extension ClientBootstrap {
   @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
-  func connect<T>(
+  func connect<T: Sendable>(
     to address: GRPCHTTP2Core.SocketAddress,
-    _ configure: @Sendable @escaping (Channel) -> EventLoopFuture<T>
+    _ configure: @Sendable @escaping (any Channel) -> EventLoopFuture<T>
   ) async throws -> T {
     if let ipv4 = address.ipv4 {
       return try await self.connect(

+ 1 - 1
Tests/GRPCHTTP2CoreTests/Client/Connection/LoadBalancers/LoadBalancerTest.swift

@@ -86,7 +86,7 @@ enum LoadBalancerTest {
   ) async throws {
     enum TestEvent {
       case timedOut
-      case completed(Result<Void, Error>)
+      case completed(Result<Void, any Error>)
     }
 
     try await withThrowingTaskGroup(of: TestEvent.self) { group in

+ 13 - 11
Tests/GRPCHTTP2CoreTests/Client/Connection/Utilities/ConnectionTest.swift

@@ -29,7 +29,7 @@ enum ConnectionTest {
   }
 
   static func run(
-    connector: HTTP2Connector,
+    connector: any HTTP2Connector,
     server mode: Server.Mode = .regular,
     handlEvents: (
       _ context: Context,
@@ -67,10 +67,10 @@ extension ConnectionTest {
   final class Server {
     private let eventLoop: any EventLoop
     private var listener: (any Channel)?
-    private let client: EventLoopPromise<Channel>
+    private let client: EventLoopPromise<any Channel>
     private let mode: Mode
 
-    enum Mode {
+    enum Mode: Sendable {
       case regular
       case closeOnAccept
     }
@@ -86,7 +86,7 @@ extension ConnectionTest {
       self.client.futureResult.whenSuccess { $0.close(mode: .all, promise: nil) }
     }
 
-    var acceptedChannel: Channel {
+    var acceptedChannel: any Channel {
       get throws {
         try self.client.futureResult.wait()
       }
@@ -95,15 +95,17 @@ extension ConnectionTest {
     func bind() async throws -> GRPCHTTP2Core.SocketAddress {
       precondition(self.listener == nil, "\(#function) must only be called once")
 
-      let hasAcceptedChannel = try await self.eventLoop.submit {
-        NIOLoopBoundBox(false, eventLoop: self.eventLoop)
+      let hasAcceptedChannel = try await self.eventLoop.submit { [loop = self.eventLoop] in
+        NIOLoopBoundBox(false, eventLoop: loop)
       }.get()
 
-      let bootstrap = ServerBootstrap(group: self.eventLoop).childChannelInitializer { channel in
+      let bootstrap = ServerBootstrap(
+        group: self.eventLoop
+      ).childChannelInitializer { [mode = self.mode, client = self.client] channel in
         precondition(!hasAcceptedChannel.value, "already accepted a channel")
         hasAcceptedChannel.value = true
 
-        switch self.mode {
+        switch mode {
         case .closeOnAccept:
           return channel.close()
 
@@ -128,7 +130,7 @@ extension ConnectionTest {
 
             try sync.addHandler(h2)
             try sync.addHandler(mux)
-            try sync.addHandlers(SucceedOnSettingsAck(promise: self.client))
+            try sync.addHandlers(SucceedOnSettingsAck(promise: client))
           }
         }
       }
@@ -147,9 +149,9 @@ extension ConnectionTest {
     typealias InboundIn = HTTP2Frame
     typealias InboundOut = HTTP2Frame
 
-    private let promise: EventLoopPromise<Channel>
+    private let promise: EventLoopPromise<any Channel>
 
-    init(promise: EventLoopPromise<Channel>) {
+    init(promise: EventLoopPromise<any Channel>) {
       self.promise = promise
     }
 

+ 4 - 4
Tests/GRPCHTTP2CoreTests/Client/Connection/Utilities/NameResolvers.swift

@@ -44,8 +44,8 @@ extension NameResolver {
 }
 
 @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
-struct ConstantAsyncSequence<Element>: AsyncSequence {
-  private let result: Result<Element, Error>
+struct ConstantAsyncSequence<Element: Sendable>: AsyncSequence, Sendable {
+  private let result: Result<Element, any Error>
 
   init(element: Element) {
     self.result = .success(element)
@@ -60,9 +60,9 @@ struct ConstantAsyncSequence<Element>: AsyncSequence {
   }
 
   struct AsyncIterator: AsyncIteratorProtocol {
-    private let result: Result<Element, Error>
+    private let result: Result<Element, any Error>
 
-    fileprivate init(result: Result<Element, Error>) {
+    fileprivate init(result: Result<Element, any Error>) {
       self.result = result
     }
 

+ 3 - 3
Tests/GRPCHTTP2CoreTests/Client/Connection/Utilities/TestServer.swift

@@ -29,7 +29,7 @@ final class TestServer: Sendable {
   private typealias Stream = NIOAsyncChannel<RPCRequestPart, RPCResponsePart>
   private typealias Multiplexer = NIOHTTP2AsyncSequence<Stream>
 
-  private let connected: NIOLockedValueBox<[Channel]>
+  private let connected: NIOLockedValueBox<[any Channel]>
 
   typealias Inbound = NIOAsyncChannelInboundStream<RPCRequestPart>
   typealias Outbound = NIOAsyncChannelOutboundWriter<RPCResponsePart>
@@ -47,7 +47,7 @@ final class TestServer: Sendable {
     case uds(String)
   }
 
-  var clients: [Channel] {
+  var clients: [any Channel] {
     return self.connected.withLockedValue { $0 }
   }
 
@@ -55,7 +55,7 @@ final class TestServer: Sendable {
     precondition(self.server.withLockedValue { $0 } == nil)
 
     @Sendable
-    func configure(_ channel: Channel) -> EventLoopFuture<Multiplexer> {
+    func configure(_ channel: any Channel) -> EventLoopFuture<Multiplexer> {
       self.connected.withLockedValue {
         $0.append(channel)
       }

+ 0 - 5
Tests/GRPCHTTP2CoreTests/GRPCStreamStateMachineTests.swift

@@ -2886,10 +2886,5 @@ extension GRPCStreamStateMachine.OnNextOutboundFrame {
   }
 }
 
-#if compiler(>=6.0)
-@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
-extension GRPCStreamStateMachine.OnNextOutboundFrame: @retroactive Equatable {}
-#else
 @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
 extension GRPCStreamStateMachine.OnNextOutboundFrame: Equatable {}
-#endif

+ 17 - 17
Tests/GRPCHTTP2CoreTests/Internal/TimerTests.swift

@@ -15,32 +15,33 @@
  */
 
 import Atomics
+import GRPCCore
+import GRPCHTTP2Core
 import NIOEmbedded
 import XCTest
 
-@testable import GRPCHTTP2Core
-
 internal final class TimerTests: XCTestCase {
   func testScheduleOneOffTimer() {
     let loop = EmbeddedEventLoop()
     defer { try! loop.close() }
 
-    var value = 0
-
+    let value = LockedValueBox(0)
     var timer = Timer(delay: .seconds(1), repeat: false)
     timer.schedule(on: loop) {
-      XCTAssertEqual(value, 0)
-      value += 1
+      value.withLockedValue {
+        XCTAssertEqual($0, 0)
+        $0 += 1
+      }
     }
 
     loop.advanceTime(by: .milliseconds(999))
-    XCTAssertEqual(value, 0)
+    XCTAssertEqual(value.withLockedValue { $0 }, 0)
     loop.advanceTime(by: .milliseconds(1))
-    XCTAssertEqual(value, 1)
+    XCTAssertEqual(value.withLockedValue { $0 }, 1)
 
     // Run again to make sure the task wasn't repeated.
     loop.advanceTime(by: .seconds(1))
-    XCTAssertEqual(value, 1)
+    XCTAssertEqual(value.withLockedValue { $0 }, 1)
   }
 
   func testCancelOneOffTimer() {
@@ -61,26 +62,25 @@ internal final class TimerTests: XCTestCase {
     let loop = EmbeddedEventLoop()
     defer { try! loop.close() }
 
-    var values = [Int]()
-
+    let values = LockedValueBox([Int]())
     var timer = Timer(delay: .seconds(1), repeat: true)
     timer.schedule(on: loop) {
-      values.append(values.count)
+      values.withLockedValue { $0.append($0.count) }
     }
 
     loop.advanceTime(by: .milliseconds(999))
-    XCTAssertEqual(values, [])
+    XCTAssertEqual(values.withLockedValue { $0 }, [])
     loop.advanceTime(by: .milliseconds(1))
-    XCTAssertEqual(values, [0])
+    XCTAssertEqual(values.withLockedValue { $0 }, [0])
 
     loop.advanceTime(by: .seconds(1))
-    XCTAssertEqual(values, [0, 1])
+    XCTAssertEqual(values.withLockedValue { $0 }, [0, 1])
     loop.advanceTime(by: .seconds(1))
-    XCTAssertEqual(values, [0, 1, 2])
+    XCTAssertEqual(values.withLockedValue { $0 }, [0, 1, 2])
 
     timer.cancel()
     loop.advanceTime(by: .seconds(1))
-    XCTAssertEqual(values, [0, 1, 2])
+    XCTAssertEqual(values.withLockedValue { $0 }, [0, 1, 2])
   }
 
   func testCancelRepeatedTimer() {

+ 1 - 1
Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift

@@ -135,7 +135,7 @@ final class HTTP2TransportTests: XCTestCase {
   }
 
   private func runServer(
-    in group: inout ThrowingTaskGroup<Void, Error>,
+    in group: inout ThrowingTaskGroup<Void, any Error>,
     kind: Transport.Kind,
     enableControlService: Bool,
     compression: CompressionAlgorithmSet

+ 1 - 1
Tests/GRPCHTTP2TransportTests/Test Utilities/HTTP2StatusCodeServer.swift

@@ -24,7 +24,7 @@ import NIOPosix
 /// then closing. Each stream will be closed with the ":status" set to the value of the
 /// "response-status" header field in the request headers.
 @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
-final class HTTP2StatusCodeServer {
+final class HTTP2StatusCodeServer: Sendable {
   private let address: EventLoopPromise<GRPCHTTP2Core.SocketAddress.IPv4>
   private let eventLoopGroup: MultiThreadedEventLoopGroup