2
0

InteroperabilityTestCases.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /*
  2. * Copyright 2024, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import GRPCCore
  17. import struct Foundation.Data
  18. /// This test verifies that implementations support zero-size messages. Ideally, client
  19. /// implementations would verify that the request and response were zero bytes serialized, but
  20. /// this is generally prohibitive to perform, so is not required.
  21. ///
  22. /// Server features:
  23. /// - EmptyCall
  24. ///
  25. /// Procedure:
  26. /// 1. Client calls EmptyCall with the default Empty message
  27. ///
  28. /// Client asserts:
  29. /// - call was successful
  30. /// - response is non-null
  31. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  32. struct EmptyUnary: InteroperabilityTest {
  33. func run(client: GRPCClient) async throws {
  34. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  35. try await testServiceClient.emptyCall(
  36. request: ClientRequest.Single(message: Grpc_Testing_Empty())
  37. ) { response in
  38. try assertEqual(response.message, Grpc_Testing_Empty())
  39. }
  40. }
  41. }
  42. /// This test verifies unary calls succeed in sending messages, and touches on flow control (even
  43. /// if compression is enabled on the channel).
  44. ///
  45. /// Server features:
  46. /// - UnaryCall
  47. ///
  48. /// Procedure:
  49. /// 1. Client calls UnaryCall with:
  50. /// ```
  51. /// {
  52. /// response_size: 314159
  53. /// payload:{
  54. /// body: 271828 bytes of zeros
  55. /// }
  56. /// }
  57. /// ```
  58. ///
  59. /// Client asserts:
  60. /// - call was successful
  61. /// - response payload body is 314159 bytes in size
  62. /// - clients are free to assert that the response payload body contents are zero and comparing
  63. /// the entire response message against a golden response
  64. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  65. struct LargeUnary: InteroperabilityTest {
  66. func run(client: GRPCClient) async throws {
  67. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  68. let request = Grpc_Testing_SimpleRequest.with { request in
  69. request.responseSize = 314_159
  70. request.payload = Grpc_Testing_Payload.with {
  71. $0.body = Data(count: 271_828)
  72. }
  73. }
  74. try await testServiceClient.unaryCall(
  75. request: ClientRequest.Single(message: request)
  76. ) { response in
  77. try assertEqual(
  78. response.message.payload,
  79. Grpc_Testing_Payload.with {
  80. $0.body = Data(count: 314_159)
  81. }
  82. )
  83. }
  84. }
  85. }
  86. /// This test verifies that client-only streaming succeeds.
  87. ///
  88. /// Server features:
  89. /// - StreamingInputCall
  90. ///
  91. /// Procedure:
  92. /// 1. Client calls StreamingInputCall
  93. /// 2. Client sends:
  94. /// ```
  95. /// {
  96. /// payload:{
  97. /// body: 27182 bytes of zeros
  98. /// }
  99. /// }
  100. /// ```
  101. /// 3. Client then sends:
  102. /// ```
  103. /// {
  104. /// payload:{
  105. /// body: 8 bytes of zeros
  106. /// }
  107. /// }
  108. /// ```
  109. /// 4. Client then sends:
  110. /// ```
  111. /// {
  112. /// payload:{
  113. /// body: 1828 bytes of zeros
  114. /// }
  115. /// }
  116. /// ```
  117. /// 5. Client then sends:
  118. /// ```
  119. /// {
  120. /// payload:{
  121. /// body: 45904 bytes of zeros
  122. /// }
  123. /// }
  124. /// ```
  125. /// 6. Client half-closes
  126. ///
  127. /// Client asserts:
  128. /// - call was successful
  129. /// - response aggregated_payload_size is 74922
  130. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  131. struct ClientStreaming: InteroperabilityTest {
  132. func run(client: GRPCClient) async throws {
  133. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  134. let request = ClientRequest.Stream { writer in
  135. for bytes in [27182, 8, 1828, 45904] {
  136. let message = Grpc_Testing_StreamingInputCallRequest.with {
  137. $0.payload = Grpc_Testing_Payload.with {
  138. $0.body = Data(count: bytes)
  139. }
  140. }
  141. try await writer.write(message)
  142. }
  143. }
  144. try await testServiceClient.streamingInputCall(request: request) { response in
  145. try assertEqual(response.message.aggregatedPayloadSize, 74922)
  146. }
  147. }
  148. }
  149. /// This test verifies that server-only streaming succeeds.
  150. ///
  151. /// Server features:
  152. /// - StreamingOutputCall
  153. ///
  154. /// Procedure:
  155. /// 1. Client calls StreamingOutputCall with StreamingOutputCallRequest:
  156. /// ```
  157. /// {
  158. /// response_parameters:{
  159. /// size: 31415
  160. /// }
  161. /// response_parameters:{
  162. /// size: 9
  163. /// }
  164. /// response_parameters:{
  165. /// size: 2653
  166. /// }
  167. /// response_parameters:{
  168. /// size: 58979
  169. /// }
  170. /// }
  171. /// ```
  172. ///
  173. /// Client asserts:
  174. /// - call was successful
  175. /// - exactly four responses
  176. /// - response payload bodies are sized (in order): 31415, 9, 2653, 58979
  177. /// - clients are free to assert that the response payload body contents are zero and
  178. /// comparing the entire response messages against golden responses
  179. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  180. struct ServerStreaming: InteroperabilityTest {
  181. func run(client: GRPCClient) async throws {
  182. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  183. let responseSizes = [31415, 9, 2653, 58979]
  184. let request = Grpc_Testing_StreamingOutputCallRequest.with { request in
  185. request.responseParameters = responseSizes.map {
  186. var parameter = Grpc_Testing_ResponseParameters()
  187. parameter.size = Int32($0)
  188. return parameter
  189. }
  190. }
  191. try await testServiceClient.streamingOutputCall(
  192. request: ClientRequest.Single(message: request)
  193. ) { response in
  194. var responseParts = response.messages.makeAsyncIterator()
  195. // There are 4 response sizes, so if there isn't a message for each one,
  196. // it means that the client didn't receive 4 messages back.
  197. for responseSize in responseSizes {
  198. if let message = try await responseParts.next() {
  199. try assertEqual(message.payload.body.count, responseSize)
  200. } else {
  201. throw AssertionFailure(
  202. message: "There were less than four responses received."
  203. )
  204. }
  205. }
  206. // Check that there were not more than 4 responses from the server.
  207. try assertEqual(try await responseParts.next(), nil)
  208. }
  209. }
  210. }
  211. /// This test verifies that full duplex bidi is supported.
  212. ///
  213. /// Server features:
  214. /// - FullDuplexCall
  215. ///
  216. /// Procedure:
  217. /// 1. Client calls FullDuplexCall with:
  218. /// ```
  219. /// {
  220. /// response_parameters:{
  221. /// size: 31415
  222. /// }
  223. /// payload:{
  224. /// body: 27182 bytes of zeros
  225. /// }
  226. /// }
  227. /// ```
  228. /// 2. After getting a reply, it sends:
  229. /// ```
  230. /// {
  231. /// response_parameters:{
  232. /// size: 9
  233. /// }
  234. /// payload:{
  235. /// body: 8 bytes of zeros
  236. /// }
  237. /// }
  238. /// ```
  239. /// 3. After getting a reply, it sends:
  240. /// ```
  241. /// {
  242. /// response_parameters:{
  243. /// size: 2653
  244. /// }
  245. /// payload:{
  246. /// body: 1828 bytes of zeros
  247. /// }
  248. /// }
  249. /// ```
  250. /// 4. After getting a reply, it sends:
  251. /// ```
  252. /// {
  253. /// response_parameters:{
  254. /// size: 58979
  255. /// }
  256. /// payload:{
  257. /// body: 45904 bytes of zeros
  258. /// }
  259. /// }
  260. /// ```
  261. /// 5. After getting a reply, client half-closes
  262. ///
  263. /// Client asserts:
  264. /// - call was successful
  265. /// - exactly four responses
  266. /// - response payload bodies are sized (in order): 31415, 9, 2653, 58979
  267. /// - clients are free to assert that the response payload body contents are zero and
  268. /// comparing the entire response messages against golden responses
  269. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  270. struct PingPong: InteroperabilityTest {
  271. func run(client: GRPCClient) async throws {
  272. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  273. let ids = AsyncStream.makeStream(of: Int.self)
  274. let request = ClientRequest.Stream { writer in
  275. let sizes = [(31_415, 27_182), (9, 8), (2_653, 1_828), (58_979, 45_904)]
  276. for try await id in ids.stream {
  277. var message = Grpc_Testing_StreamingOutputCallRequest()
  278. switch id {
  279. case 1 ... 4:
  280. let (responseSize, bodySize) = sizes[id - 1]
  281. message.responseParameters = [
  282. Grpc_Testing_ResponseParameters.with {
  283. $0.size = Int32(responseSize)
  284. }
  285. ]
  286. message.payload = Grpc_Testing_Payload.with {
  287. $0.body = Data(count: bodySize)
  288. }
  289. default:
  290. // When the id is higher than 4 it means the client received all the expected responses
  291. // and it doesn't need to send another message.
  292. return
  293. }
  294. try await writer.write(message)
  295. }
  296. }
  297. ids.continuation.yield(1)
  298. try await testServiceClient.fullDuplexCall(request: request) { response in
  299. var id = 1
  300. for try await message in response.messages {
  301. switch id {
  302. case 1:
  303. try assertEqual(message.payload.body, Data(count: 31_415))
  304. case 2:
  305. try assertEqual(message.payload.body, Data(count: 9))
  306. case 3:
  307. try assertEqual(message.payload.body, Data(count: 2_653))
  308. case 4:
  309. try assertEqual(message.payload.body, Data(count: 58_979))
  310. default:
  311. throw AssertionFailure(
  312. message: "We should only receive messages with ids between 1 and 4."
  313. )
  314. }
  315. // Add the next id to the continuation.
  316. id += 1
  317. ids.continuation.yield(id)
  318. }
  319. }
  320. }
  321. }
  322. /// This test verifies that streams support having zero-messages in both directions.
  323. ///
  324. /// Server features:
  325. /// - FullDuplexCall
  326. ///
  327. /// Procedure:
  328. /// 1. Client calls FullDuplexCall and then half-closes
  329. ///
  330. /// Client asserts:
  331. /// - call was successful
  332. /// - exactly zero responses
  333. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  334. struct EmptyStream: InteroperabilityTest {
  335. func run(client: GRPCClient) async throws {
  336. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  337. let request = ClientRequest.Stream<Grpc_Testing_StreamingOutputCallRequest> { _ in }
  338. try await testServiceClient.fullDuplexCall(request: request) { response in
  339. var messages = response.messages.makeAsyncIterator()
  340. try await assertEqual(messages.next(), nil)
  341. }
  342. }
  343. }
  344. /// This test verifies that custom metadata in either binary or ascii format can be sent as
  345. /// initial-metadata by the client and as both initial- and trailing-metadata by the server.
  346. ///
  347. /// Server features:
  348. /// - UnaryCall
  349. /// - FullDuplexCall
  350. /// - Echo Metadata
  351. ///
  352. /// Procedure:
  353. /// 1. The client attaches custom metadata with the following keys and values
  354. /// to a UnaryCall with request:
  355. /// - key: "x-grpc-test-echo-initial", value: "test_initial_metadata_value"
  356. /// - key: "x-grpc-test-echo-trailing-bin", value: 0xababab
  357. /// ```
  358. /// {
  359. /// response_size: 314159
  360. /// payload:{
  361. /// body: 271828 bytes of zeros
  362. /// }
  363. /// }
  364. /// ```
  365. /// 2. The client attaches custom metadata with the following keys and values
  366. /// to a FullDuplexCall with request:
  367. /// - key: "x-grpc-test-echo-initial", value: "test_initial_metadata_value"
  368. /// - key: "x-grpc-test-echo-trailing-bin", value: 0xababab
  369. /// ```
  370. /// {
  371. /// response_parameters:{
  372. /// size: 314159
  373. /// }
  374. /// payload:{
  375. /// body: 271828 bytes of zeros
  376. /// }
  377. /// }
  378. /// ```
  379. /// and then half-closes
  380. ///
  381. /// Client asserts:
  382. /// - call was successful
  383. /// - metadata with key "x-grpc-test-echo-initial" and value "test_initial_metadata_value" is
  384. /// received in the initial metadata for calls in Procedure steps 1 and 2.
  385. /// - metadata with key "x-grpc-test-echo-trailing-bin" and value 0xababab is received in the
  386. /// trailing metadata for calls in Procedure steps 1 and 2.
  387. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  388. struct CustomMetadata: InteroperabilityTest {
  389. let initialMetadataName = "x-grpc-test-echo-initial"
  390. let initialMetadataValue = "test_initial_metadata_value"
  391. let trailingMetadataName = "x-grpc-test-echo-trailing-bin"
  392. let trailingMetadataValue: [UInt8] = [0xAB, 0xAB, 0xAB]
  393. func checkInitialMetadata(_ metadata: Metadata) throws {
  394. let values = metadata[self.initialMetadataName]
  395. try assertEqual(Array(values), [.string(self.initialMetadataValue)])
  396. }
  397. func checkTrailingMetadata(_ metadata: Metadata) throws {
  398. let values = metadata[self.trailingMetadataName]
  399. try assertEqual(Array(values), [.binary(self.trailingMetadataValue)])
  400. }
  401. func run(client: GRPCClient) async throws {
  402. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  403. let unaryRequest = Grpc_Testing_SimpleRequest.with { request in
  404. request.responseSize = 314_159
  405. request.payload = Grpc_Testing_Payload.with {
  406. $0.body = Data(count: 271_828)
  407. }
  408. }
  409. let metadata: Metadata = [
  410. self.initialMetadataName: .string(self.initialMetadataValue),
  411. self.trailingMetadataName: .binary(self.trailingMetadataValue),
  412. ]
  413. try await testServiceClient.unaryCall(
  414. request: ClientRequest.Single(message: unaryRequest, metadata: metadata)
  415. ) { response in
  416. // Check the initial metadata.
  417. let receivedInitialMetadata = response.metadata
  418. try checkInitialMetadata(receivedInitialMetadata)
  419. // Check the message.
  420. try assertEqual(response.message.payload.body, Data(count: 314_159))
  421. // Check the trailing metadata.
  422. try checkTrailingMetadata(response.trailingMetadata)
  423. }
  424. let streamingRequest = ClientRequest.Stream(metadata: metadata) { writer in
  425. let message = Grpc_Testing_StreamingOutputCallRequest.with {
  426. $0.responseParameters = [
  427. Grpc_Testing_ResponseParameters.with {
  428. $0.size = 314_159
  429. }
  430. ]
  431. $0.payload = Grpc_Testing_Payload.with {
  432. $0.body = Data(count: 271_828)
  433. }
  434. }
  435. try await writer.write(message)
  436. }
  437. try await testServiceClient.fullDuplexCall(request: streamingRequest) { response in
  438. switch response.accepted {
  439. case .success(let contents):
  440. // Check the initial metadata.
  441. let receivedInitialMetadata = response.metadata
  442. try self.checkInitialMetadata(receivedInitialMetadata)
  443. let parts = try await contents.bodyParts.reduce(into: []) { $0.append($1) }
  444. try assertEqual(parts.count, 2)
  445. for part in parts {
  446. switch part {
  447. // Check the message.
  448. case .message(let message):
  449. try assertEqual(message.payload.body, Data(count: 314_159))
  450. // Check the trailing metadata.
  451. case .trailingMetadata(let receivedTrailingMetadata):
  452. try self.checkTrailingMetadata(receivedTrailingMetadata)
  453. }
  454. }
  455. case .failure(_):
  456. throw AssertionFailure(
  457. message: "The client should have received a response from the server."
  458. )
  459. }
  460. }
  461. }
  462. }
  463. /// This test verifies unary calls succeed in sending messages, and propagate back status code and
  464. /// message sent along with the messages.
  465. ///
  466. /// Server features:
  467. /// - UnaryCall
  468. /// - FullDuplexCall
  469. /// - Echo Status
  470. ///
  471. /// Procedure:
  472. /// 1. Client calls UnaryCall with:
  473. /// ```
  474. /// {
  475. /// response_status:{
  476. /// code: 2
  477. /// message: "test status message"
  478. /// }
  479. /// }
  480. /// ```
  481. /// 2. Client calls FullDuplexCall with:
  482. /// ```
  483. /// {
  484. /// response_status:{
  485. /// code: 2
  486. /// message: "test status message"
  487. /// }
  488. /// }
  489. /// ```
  490. /// 3. and then half-closes
  491. ///
  492. /// Client asserts:
  493. /// - received status code is the same as the sent code for both Procedure steps 1 and 2
  494. /// - received status message is the same as the sent message for both Procedure steps 1 and 2
  495. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  496. struct StatusCodeAndMessage: InteroperabilityTest {
  497. let expectedCode = 2
  498. let expectedMessage = "test status message"
  499. func run(client: GRPCClient) async throws {
  500. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  501. let message = Grpc_Testing_SimpleRequest.with {
  502. $0.responseStatus = Grpc_Testing_EchoStatus.with {
  503. $0.code = Int32(self.expectedCode)
  504. $0.message = self.expectedMessage
  505. }
  506. }
  507. try await testServiceClient.unaryCall(
  508. request: ClientRequest.Single(message: message)
  509. ) { response in
  510. switch response.accepted {
  511. case .failure(let error):
  512. try assertEqual(error.code.rawValue, self.expectedCode)
  513. try assertEqual(error.message, self.expectedMessage)
  514. case .success(_):
  515. throw AssertionFailure(
  516. message:
  517. "The client should receive an error with the status code and message sent by the client."
  518. )
  519. }
  520. }
  521. let request = ClientRequest.Stream { writer in
  522. let message = Grpc_Testing_StreamingOutputCallRequest.with {
  523. $0.responseStatus = Grpc_Testing_EchoStatus.with {
  524. $0.code = Int32(self.expectedCode)
  525. $0.message = self.expectedMessage
  526. }
  527. }
  528. try await writer.write(message)
  529. }
  530. try await testServiceClient.fullDuplexCall(request: request) { response in
  531. do {
  532. for try await _ in response.messages {
  533. throw AssertionFailure(
  534. message:
  535. "The client should receive an error with the status code and message sent by the client."
  536. )
  537. }
  538. } catch let error as RPCError {
  539. try assertEqual(error.code.rawValue, self.expectedCode)
  540. try assertEqual(error.message, self.expectedMessage)
  541. }
  542. }
  543. }
  544. }
  545. /// This test verifies Unicode and whitespace is correctly processed in status message. "\t" is
  546. /// horizontal tab. "\r" is carriage return. "\n" is line feed.
  547. ///
  548. /// Server features:
  549. /// - UnaryCall
  550. /// - Echo Status
  551. ///
  552. /// Procedure:
  553. /// 1. Client calls UnaryCall with:
  554. /// ```
  555. /// {
  556. /// response_status:{
  557. /// code: 2
  558. /// message: "\t\ntest with whitespace\r\nand Unicode BMP ☺ and non-BMP 😈\t\n"
  559. /// }
  560. /// }
  561. /// ```
  562. ///
  563. /// Client asserts:
  564. /// - received status code is the same as the sent code for Procedure step 1
  565. /// - received status message is the same as the sent message for Procedure step 1, including all
  566. /// whitespace characters
  567. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  568. struct SpecialStatusMessage: InteroperabilityTest {
  569. func run(client: GRPCClient) async throws {
  570. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  571. let responseMessage = "\t\ntest with whitespace\r\nand Unicode BMP ☺ and non-BMP 😈\t\n"
  572. let message = Grpc_Testing_SimpleRequest.with {
  573. $0.responseStatus = Grpc_Testing_EchoStatus.with {
  574. $0.code = 2
  575. $0.message = responseMessage
  576. }
  577. }
  578. try await testServiceClient.unaryCall(
  579. request: ClientRequest.Single(message: message)
  580. ) { response in
  581. switch response.accepted {
  582. case .success(_):
  583. throw AssertionFailure(
  584. message: "The response should be an error with the error code 2."
  585. )
  586. case .failure(let error):
  587. try assertEqual(error.code.rawValue, 2)
  588. try assertEqual(error.message, responseMessage)
  589. }
  590. }
  591. }
  592. }
  593. /// This test verifies that calling an unimplemented RPC method returns the UNIMPLEMENTED status
  594. /// code.
  595. ///
  596. /// Server features: N/A
  597. ///
  598. /// Procedure:
  599. /// 1. Client calls grpc.testing.TestService/UnimplementedCall with an empty request (defined as
  600. /// grpc.testing.Empty):
  601. /// ```
  602. /// {
  603. /// }
  604. /// ```
  605. ///
  606. /// Client asserts:
  607. /// - received status code is 12 (UNIMPLEMENTED)
  608. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  609. struct UnimplementedMethod: InteroperabilityTest {
  610. func run(client: GRPCClient) async throws {
  611. let testServiceClient = Grpc_Testing_TestService.Client(client: client)
  612. try await testServiceClient.unimplementedCall(
  613. request: ClientRequest.Single(message: Grpc_Testing_Empty())
  614. ) { response in
  615. let result = response.accepted
  616. switch result {
  617. case .success(_):
  618. throw AssertionFailure(
  619. message: "The result should be an error."
  620. )
  621. case .failure(let error):
  622. try assertEqual(error.code, .unimplemented)
  623. }
  624. }
  625. }
  626. }
  627. /// This test verifies calling an unimplemented server returns the UNIMPLEMENTED status code.
  628. ///
  629. /// Server features: N/A
  630. ///
  631. /// Procedure:
  632. /// 1. Client calls grpc.testing.UnimplementedService/UnimplementedCall with an empty request
  633. /// (defined as grpc.testing.Empty):
  634. /// ```
  635. /// {
  636. /// }
  637. /// ```
  638. ///
  639. /// Client asserts:
  640. /// - received status code is 12 (UNIMPLEMENTED)
  641. @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  642. struct UnimplementedService: InteroperabilityTest {
  643. func run(client: GRPCClient) async throws {
  644. let unimplementedServiceClient = Grpc_Testing_UnimplementedService.Client(client: client)
  645. try await unimplementedServiceClient.unimplementedCall(
  646. request: ClientRequest.Single(message: Grpc_Testing_Empty())
  647. ) { response in
  648. let result = response.accepted
  649. switch result {
  650. case .success(_):
  651. throw AssertionFailure(
  652. message: "The result should be an error."
  653. )
  654. case .failure(let error):
  655. try assertEqual(error.code, .unimplemented)
  656. }
  657. }
  658. }
  659. }