chore: import upstream snapshot with attribution
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:14:16 +08:00
commit 8a852e4b4e
36502 changed files with 9277225 additions and 0 deletions
@@ -0,0 +1,391 @@
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
@testable import TensorFlowLite
class InterpreterTests: XCTestCase {
var interpreter: Interpreter!
override func setUp() {
super.setUp()
interpreter = try! Interpreter(modelPath: AddModel.path)
}
override func tearDown() {
interpreter = nil
super.tearDown()
}
func testInit_ValidModelPath() {
XCTAssertNoThrow(try Interpreter(modelPath: AddModel.path))
}
func testInit_InvalidModelPath_ThrowsFailedToLoadModel() {
XCTAssertThrowsError(try Interpreter(modelPath: "/invalid/path")) { error in
self.assertEqualErrors(actual: error, expected: .failedToLoadModel)
}
}
func testInitWithOptions() throws {
var options = Interpreter.Options()
options.threadCount = 2
let interpreter = try Interpreter(modelPath: AddQuantizedModel.path, options: options)
XCTAssertNotNil(interpreter.options)
XCTAssertNil(interpreter.delegates)
}
func testInit_WithData_ValidModelPath() {
XCTAssertNoThrow(
try Interpreter(modelData: try Data(contentsOf: URL(fileURLWithPath: AddModel.path))))
}
func testInitWithDataWithOptions() throws {
var options = Interpreter.Options()
options.threadCount = 2
let interpreter = try Interpreter(
modelData: try Data(contentsOf: URL(fileURLWithPath: AddQuantizedModel.path)),
options: options
)
XCTAssertNotNil(interpreter.options)
XCTAssertNil(interpreter.delegates)
}
func testInputTensorCount() {
XCTAssertEqual(interpreter.inputTensorCount, AddModel.inputTensorCount)
}
func testOutputTensorCount() {
XCTAssertEqual(interpreter.outputTensorCount, AddModel.outputTensorCount)
}
func testInvoke() throws {
try interpreter.allocateTensors()
XCTAssertNoThrow(try interpreter.invoke())
}
func testInvoke_ThrowsAllocateTensorsRequired_ModelNotReady() {
XCTAssertThrowsError(try interpreter.invoke()) { error in
self.assertEqualErrors(actual: error, expected: .allocateTensorsRequired)
}
}
func testInputTensorAtIndex() throws {
try setUpAddModelInputTensor()
let inputTensor = try interpreter.input(at: AddModel.validIndex)
XCTAssertEqual(inputTensor, AddModel.inputTensor)
}
func testInputTensorAtIndex_QuantizedModel() throws {
interpreter = try Interpreter(modelPath: AddQuantizedModel.path)
try setUpAddQuantizedModelInputTensor()
let inputTensor = try interpreter.input(at: AddQuantizedModel.inputOutputIndex)
XCTAssertEqual(inputTensor, AddQuantizedModel.inputTensor)
}
func testInputTensorAtIndex_ThrowsInvalidIndex() throws {
try interpreter.allocateTensors()
XCTAssertThrowsError(try interpreter.input(at: AddModel.invalidIndex)) { error in
let maxIndex = AddModel.inputTensorCount - 1
self.assertEqualErrors(
actual: error,
expected: .invalidTensorIndex(index: AddModel.invalidIndex, maxIndex: maxIndex)
)
}
}
func testInputTensorAtIndex_ThrowsAllocateTensorsRequired() {
XCTAssertThrowsError(try interpreter.input(at: AddModel.validIndex)) { error in
self.assertEqualErrors(actual: error, expected: .allocateTensorsRequired)
}
}
func testOutputTensorAtIndex() throws {
try setUpAddModelInputTensor()
try interpreter.invoke()
let outputTensor = try interpreter.output(at: AddModel.validIndex)
XCTAssertEqual(outputTensor, AddModel.outputTensor)
let expectedResults = [Float32](unsafeData: outputTensor.data)
XCTAssertEqual(expectedResults, AddModel.results)
}
func testOutputTensorAtIndex_QuantizedModel() throws {
interpreter = try Interpreter(modelPath: AddQuantizedModel.path)
try setUpAddQuantizedModelInputTensor()
try interpreter.invoke()
let outputTensor = try interpreter.output(at: AddQuantizedModel.inputOutputIndex)
XCTAssertEqual(outputTensor, AddQuantizedModel.outputTensor)
let expectedResults = [UInt8](outputTensor.data)
XCTAssertEqual(expectedResults, AddQuantizedModel.results)
}
func testOutputTensorAtIndex_ThrowsInvalidIndex() throws {
try interpreter.allocateTensors()
try interpreter.invoke()
XCTAssertThrowsError(try interpreter.output(at: AddModel.invalidIndex)) { error in
let maxIndex = AddModel.outputTensorCount - 1
self.assertEqualErrors(
actual: error,
expected: .invalidTensorIndex(index: AddModel.invalidIndex, maxIndex: maxIndex)
)
}
}
func testOutputTensorAtIndex_ThrowsInvokeInterpreterRequired() {
XCTAssertThrowsError(try interpreter.output(at: AddModel.validIndex)) { error in
self.assertEqualErrors(actual: error, expected: .invokeInterpreterRequired)
}
}
func testResizeInputTensorAtIndexToShape() {
XCTAssertNoThrow(try interpreter.resizeInput(at: AddModel.validIndex, to: [2, 2, 3]))
XCTAssertNoThrow(try interpreter.allocateTensors())
}
func testResizeInputTensorAtIndexToShape_ThrowsInvalidIndex() {
XCTAssertThrowsError(
try interpreter.resizeInput(
at: AddModel.invalidIndex,
to: [2, 2, 3]
)
) { error in
let maxIndex = AddModel.inputTensorCount - 1
self.assertEqualErrors(
actual: error,
expected: .invalidTensorIndex(index: AddModel.invalidIndex, maxIndex: maxIndex)
)
}
}
func testCopyDataToInputTensorAtIndex() throws {
try interpreter.resizeInput(at: AddModel.validIndex, to: AddModel.shape)
try interpreter.allocateTensors()
let inputTensor = try interpreter.copy(AddModel.inputData, toInputAt: AddModel.validIndex)
XCTAssertEqual(inputTensor.data, AddModel.inputData)
}
func testCopyDataToInputTensorAtIndex_ThrowsInvalidIndex() {
XCTAssertThrowsError(
try interpreter.copy(
AddModel.inputData,
toInputAt: AddModel.invalidIndex
)
) { error in
let maxIndex = AddModel.inputTensorCount - 1
self.assertEqualErrors(
actual: error,
expected: .invalidTensorIndex(index: AddModel.invalidIndex, maxIndex: maxIndex)
)
}
}
func testCopyDataToInputTensorAtIndex_ThrowsInvalidDataCount() throws {
try interpreter.resizeInput(at: AddModel.validIndex, to: AddModel.shape)
try interpreter.allocateTensors()
let invalidData = Data(count: AddModel.dataCount - 1)
XCTAssertThrowsError(
try interpreter.copy(
invalidData,
toInputAt: AddModel.validIndex
)
) { error in
self.assertEqualErrors(
actual: error,
expected: .invalidTensorDataCount(provided: invalidData.count, required: AddModel.dataCount)
)
}
}
func testAllocateTensors() {
XCTAssertNoThrow(try interpreter.allocateTensors())
}
// MARK: - Private
private func setUpAddModelInputTensor() throws {
precondition(interpreter != nil)
try interpreter.resizeInput(at: AddModel.validIndex, to: AddModel.shape)
try interpreter.allocateTensors()
try interpreter.copy(AddModel.inputData, toInputAt: AddModel.validIndex)
}
private func setUpAddQuantizedModelInputTensor() throws {
precondition(interpreter != nil)
try interpreter.resizeInput(at: AddQuantizedModel.inputOutputIndex, to: AddQuantizedModel.shape)
try interpreter.allocateTensors()
try interpreter.copy(AddQuantizedModel.inputData, toInputAt: AddQuantizedModel.inputOutputIndex)
}
private func assertEqualErrors(actual: Error, expected: InterpreterError) {
guard let actual = actual as? InterpreterError else {
XCTFail("Actual error should be of type InterpreterError.")
return
}
XCTAssertEqual(actual, expected)
}
}
class InterpreterOptionsTests: XCTestCase {
func testInitWithDefaultValues() {
let options = Interpreter.Options()
XCTAssertNil(options.threadCount)
XCTAssertFalse(options.isXNNPackEnabled)
}
func testInitWithCustomValues() {
var options = Interpreter.Options()
options.threadCount = 2
XCTAssertEqual(options.threadCount, 2)
options.isXNNPackEnabled = false
XCTAssertFalse(options.isXNNPackEnabled)
options.isXNNPackEnabled = true
XCTAssertTrue(options.isXNNPackEnabled)
}
func testEquatable() {
var options1 = Interpreter.Options()
var options2 = Interpreter.Options()
XCTAssertEqual(options1, options2)
options1.threadCount = 2
options2.threadCount = 2
XCTAssertEqual(options1, options2)
options2.threadCount = 3
XCTAssertNotEqual(options1, options2)
options2.threadCount = 2
XCTAssertEqual(options1, options2)
options2.isXNNPackEnabled = true
XCTAssertNotEqual(options1, options2)
options1.isXNNPackEnabled = true
XCTAssertEqual(options1, options2)
}
}
// MARK: - Constants
/// Values for the `add.bin` model.
enum AddModel {
static let info = (name: "add", extension: "bin")
static let inputTensorCount = 1
static let outputTensorCount = 1
static let invalidIndex = 1
static let validIndex = 0
static let shape: Tensor.Shape = [2]
static let dataCount = inputData.count
static let inputData = Data(copyingBufferOf: [Float32(1.0), Float32(3.0)])
static let outputData = Data(copyingBufferOf: [Float32(3.0), Float32(9.0)])
static let results = [Float32(3.0), Float32(9.0)]
static let inputTensor = Tensor(
name: "input",
dataType: .float32,
shape: shape,
data: inputData
)
static let outputTensor = Tensor(
name: "output",
dataType: .float32,
shape: shape,
data: outputData
)
static var path: String = {
let bundle = Bundle(for: InterpreterTests.self)
guard let path = bundle.path(forResource: info.name, ofType: info.extension) else { return "" }
return path
}()
}
/// Values for the `add_quantized.bin` model.
enum AddQuantizedModel {
static let info = (name: "add_quantized", extension: "bin")
static let inputOutputIndex = 0
static let shape: Tensor.Shape = [2]
static let inputData = Data([1, 3])
static let outputData = Data([3, 9])
static let quantizationParameters = QuantizationParameters(scale: 0.003922, zeroPoint: 0)
static let results: [UInt8] = [3, 9]
static let inputTensor = Tensor(
name: "input",
dataType: .uInt8,
shape: shape,
data: inputData,
quantizationParameters: quantizationParameters
)
static let outputTensor = Tensor(
name: "output",
dataType: .uInt8,
shape: shape,
data: outputData,
quantizationParameters: quantizationParameters
)
static var path: String = {
let bundle = Bundle(for: InterpreterTests.self)
guard let path = bundle.path(forResource: info.name, ofType: info.extension) else { return "" }
return path
}()
}
// MARK: - Extensions
extension Array {
/// Creates a new array from the bytes of the given unsafe data.
///
/// - Warning: The array's `Element` type must be trivial in that it can be copied bit for bit
/// with no indirection or reference-counting operations; otherwise, copying the raw bytes in
/// the `unsafeData`'s buffer to a new array returns an unsafe copy.
/// - Note: Returns `nil` if `unsafeData.count` is not a multiple of
/// `MemoryLayout<Element>.stride`.
/// - Parameter unsafeData: The data containing the bytes to turn into an array.
init?(unsafeData: Data) {
guard unsafeData.count % MemoryLayout<Element>.stride == 0 else { return nil }
#if swift(>=5.0)
self = unsafeData.withUnsafeBytes { .init($0.bindMemory(to: Element.self)) }
#else
self = unsafeData.withUnsafeBytes {
.init(
UnsafeBufferPointer<Element>(
start: $0,
count: unsafeData.count / MemoryLayout<Element>.stride
))
}
#endif // swift(>=5.0)
}
}
extension Data {
/// Creates a new buffer by copying the buffer pointer of the given array.
///
/// - Warning: The given array's element type `T` must be trivial in that it can be copied bit
/// for bit with no indirection or reference-counting operations; otherwise, reinterpreting
/// data from the resulting buffer has undefined behavior.
/// - Parameter array: An array with elements of type `T`.
init<T>(copyingBufferOf array: [T]) {
self = array.withUnsafeBufferPointer(Data.init)
}
}
@@ -0,0 +1,114 @@
// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
@testable import TensorFlowLite
class MetalDelegateTests: XCTestCase {
func testInitDefaultGPUDelegateOptions() {
let delegate = MetalDelegate()
XCTAssertFalse(delegate.options.isPrecisionLossAllowed)
XCTAssertEqual(delegate.options.waitType, .passive)
}
func testInitWithCustomGPUDelegateOptions() {
var options = MetalDelegate.Options()
options.isPrecisionLossAllowed = true
options.waitType = .active
let delegate = MetalDelegate(options: options)
XCTAssertTrue(delegate.options.isPrecisionLossAllowed)
XCTAssertEqual(delegate.options.waitType, .active)
}
func testInitInterpreterWithDelegate() throws {
// If metal device is not available, skip.
if MTLCreateSystemDefaultDevice() == nil {
return
}
let metalDelegate = MetalDelegate()
let interpreter = try Interpreter(modelPath: MultiAddModel.path, delegates: [metalDelegate])
XCTAssertEqual(interpreter.delegates?.count, 1)
XCTAssertNil(interpreter.options)
}
func testInitInterpreterWithOptionsAndDelegate() throws {
// If metal device is not available, skip.
if MTLCreateSystemDefaultDevice() == nil {
return
}
var options = Interpreter.Options()
options.threadCount = 1
let metalDelegate = MetalDelegate()
let interpreter = try Interpreter(
modelPath: MultiAddModel.path,
options: options,
delegates: [metalDelegate]
)
XCTAssertNotNil(interpreter.options)
XCTAssertEqual(interpreter.delegates?.count, 1)
}
}
class MetalDelegateOptionsTests: XCTestCase {
func testInitWithDefaultValues() {
let options = MetalDelegate.Options()
XCTAssertFalse(options.isPrecisionLossAllowed)
XCTAssertEqual(options.waitType, .passive)
}
func testInitWithCustomValues() {
var options = MetalDelegate.Options()
options.isPrecisionLossAllowed = true
options.waitType = .active
XCTAssertTrue(options.isPrecisionLossAllowed)
XCTAssertEqual(options.waitType, .active)
}
func testEquatable() {
var options1 = MetalDelegate.Options()
var options2 = MetalDelegate.Options()
XCTAssertEqual(options1, options2)
options1.isPrecisionLossAllowed = true
options2.isPrecisionLossAllowed = true
XCTAssertEqual(options1, options2)
options1.waitType = .none
options2.waitType = .none
XCTAssertEqual(options1, options2)
options2.isPrecisionLossAllowed = false
XCTAssertNotEqual(options1, options2)
options1.isPrecisionLossAllowed = false
options1.waitType = .aggressive
XCTAssertNotEqual(options1, options2)
}
}
/// Values for the `multi_add.bin` model.
enum MultiAddModel {
static let info = (name: "multi_add", extension: "bin")
static var path: String = {
let bundle = Bundle(for: MetalDelegateTests.self)
guard let path = bundle.path(forResource: info.name, ofType: info.extension) else { return "" }
return path
}()
}
@@ -0,0 +1,72 @@
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
@testable import TensorFlowLite
class ModelTests: XCTestCase {
var modelPath: String!
override func setUp() {
super.setUp()
let bundle = Bundle(for: type(of: self))
guard
let modelPath = bundle.path(
forResource: Constant.modelInfo.name,
ofType: Constant.modelInfo.extension
)
else {
XCTFail("Failed to get the model file path.")
return
}
self.modelPath = modelPath
}
override func tearDown() {
modelPath = nil
super.tearDown()
}
func testInitWithFilePath() {
let model = Model(filePath: modelPath)
XCTAssertNotNil(model)
XCTAssertNotNil(model?.cModel)
XCTAssertNil(model?.data)
}
func testInitWithEmptyFilePath_FailsInitialization() {
XCTAssertNil(Model(filePath: ""))
}
func testInitWithInvalidFilePath_FailsInitialization() {
XCTAssertNil(Model(filePath: "invalid/path"))
}
func testInitWithData() throws {
let model = Model(modelData: try Data(contentsOf: URL(fileURLWithPath: modelPath)))
XCTAssertNotNil(model)
XCTAssertNotNil(model?.cModel)
XCTAssertNotNil(model?.data)
}
}
// MARK: - Constants
private enum Constant {
static let modelInfo = (name: "add", extension: "bin")
}
@@ -0,0 +1,36 @@
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
@testable import TensorFlowLite
class QuantizationParametersTests: XCTestCase {
func testInitWithCustomValues() {
let parameters = QuantizationParameters(scale: 0.5, zeroPoint: 1)
XCTAssertEqual(parameters.scale, 0.5)
XCTAssertEqual(parameters.zeroPoint, 1)
}
func testEquatable() {
let parameters1 = QuantizationParameters(scale: 0.5, zeroPoint: 1)
let parameters2 = QuantizationParameters(scale: 0.5, zeroPoint: 1)
XCTAssertEqual(parameters1, parameters2)
let parameters3 = QuantizationParameters(scale: 0.4, zeroPoint: 1)
XCTAssertNotEqual(parameters1, parameters3)
XCTAssertNotEqual(parameters2, parameters3)
}
}
@@ -0,0 +1,141 @@
// Copyright 2022 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
@testable import TensorFlowLite
class SignatureRunnerTest: XCTestCase {
func testSignatureKeys() throws {
let interpreter = try Interpreter(modelPath: MultiSignaturesModel.path)
XCTAssertEqual(interpreter.signatureKeys, MultiSignaturesModel.signatureKeys)
XCTAssertNotNil(try interpreter.signatureRunner(with: MultiSignaturesModel.AddSignature.key))
XCTAssertThrowsError(try interpreter.signatureRunner(with: "dummy")) { error in
self.assertEqualErrors(
actual: error, expected: .failedToCreateSignatureRunner(signatureKey: "dummy"))
}
}
func testResizeInputTensor() throws {
let interpreter = try Interpreter(modelPath: MultiSignaturesModel.path)
let addRunner = try interpreter.signatureRunner(with: MultiSignaturesModel.AddSignature.key)
XCTAssertEqual(addRunner.inputs, MultiSignaturesModel.AddSignature.inputs)
let inputTensor = try addRunner.input(named: "x")
// Validate signature "add" input tensor "x" before resizing.
XCTAssertEqual(inputTensor.name, MultiSignaturesModel.AddSignature.inputTensor.name)
XCTAssertEqual(inputTensor.dataType, MultiSignaturesModel.AddSignature.inputTensor.dataType)
XCTAssertEqual(inputTensor.shape, [1])
// Test fail to copy data before resizing the tensor
XCTAssertThrowsError(
try addRunner.copy(MultiSignaturesModel.AddSignature.inputData, toInputNamed: "x")
) { error in
self.assertEqualErrors(
actual: error, expected: .invalidTensorDataCount(provided: 8, required: 4))
}
// Resize signature "add" input tensor "x"
try addRunner.resizeInput(named: "x", toShape: MultiSignaturesModel.AddSignature.shape)
try addRunner.allocateTensors()
// Copy data to input tensor "x"
try addRunner.copy(MultiSignaturesModel.AddSignature.inputData, toInputNamed: "x")
// Validate signature "add" input tensor "x" after resizing and copying data.
XCTAssertEqual(
try addRunner.input(named: "x"), MultiSignaturesModel.AddSignature.inputTensor)
}
func testResizeInputTensor_invalidTensor() throws {
let interpreter = try Interpreter(modelPath: MultiSignaturesModel.path)
let addRunner = try interpreter.signatureRunner(with: MultiSignaturesModel.AddSignature.key)
// Test fail to get input tensor for a dummy input name.
XCTAssertThrowsError(
try addRunner.input(named: "dummy")
) { error in
self.assertEqualErrors(
actual: error, expected: .failedToGetTensor(tensorType: "input", nameInSignature: "dummy"))
}
// Test fail to resize dummy input tensor
XCTAssertThrowsError(
try addRunner.resizeInput(named: "dummy", toShape: [2])
) { error in
self.assertEqualErrors(
actual: error, expected: .failedToResizeInputTensor(inputName: "dummy"))
}
}
func testInvokeWithInputs() throws {
let interpreter = try Interpreter(modelPath: MultiSignaturesModel.path)
let addRunner = try interpreter.signatureRunner(with: MultiSignaturesModel.AddSignature.key)
XCTAssertEqual(addRunner.outputs, MultiSignaturesModel.AddSignature.outputs)
// Validate signature "add" output tensor "output_0" before inference
let outputTensor = try addRunner.output(named: "output_0")
XCTAssertEqual(outputTensor.name, MultiSignaturesModel.AddSignature.outputTensor.name)
XCTAssertEqual(outputTensor.dataType, MultiSignaturesModel.AddSignature.outputTensor.dataType)
XCTAssertEqual(outputTensor.shape, [1])
// Resize signature "add" input tensor "x"
try addRunner.resizeInput(named: "x", toShape: MultiSignaturesModel.AddSignature.shape)
// Invoke signature "add" with inputs.
try addRunner.invoke(with: ["x": MultiSignaturesModel.AddSignature.inputData])
// Validate signature "add" output tensor "output_0" after inference
XCTAssertEqual(
try addRunner.output(named: "output_0"), MultiSignaturesModel.AddSignature.outputTensor)
}
// MARK: - Private
private func assertEqualErrors(actual: Error, expected: SignatureRunnerError) {
guard let actual = actual as? SignatureRunnerError else {
XCTFail("Actual error should be of type SignatureRunnerError.")
return
}
XCTAssertEqual(actual, expected)
}
}
// MARK: - Constants
/// Values for the `multi_signatures.bin` model.
enum MultiSignaturesModel {
static let info = (name: "multi_signatures", extension: "bin")
static let signatureKeys = [AddSignature.key, SubSignature.key]
static var path: String = {
let bundle = Bundle(for: SignatureRunnerTest.self)
guard let path = bundle.path(forResource: info.name, ofType: info.extension) else { return "" }
return path
}()
enum AddSignature {
static let key = "add"
static let inputs = ["x"]
static let outputs = ["output_0"]
static let inputData = Data(copyingBufferOf: [Float32(2.0), Float32(4.0)])
static let outputData = Data(copyingBufferOf: [Float32(4.0), Float32(6.0)])
static let shape: Tensor.Shape = [2]
static let inputTensor = Tensor(
name: "add_x:0",
dataType: .float32,
shape: shape,
data: inputData
)
static let outputTensor = Tensor(
name: "StatefulPartitionedCall:0",
dataType: .float32,
shape: shape,
data: outputData
)
}
enum SubSignature {
static let key = "sub"
}
}
@@ -0,0 +1,29 @@
// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
@testable import TensorFlowLite
class TensorFlowLiteTests: XCTestCase {
func testRuntime_Version() {
#if swift(>=5.0)
let pattern = #"^(\d+)\.(\d+)\.(\d+)([+-][-.0-9A-Za-z]+)?(\+\w+)?$"#
#else
let pattern = "^(\\d+)\\.(\\d+)\\.(\\d+)([+-][-.0-9A-Za-z]+)?(\\+\\w+)?$"
#endif // swift(>=5.0)
XCTAssertNotNil(TensorFlowLite.Runtime.version.range(of: pattern, options: .regularExpression))
}
}
@@ -0,0 +1,109 @@
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
@testable import TensorFlowLite
class TensorTests: XCTestCase {
func testInit() {
let name = "InputTensor"
let dataType: Tensor.DataType = .uInt8
let shape = Tensor.Shape(Constant.dimensions)
guard let data = name.data(using: .utf8) else { XCTFail("Data should not be nil."); return }
let quantizationParameters = QuantizationParameters(scale: 0.5, zeroPoint: 1)
let inputTensor = Tensor(
name: name,
dataType: dataType,
shape: shape,
data: data,
quantizationParameters: quantizationParameters
)
XCTAssertEqual(inputTensor.name, name)
XCTAssertEqual(inputTensor.dataType, dataType)
XCTAssertEqual(inputTensor.shape, shape)
XCTAssertEqual(inputTensor.data, data)
XCTAssertEqual(inputTensor.quantizationParameters, quantizationParameters)
}
func testEquatable() {
let name = "Tensor"
let dataType: Tensor.DataType = .uInt8
let shape = Tensor.Shape(Constant.dimensions)
guard let data = name.data(using: .utf8) else { XCTFail("Data should not be nil."); return }
let quantizationParameters = QuantizationParameters(scale: 0.5, zeroPoint: 1)
let tensor1 = Tensor(
name: name,
dataType: dataType,
shape: shape,
data: data,
quantizationParameters: quantizationParameters
)
var tensor2 = Tensor(
name: name,
dataType: dataType,
shape: shape,
data: data,
quantizationParameters: quantizationParameters
)
XCTAssertEqual(tensor1, tensor2)
tensor2 = Tensor(
name: "Tensor2",
dataType: dataType,
shape: shape,
data: data,
quantizationParameters: quantizationParameters
)
XCTAssertNotEqual(tensor1, tensor2)
}
}
class TensorShapeTests: XCTestCase {
func testInitWithArray() {
let shape = Tensor.Shape(Constant.dimensions)
XCTAssertEqual(shape.rank, Constant.dimensions.count)
XCTAssertEqual(shape.dimensions, Constant.dimensions)
}
func testInitWithElements() {
let shape = Tensor.Shape(2, 2, 3)
XCTAssertEqual(shape.rank, Constant.dimensions.count)
XCTAssertEqual(shape.dimensions, Constant.dimensions)
}
func testInitWithArrayLiteral() {
let shape: Tensor.Shape = [2, 2, 3]
XCTAssertEqual(shape.rank, Constant.dimensions.count)
XCTAssertEqual(shape.dimensions, Constant.dimensions)
}
func testEquatable() {
let shape1 = Tensor.Shape(2, 2, 3)
var shape2: Tensor.Shape = [2, 2, 3]
XCTAssertEqual(shape1, shape2)
shape2 = [2, 2, 4]
XCTAssertNotEqual(shape1, shape2)
}
}
// MARK: - Constants
private enum Constant {
/// Array of 2 arrays of 2 arrays of 3 numbers: [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]].
static let dimensions = [2, 2, 3]
}