GRPCTestCase.swift 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. import Logging
  18. /// A test case which initializes the logging system once.
  19. ///
  20. /// This should be used instead of `XCTestCase`.
  21. class GRPCTestCase: XCTestCase {
  22. // Travis will fail the CI if there is too much logging, but it can be useful when running
  23. // locally; conditionally enable it based on the environment.
  24. //
  25. // https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
  26. private static let isCI = Bool(
  27. fromTruthLike: ProcessInfo.processInfo.environment["CI"],
  28. defaultingTo: false
  29. )
  30. private static let isLoggingEnabled = !isCI
  31. private static let runTimeSensitiveTests = Bool(
  32. fromTruthLike: ProcessInfo.processInfo.environment["ENABLE_TIMING_TESTS"],
  33. defaultingTo: true
  34. )
  35. // `LoggingSystem.bootstrap` must be called once per process. This is the suggested approach to
  36. // workaround this for XCTestCase.
  37. //
  38. // See: https://github.com/apple/swift-log/issues/77
  39. private static let isLoggingConfigured: Bool = {
  40. LoggingSystem.bootstrap { label in
  41. guard isLoggingEnabled else {
  42. return BlackHole()
  43. }
  44. var handler = StreamLogHandler.standardOutput(label: label)
  45. handler.logLevel = .debug
  46. return handler
  47. }
  48. return true
  49. }()
  50. override class func setUp() {
  51. super.setUp()
  52. XCTAssertTrue(GRPCTestCase.isLoggingConfigured)
  53. }
  54. func runTimeSensitiveTests() -> Bool {
  55. let shouldRun = GRPCTestCase.runTimeSensitiveTests
  56. if !shouldRun {
  57. print("Skipping '\(self.name)' as ENABLE_TIMING_TESTS=false")
  58. }
  59. return shouldRun
  60. }
  61. var logger: Logger {
  62. return Logger(label: "io.grpc.testing")
  63. }
  64. }
  65. /// A `LogHandler` which does nothing with log messages.
  66. struct BlackHole: LogHandler {
  67. func log(level: Logger.Level, message: Logger.Message, metadata: Logger.Metadata?, file: String, function: String, line: UInt) {
  68. ()
  69. }
  70. subscript(metadataKey key: String) -> Logger.Metadata.Value? {
  71. get {
  72. return metadata[key]
  73. }
  74. set(newValue) {
  75. self.metadata[key] = newValue
  76. }
  77. }
  78. var metadata: Logger.Metadata = [:]
  79. var logLevel: Logger.Level = .critical
  80. }
  81. fileprivate extension Bool {
  82. init(fromTruthLike value: String?, defaultingTo defaultValue: Bool) {
  83. switch value?.lowercased() {
  84. case "0", "false", "no":
  85. self = false
  86. case "1", "true", "yes":
  87. self = true
  88. default:
  89. self = defaultValue
  90. }
  91. }
  92. }