GRPCTestCase.swift 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. }
  62. /// A `LogHandler` which does nothing with log messages.
  63. struct BlackHole: LogHandler {
  64. func log(level: Logger.Level, message: Logger.Message, metadata: Logger.Metadata?, file: String, function: String, line: UInt) {
  65. ()
  66. }
  67. subscript(metadataKey key: String) -> Logger.Metadata.Value? {
  68. get {
  69. return metadata[key]
  70. }
  71. set(newValue) {
  72. self.metadata[key] = newValue
  73. }
  74. }
  75. var metadata: Logger.Metadata = [:]
  76. var logLevel: Logger.Level = .critical
  77. }
  78. fileprivate extension Bool {
  79. init(fromTruthLike value: String?, defaultingTo defaultValue: Bool) {
  80. switch value?.lowercased() {
  81. case "0", "false", "no":
  82. self = false
  83. case "1", "true", "yes":
  84. self = true
  85. default:
  86. self = defaultValue
  87. }
  88. }
  89. }