142 lines
5.8 KiB
Swift
142 lines
5.8 KiB
Swift
// 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"
|
|
}
|
|
}
|