DDLogMessageFormatTests.swift 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Software License Agreement (BSD License)
  2. //
  3. // Copyright (c) 2010-2025, Deusty, LLC
  4. // All rights reserved.
  5. //
  6. // Redistribution and use of this software in source and binary forms,
  7. // with or without modification, are permitted provided that the following conditions are met:
  8. //
  9. // * Redistributions of source code must retain the above copyright notice,
  10. // this list of conditions and the following disclaimer.
  11. //
  12. // * Neither the name of Deusty nor the names of its contributors may be used
  13. // to endorse or promote products derived from this software without specific
  14. // prior written permission of Deusty, LLC.
  15. import XCTest
  16. @testable import CocoaLumberjackSwift
  17. final class DDLogMessageFormatTests: XCTestCase {
  18. func testMessageFormatCreationWithNoArgs() {
  19. let format: DDLogMessageFormat = "Message with no args"
  20. let expectedFormat: String = "Message with no args"
  21. XCTAssertFalse(format.storage.requiresArgumentParsing)
  22. XCTAssertEqual(format.format, expectedFormat)
  23. XCTAssertTrue(format.args.isEmpty)
  24. XCTAssertEqual(format.formatted, expectedFormat)
  25. }
  26. func testMessageFormatCreationWithString() {
  27. let str: String = "String"
  28. let substr: Substring = "Substring"
  29. let format: DDLogMessageFormat = "This is a string: \(str). And this a substring: \(substr)."
  30. let expectedFormat: String = "This is a string: %@. And this a substring: %@."
  31. XCTAssertTrue(format.storage.requiresArgumentParsing)
  32. XCTAssertEqual(format.format, expectedFormat)
  33. XCTAssertEqual(format.args.count, 2)
  34. XCTAssertEqual(format.args.first as? String, str)
  35. XCTAssertEqual(format.args.last as? String, String(substr))
  36. XCTAssertEqual(format.formatted, String(format: expectedFormat, arguments: [str, String(substr)]))
  37. }
  38. func testMessageFormatCreationWithInts() {
  39. let int8: Int8 = -7
  40. let uint8: UInt8 = 7
  41. let int16: Int16 = -42
  42. let uint16: UInt16 = 42
  43. let int32: Int32 = -472345
  44. let uint32: UInt32 = 472345
  45. let int64: Int64 = -47234532145
  46. let uint64: UInt64 = 47234532145
  47. let int: Int = -2345654
  48. let uint: UInt = 2345654
  49. let format: DDLogMessageFormat = "Int8: \(int8); UInt8: \(uint8); Int16: \(int16); UInt16: \(uint16); Int32: \(int32); UInt32: \(uint32); Int64: \(int64); UInt64: \(uint64); Int: \(int); UInt: \(uint)"
  50. let expectedFormat: String = "Int8: %c; UInt8: %c; Int16: %i; UInt16: %u; Int32: %li; UInt32: %lu; Int64: %lli; UInt64: %llu; Int: %lli; UInt: %llu"
  51. XCTAssertTrue(format.storage.requiresArgumentParsing)
  52. XCTAssertEqual(format.format, expectedFormat)
  53. XCTAssertEqual(format.args.count, 10)
  54. guard format.args.count >= 10 else { return } // prevent crashes
  55. XCTAssertEqual(format.args[0] as? Int8, int8)
  56. XCTAssertEqual(format.args[1] as? UInt8, uint8)
  57. XCTAssertEqual(format.args[2] as? Int16, int16)
  58. XCTAssertEqual(format.args[3] as? UInt16, uint16)
  59. XCTAssertEqual(format.args[4] as? Int32, int32)
  60. XCTAssertEqual(format.args[5] as? UInt32, uint32)
  61. XCTAssertEqual(format.args[6] as? Int64, int64)
  62. XCTAssertEqual(format.args[7] as? UInt64, uint64)
  63. XCTAssertEqual(format.args[8] as? Int, int)
  64. XCTAssertEqual(format.args[9] as? UInt, uint)
  65. XCTAssertEqual(format.formatted, String(format: expectedFormat, arguments: [
  66. int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint,
  67. ]))
  68. }
  69. func testMessageFormatCreationWithFloats() {
  70. let flt: Float = 42.4344
  71. let dbl: Double = 42.1345512
  72. let format: DDLogMessageFormat = "Float: \(flt); Double: \(dbl)"
  73. let expectedFormat: String = "Float: %f; Double: %lf"
  74. XCTAssertTrue(format.storage.requiresArgumentParsing)
  75. XCTAssertEqual(format.format, expectedFormat)
  76. XCTAssertEqual(format.args.count, 2)
  77. XCTAssertEqual(format.args.first as? Float, flt)
  78. XCTAssertEqual(format.args.last as? Double, dbl)
  79. XCTAssertEqual(format.formatted, String(format: expectedFormat, arguments: [flt, dbl]))
  80. }
  81. func testMessageFormatCreationWithReferenceConvertibles() {
  82. let date = Date()
  83. let uuid = UUID()
  84. let indexPath = IndexPath(indexes: [1, 2, 3])
  85. let format: DDLogMessageFormat = "Date: \(date); UUID: \(uuid); IndexPath: \(indexPath)"
  86. let expectedFormat: String = "Date: %@; UUID: %@; IndexPath: %@"
  87. XCTAssertTrue(format.storage.requiresArgumentParsing)
  88. XCTAssertEqual(format.format, expectedFormat)
  89. XCTAssertEqual(format.args.count, 3)
  90. guard format.args.count >= 3 else { return } // prevent crashes
  91. XCTAssertEqual((format.args[0] as? NSDate).map { $0 as Date }, date)
  92. XCTAssertEqual((format.args[1] as? NSUUID).map { $0 as UUID }, uuid)
  93. XCTAssertEqual((format.args[2] as? NSIndexPath).map { $0 as IndexPath }, indexPath)
  94. XCTAssertEqual(format.formatted, String(format: expectedFormat, arguments: [date as NSDate, uuid as NSUUID, indexPath as NSIndexPath]))
  95. }
  96. func testMessageFormatCreationWithNSObjects() {
  97. final class TestObject: NSObject {}
  98. let obj = TestObject()
  99. let format: DDLogMessageFormat = "Object: \(obj)"
  100. let expectedFormat: String = "Object: %@"
  101. XCTAssertTrue(format.storage.requiresArgumentParsing)
  102. XCTAssertEqual(format.format, expectedFormat)
  103. XCTAssertEqual(format.args.count, 1)
  104. XCTAssertIdentical(format.args.first as? NSObject, obj)
  105. XCTAssertEqual(format.formatted, String(format: expectedFormat, arguments: [obj]))
  106. }
  107. func testMessageFormatCreationWithOtherTypes() {
  108. struct TestStruct: Sendable, CustomStringConvertible {
  109. var description: String { "STRUCT DESCRIPTION" }
  110. }
  111. let other = TestStruct()
  112. let format: DDLogMessageFormat = "Other: \(other)"
  113. let expectedFormat: String = "Other: %@"
  114. XCTAssertTrue(format.storage.requiresArgumentParsing)
  115. XCTAssertEqual(format.format, expectedFormat)
  116. XCTAssertEqual(format.args.count, 1)
  117. XCTAssertEqual(format.args.first as? String, String(describing: other))
  118. XCTAssertEqual(format.formatted, String(format: expectedFormat, arguments: [String(describing: other)]))
  119. }
  120. func testMessageFormatWithSpaces() {
  121. let format: DDLogMessageFormat = " this is a message that starts and ends with a space "
  122. let expectedFormat: String = " this is a message that starts and ends with a space "
  123. XCTAssertFalse(format.storage.requiresArgumentParsing)
  124. XCTAssertEqual(format.format, expectedFormat)
  125. XCTAssertTrue(format.args.isEmpty)
  126. XCTAssertEqual(format.formatted, expectedFormat)
  127. }
  128. func testMessageFormatWithPercentInLiteral() {
  129. let formatWithoutArgs: DDLogMessageFormat = "This message contains % some % percent %20 signs but no args"
  130. let formatWithArgs: DDLogMessageFormat = "This message contains % some % percent %20 signs and \(1) other stuff at \(12.34)"
  131. let expectedFormatWithoutArgs = "This message contains % some % percent %20 signs but no args"
  132. let expectedFormatWithArgs = "This message contains %% some %% percent %%20 signs and %lli other stuff at %lf"
  133. XCTAssertFalse(formatWithoutArgs.storage.requiresArgumentParsing)
  134. XCTAssertTrue(formatWithArgs.storage.requiresArgumentParsing)
  135. XCTAssertEqual(formatWithoutArgs.format, expectedFormatWithoutArgs)
  136. XCTAssertEqual(formatWithArgs.format, expectedFormatWithArgs)
  137. XCTAssertTrue(formatWithoutArgs.args.isEmpty)
  138. XCTAssertFalse(formatWithArgs.args.isEmpty)
  139. XCTAssertEqual(formatWithArgs.args.count, 2)
  140. XCTAssertEqual(formatWithoutArgs.formatted, expectedFormatWithoutArgs)
  141. XCTAssertEqual(formatWithArgs.formatted, String(format: expectedFormatWithArgs, arguments: formatWithArgs.args))
  142. }
  143. }