GRPCStatusTests.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright 2019, 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 XCTest
  17. @testable import GRPC
  18. class GRPCStatusTests: GRPCTestCase {
  19. func testStatusDescriptionWithoutMessage() {
  20. XCTAssertEqual(
  21. "ok (0)",
  22. String(describing: GRPCStatus(code: .ok, message: nil))
  23. )
  24. XCTAssertEqual(
  25. "aborted (10)",
  26. String(describing: GRPCStatus(code: .aborted, message: nil))
  27. )
  28. XCTAssertEqual(
  29. "internal error (13)",
  30. String(describing: GRPCStatus(code: .internalError, message: nil))
  31. )
  32. }
  33. func testStatusDescriptionWithWithMessageWithoutCause() {
  34. XCTAssertEqual(
  35. "ok (0): OK",
  36. String(describing: GRPCStatus(code: .ok, message: "OK"))
  37. )
  38. XCTAssertEqual(
  39. "resource exhausted (8): a resource was exhausted",
  40. String(describing: GRPCStatus(code: .resourceExhausted, message: "a resource was exhausted"))
  41. )
  42. XCTAssertEqual(
  43. "failed precondition (9): invalid state",
  44. String(describing: GRPCStatus(code: .failedPrecondition, message: "invalid state"))
  45. )
  46. }
  47. func testStatusDescriptionWithMessageWithCause() {
  48. struct UnderlyingError: Error, CustomStringConvertible {
  49. var description: String { "underlying error description" }
  50. }
  51. let cause = UnderlyingError()
  52. XCTAssertEqual(
  53. "internal error (13): unknown error processing request, cause: \(cause.description)",
  54. String(
  55. describing: GRPCStatus(
  56. code: .internalError,
  57. message: "unknown error processing request",
  58. cause: cause
  59. )
  60. )
  61. )
  62. }
  63. func testStatusDescriptionWithoutMessageWithCause() {
  64. struct UnderlyingError: Error, CustomStringConvertible {
  65. var description: String { "underlying error description" }
  66. }
  67. let cause = UnderlyingError()
  68. XCTAssertEqual(
  69. "internal error (13), cause: \(cause.description)",
  70. String(
  71. describing: GRPCStatus(
  72. code: .internalError,
  73. message: nil,
  74. cause: cause
  75. )
  76. )
  77. )
  78. }
  79. func testCoWSemanticsModifyingMessage() {
  80. let nilStorageID = GRPCStatus.ok.testingOnly_storageObjectIdentifier
  81. var status = GRPCStatus(code: .resourceExhausted)
  82. // No message/cause, so uses the nil backing storage.
  83. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, nilStorageID)
  84. status.message = "no longer using the nil backing storage"
  85. let storageID = status.testingOnly_storageObjectIdentifier
  86. XCTAssertNotEqual(storageID, nilStorageID)
  87. XCTAssertEqual(status.message, "no longer using the nil backing storage")
  88. // The storage of status should be uniquely ref'd, so setting message to nil should not change
  89. // the backing storage (even if the nil storage could now be used).
  90. status.message = nil
  91. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, storageID)
  92. XCTAssertNil(status.message)
  93. }
  94. func testCoWSemanticsModifyingCause() {
  95. let nilStorageID = GRPCStatus.ok.testingOnly_storageObjectIdentifier
  96. var status = GRPCStatus(code: .cancelled)
  97. // No message/cause, so uses the nil backing storage.
  98. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, nilStorageID)
  99. status.cause = ConnectionPoolError.tooManyWaiters(connectionError: nil)
  100. let storageID = status.testingOnly_storageObjectIdentifier
  101. XCTAssertNotEqual(storageID, nilStorageID)
  102. XCTAssert(status.cause is ConnectionPoolError)
  103. // The storage of status should be uniquely ref'd, so setting cause to nil should not change
  104. // the backing storage (even if the nil storage could now be used).
  105. status.cause = nil
  106. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, storageID)
  107. XCTAssertNil(status.cause)
  108. }
  109. func testStatusesWithNoMessageOrCauseShareBackingStorage() {
  110. let validStatusCodes = (0 ... 16)
  111. let statuses: [GRPCStatus] = validStatusCodes.map { code in
  112. // 0...16 are all valid, '!' is fine.
  113. let code = GRPCStatus.Code(rawValue: code)!
  114. return GRPCStatus(code: code)
  115. }
  116. let storageIDs = Set(statuses.map { $0.testingOnly_storageObjectIdentifier })
  117. XCTAssertEqual(storageIDs.count, 1)
  118. }
  119. }