Files
tensorflow--tensorflow/tensorflow/lite/objc/tests/TFLSignatureRunnerTest.m
T
wehub-resource-sync 8a852e4b4e
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:14:16 +08:00

225 lines
9.4 KiB
Objective-C

// 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 "tensorflow/lite/objc/apis/TFLInterpreter.h"
#import "tensorflow/lite/objc/apis/TFLQuantizationParameters.h"
#import "tensorflow/lite/objc/apis/TFLSignatureRunner.h"
#import "tensorflow/lite/objc/apis/TFLTensor.h"
#import <XCTest/XCTest.h>
/** Multiple signatures model resource name. */
static NSString *const kMultiSignaturesModelResourceName = @"multi_signatures";
/** Model resource type. */
static NSString *const kModelResourceType = @"bin";
static NSString *const kAddSignatureKey = @"add";
static NSString *const kSubSignatureKey = @"sub";
static NSString *const kDummySignatureKey = @"dummy";
@interface TFLSignatureRunnerTest : XCTestCase
/** Absolute path of the multi-signature model resource. */
@property(nonatomic, nullable) NSString *multiSignaturesModelPath;
@end
@implementation TFLSignatureRunnerTest
- (void)setUp {
[super setUp];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
self.multiSignaturesModelPath = [bundle pathForResource:kMultiSignaturesModelResourceName
ofType:kModelResourceType];
}
- (void)tearDown {
self.multiSignaturesModelPath = nil;
[super tearDown];
}
- (void)testSignatureKeys {
NSError *error;
TFLInterpreter *interpreter =
[[TFLInterpreter alloc] initWithModelPath:self.multiSignaturesModelPath error:&error];
XCTAssertNil(error);
XCTAssertNotNil(interpreter);
NSArray<NSString *> *signatureKeys = interpreter.signatureKeys;
NSArray<NSString *> *expectedKeys = @[ kAddSignatureKey, kSubSignatureKey ];
XCTAssertTrue([signatureKeys isEqualToArray:expectedKeys]);
// Validate signature runner for "add" signature.
XCTAssertNotNil([interpreter signatureRunnerWithKey:kAddSignatureKey error:&error]);
XCTAssertNil(error);
// Test fail to get signature runner for dummy signature.
XCTAssertNil([interpreter signatureRunnerWithKey:kDummySignatureKey error:&error]);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, TFLSignatureRunnerErrorCodeFailedToCreateSignatureRunner);
}
- (void)testResizeInputTensor {
NSError *error;
TFLInterpreter *interpreter =
[[TFLInterpreter alloc] initWithModelPath:self.multiSignaturesModelPath error:&error];
TFLSignatureRunner *addRunner = [interpreter signatureRunnerWithKey:kAddSignatureKey
error:&error];
XCTAssertNil(error);
NSArray<NSString *> *expectedInputs = @[ @"x" ];
XCTAssertTrue([addRunner.inputs isEqualToArray:expectedInputs]);
// Validate signature "add" input tensor "x" before resizing.
TFLTensor *inputTensor = [addRunner inputTensorWithName:@"x" error:&error];
XCTAssertNotNil(inputTensor);
XCTAssertEqual(inputTensor.dataType, TFLTensorDataTypeFloat32);
XCTAssertTrue([[inputTensor shapeWithError:&error] isEqualToArray:@[ @(1) ]]);
XCTAssertNil(error);
XCTAssertEqual([inputTensor dataWithError:&error].length, 4U);
XCTAssertNil(error);
XCTAssertEqual(inputTensor.quantizationParameters.scale, 0.);
XCTAssertEqual(inputTensor.quantizationParameters.zeroPoint, 0U);
// Test fail to copy data before resizing the tensor
float inputs[2] = {2.f, 4.f};
NSData *inputData = [NSData dataWithBytes:&inputs length:(2 * sizeof(float))];
XCTAssertFalse([inputTensor copyData:inputData error:&error]);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, TFLSignatureRunnerErrorCodeInvalidInputByteSize);
error = nil;
// Resize signature "add" input tensor "x"
NSArray<NSNumber *> *newShape = @[ @(2) ];
XCTAssertTrue([addRunner resizeInputTensorWithName:@"x" toShape:newShape error:&error]);
XCTAssertNil(error);
XCTAssertTrue([addRunner allocateTensorsWithError:&error]);
XCTAssertNil(error);
// Validate signature "add" input tensor "x" after resizing.
inputTensor = [addRunner inputTensorWithName:@"x" error:&error];
XCTAssertNotNil(inputTensor);
XCTAssertEqual(inputTensor.dataType, TFLTensorDataTypeFloat32);
XCTAssertTrue([[inputTensor shapeWithError:&error] isEqualToArray:newShape]);
XCTAssertNil(error);
XCTAssertEqual([inputTensor dataWithError:&error].length, 8U);
XCTAssertNil(error);
XCTAssertEqual(inputTensor.quantizationParameters.scale, 0.);
XCTAssertEqual(inputTensor.quantizationParameters.zeroPoint, 0U);
// Validate input tensor "x" after copying data
XCTAssertTrue([inputTensor copyData:inputData error:&error]);
XCTAssertNil(error);
NSData *retrievedInputData = [inputTensor dataWithError:&error];
XCTAssertNil(error);
float retrievedInputs[2];
[retrievedInputData getBytes:&retrievedInputs length:retrievedInputData.length];
XCTAssertEqual(retrievedInputs[0], inputs[0]);
XCTAssertEqual(retrievedInputs[1], inputs[1]);
}
- (void)testResizeInputTensor_invalidTensor {
NSError *error;
TFLInterpreter *interpreter =
[[TFLInterpreter alloc] initWithModelPath:self.multiSignaturesModelPath error:&error];
TFLSignatureRunner *addRunner = [interpreter signatureRunnerWithKey:kAddSignatureKey
error:&error];
XCTAssertNil(error);
// Test fail to get input tensor for a dummy input name.
XCTAssertNil([addRunner inputTensorWithName:@"dummy" error:&error]);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, TFLSignatureRunnerErrorCodeFailedToGetTensor);
// Test fail to resize a dummy input tensor
error = nil;
XCTAssertFalse([addRunner resizeInputTensorWithName:@"dummy" toShape:@[ @(2) ] error:&error]);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, TFLSignatureRunnerErrorCodeFailedToResizeInputTensor);
}
- (void)testInvokeWithInputs {
NSError *error;
TFLInterpreter *interpreter =
[[TFLInterpreter alloc] initWithModelPath:self.multiSignaturesModelPath error:&error];
TFLSignatureRunner *addRunner = [interpreter signatureRunnerWithKey:kAddSignatureKey
error:&error];
XCTAssertNil(error);
// Validate signature "add" output tensor "output_0" before inference
NSArray<NSString *> *expectedOutputs = @[ @"output_0" ];
XCTAssertTrue([addRunner.outputs isEqualToArray:expectedOutputs]);
TFLTensor *outputTensor = [addRunner outputTensorWithName:@"output_0" error:&error];
XCTAssertNotNil(outputTensor);
XCTAssertEqual(outputTensor.dataType, TFLTensorDataTypeFloat32);
XCTAssertTrue([[outputTensor shapeWithError:&error] isEqualToArray:@[ @(1) ]]);
XCTAssertNil(error);
XCTAssertEqual([outputTensor dataWithError:&error].length, 4U);
XCTAssertNil(error);
XCTAssertEqual(outputTensor.quantizationParameters.scale, 0.);
XCTAssertEqual(outputTensor.quantizationParameters.zeroPoint, 0U);
// Resize signature "add" input tensor "x"
XCTAssertTrue([addRunner resizeInputTensorWithName:@"x" toShape:@[ @(2) ] error:&error]);
XCTAssertNil(error);
// Invoke signature "add" with inputs.
float inputs[2] = {2.f, 4.f};
NSData *inputData = [NSData dataWithBytes:&inputs length:(2 * sizeof(float))];
XCTAssertTrue([addRunner invokeWithInputs:@{@"x" : inputData} Error:&error]);
XCTAssertNil(error);
// Validate signature "add" output tensor "output_0" after inference
outputTensor = [addRunner outputTensorWithName:@"output_0" error:&error];
XCTAssertNotNil(outputTensor);
XCTAssertEqual(outputTensor.dataType, TFLTensorDataTypeFloat32);
XCTAssertTrue([[outputTensor shapeWithError:&error] isEqualToArray:@[ @(2) ]]);
XCTAssertNil(error);
XCTAssertEqual(outputTensor.quantizationParameters.scale, 0.);
XCTAssertEqual(outputTensor.quantizationParameters.zeroPoint, 0U);
NSData *outputData = [outputTensor dataWithError:&error];
XCTAssertNil(error);
XCTAssertEqual(outputData.length, 8U);
float outputs[2];
[outputData getBytes:&outputs length:outputData.length];
XCTAssertEqual(outputs[0], inputs[0] + 2.f);
XCTAssertEqual(outputs[1], inputs[1] + 2.f);
}
- (void)testInvokeWithInputs_invalidInputs {
NSError *error;
TFLInterpreter *interpreter =
[[TFLInterpreter alloc] initWithModelPath:self.multiSignaturesModelPath error:&error];
TFLSignatureRunner *addRunner = [interpreter signatureRunnerWithKey:kAddSignatureKey
error:&error];
XCTAssertNil(error);
// Invoke signature "add" with invalid input data.
float inputs[2] = {2.f, 4.f};
NSData *inputData = [NSData dataWithBytes:&inputs length:(2 * sizeof(float))];
XCTAssertFalse([addRunner invokeWithInputs:@{@"x" : inputData} Error:&error]);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, TFLSignatureRunnerErrorCodeInvalidInputByteSize);
// Invoke signature "add" with invalid input name.
error = nil;
float input = 2.f;
inputData = [NSData dataWithBytes:&input length:(1 * sizeof(float))];
XCTAssertFalse([addRunner invokeWithInputs:@{@"dummy" : inputData} Error:&error]);
XCTAssertNotNil(error);
XCTAssertEqual(error.code, TFLSignatureRunnerErrorCodeFailedToGetTensor);
}
@end