PartsRepresentableTests.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright 2024 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import CoreGraphics
  15. import XCTest
  16. #if canImport(UIKit)
  17. import UIKit
  18. #elseif canImport(AppKit)
  19. import AppKit
  20. #endif
  21. #if canImport(CoreImage)
  22. import CoreImage
  23. #endif // canImport(CoreImage)
  24. @testable import FirebaseVertexAI
  25. @available(iOS 15.0, macOS 11.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  26. final class PartsRepresentableTests: XCTestCase {
  27. #if !os(watchOS)
  28. func testModelContentFromCGImageIsNotEmpty() throws {
  29. // adapted from https://forums.swift.org/t/creating-a-cgimage-from-color-array/18634/2
  30. var srgbArray = [UInt32](repeating: 0xFFFF_FFFF, count: 8 * 8)
  31. let image = srgbArray.withUnsafeMutableBytes { ptr -> CGImage in
  32. let ctx = CGContext(
  33. data: ptr.baseAddress,
  34. width: 8,
  35. height: 8,
  36. bitsPerComponent: 8,
  37. bytesPerRow: 4 * 8,
  38. space: CGColorSpace(name: CGColorSpace.sRGB)!,
  39. bitmapInfo: CGBitmapInfo.byteOrder32Little.rawValue +
  40. CGImageAlphaInfo.premultipliedFirst.rawValue
  41. )!
  42. return ctx.makeImage()!
  43. }
  44. let modelContent = image.partsValue
  45. XCTAssert(modelContent.count > 0, "Expected non-empty model content for CGImage: \(image)")
  46. }
  47. #endif // !os(watchOS)
  48. #if canImport(CoreImage)
  49. func testModelContentFromCIImageIsNotEmpty() throws {
  50. let image = CIImage(color: CIColor.red)
  51. .cropped(to: CGRect(origin: CGPointZero, size: CGSize(width: 16, height: 16)))
  52. let modelContent = image.partsValue
  53. XCTAssert(modelContent.count > 0, "Expected non-empty model content for CGImage: \(image)")
  54. }
  55. func testModelContentFromInvalidCIImageThrows() throws {
  56. let image = CIImage.empty()
  57. let modelContent = image.partsValue
  58. let part = try XCTUnwrap(modelContent.first)
  59. let errorPart = try XCTUnwrap(part as? ErrorPart, "Expected ErrorPart.")
  60. let imageError = try XCTUnwrap(
  61. errorPart.error as? ImageConversionError,
  62. "Got unexpected error type: \(errorPart.error)"
  63. )
  64. guard case .couldNotConvertToJPEG = imageError else {
  65. XCTFail("Expected JPEG conversion error, got \(imageError) instead.")
  66. return
  67. }
  68. }
  69. #endif // canImport(CoreImage)
  70. #if canImport(UIKit) && !os(visionOS) // These tests are stalling in CI on visionOS.
  71. func testModelContentFromInvalidUIImageThrows() throws {
  72. let image = UIImage()
  73. let modelContent = image.partsValue
  74. let part = try XCTUnwrap(modelContent.first)
  75. let errorPart = try XCTUnwrap(part as? ErrorPart, "Expected ErrorPart.")
  76. let imageError = try XCTUnwrap(
  77. errorPart.error as? ImageConversionError,
  78. "Got unexpected error type: \(errorPart.error)"
  79. )
  80. guard case .couldNotConvertToJPEG = imageError else {
  81. XCTFail("Expected JPEG conversion error, got \(imageError) instead.")
  82. return
  83. }
  84. }
  85. func testModelContentFromUIImageIsNotEmpty() throws {
  86. let image = try XCTUnwrap(UIImage(systemName: "star.fill"))
  87. let modelContent = image.partsValue
  88. XCTAssert(modelContent.count > 0, "Expected non-empty model content for UIImage: \(image)")
  89. }
  90. #elseif canImport(AppKit)
  91. func testModelContentFromNSImageIsNotEmpty() throws {
  92. let coreImage = CIImage(color: CIColor.red)
  93. .cropped(to: CGRect(origin: CGPointZero, size: CGSize(width: 16, height: 16)))
  94. let rep = NSCIImageRep(ciImage: coreImage)
  95. let image = NSImage(size: rep.size)
  96. image.addRepresentation(rep)
  97. let modelContent = image.partsValue
  98. XCTAssert(modelContent.count > 0, "Expected non-empty model content for NSImage: \(image)")
  99. }
  100. func testModelContentFromInvalidNSImageThrows() throws {
  101. let image = NSImage()
  102. let modelContent = image.partsValue
  103. let part = try XCTUnwrap(modelContent.first)
  104. let errorPart = try XCTUnwrap(part as? ErrorPart, "Expected ErrorPart.")
  105. let imageError = try XCTUnwrap(
  106. errorPart.error as? ImageConversionError,
  107. "Got unexpected error type: \(errorPart.error)"
  108. )
  109. guard case .invalidUnderlyingImage = imageError else {
  110. XCTFail("Expected invalid underyling image conversion error, got \(imageError) instead.")
  111. return
  112. }
  113. }
  114. #endif
  115. }