GRPCStatusTests.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. @testable import GRPC
  17. import XCTest
  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(describing: GRPCStatus(
  55. code: .internalError,
  56. message: "unknown error processing request",
  57. cause: cause
  58. ))
  59. )
  60. }
  61. func testStatusDescriptionWithoutMessageWithCause() {
  62. struct UnderlyingError: Error, CustomStringConvertible {
  63. var description: String { "underlying error description" }
  64. }
  65. let cause = UnderlyingError()
  66. XCTAssertEqual(
  67. "internal error (13), cause: \(cause.description)",
  68. String(describing: GRPCStatus(
  69. code: .internalError,
  70. message: nil,
  71. cause: cause
  72. ))
  73. )
  74. }
  75. func testCoWSemanticsModifyingMessage() {
  76. let nilStorageID = GRPCStatus.ok.testingOnly_storageObjectIdentifier
  77. var status = GRPCStatus(code: .resourceExhausted)
  78. // No message/cause, so uses the nil backing storage.
  79. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, nilStorageID)
  80. status.message = "no longer using the nil backing storage"
  81. let storageID = status.testingOnly_storageObjectIdentifier
  82. XCTAssertNotEqual(storageID, nilStorageID)
  83. XCTAssertEqual(status.message, "no longer using the nil backing storage")
  84. // The storage of status should be uniquely ref'd, so setting message to nil should not change
  85. // the backing storage (even if the nil storage could now be used).
  86. status.message = nil
  87. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, storageID)
  88. XCTAssertNil(status.message)
  89. }
  90. func testCoWSemanticsModifyingCause() {
  91. let nilStorageID = GRPCStatus.ok.testingOnly_storageObjectIdentifier
  92. var status = GRPCStatus(code: .cancelled)
  93. // No message/cause, so uses the nil backing storage.
  94. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, nilStorageID)
  95. status.cause = ConnectionPoolError.tooManyWaiters(connectionError: nil)
  96. let storageID = status.testingOnly_storageObjectIdentifier
  97. XCTAssertNotEqual(storageID, nilStorageID)
  98. XCTAssert(status.cause is ConnectionPoolError)
  99. // The storage of status should be uniquely ref'd, so setting cause to nil should not change
  100. // the backing storage (even if the nil storage could now be used).
  101. status.cause = nil
  102. XCTAssertEqual(status.testingOnly_storageObjectIdentifier, storageID)
  103. XCTAssertNil(status.cause)
  104. }
  105. func testStatusesWithNoMessageOrCauseShareBackingStorage() {
  106. let validStatusCodes = (0 ... 16)
  107. let statuses: [GRPCStatus] = validStatusCodes.map { code in
  108. // 0...16 are all valid, '!' is fine.
  109. let code = GRPCStatus.Code(rawValue: code)!
  110. return GRPCStatus(code: code)
  111. }
  112. let storageIDs = Set(statuses.map { $0.testingOnly_storageObjectIdentifier })
  113. XCTAssertEqual(storageIDs.count, 1)
  114. }
  115. }