blob: 35b2dc87fcea74d3390ddd1934ba0e4233335e49 [file] [log] [blame]
/*
* Copyright 2012 ZXing authors
*
* 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 "AbstractNegativeBlackBoxTestCase.h"
@interface NegativeTestResult : NSObject
@property (nonatomic, assign) int falsePositivesAllowed;
@property (nonatomic, assign) float rotation;
@end
@implementation NegativeTestResult
- (id)initWithFalsePositivesAllowed:(int)falsePositivesAllowed rotation:(float)rotation {
if (self = [super init]) {
_falsePositivesAllowed = falsePositivesAllowed;
_rotation = rotation;
}
return self;
}
@end
@implementation AbstractNegativeBlackBoxTestCase
// Use the multiformat reader to evaluate all decoders in the system.
- (id)initWithInvocation:(NSInvocation *)invocation testBasePathSuffix:(NSString *)testBasePathSuffix {
if (self = [super initWithInvocation:invocation testBasePathSuffix:testBasePathSuffix barcodeReader:[[ZXMultiFormatReader alloc] init] expectedFormat:0]) {
self.testResults = [NSMutableArray array];
}
return self;
}
- (void)addTest:(int)falsePositivesAllowed rotation:(float)rotation {
[self.testResults addObject:[[NegativeTestResult alloc] initWithFalsePositivesAllowed:falsePositivesAllowed rotation:rotation]];
}
- (NSString *)pathInBundle:(NSURL *)file {
NSInteger startOfResources = [[file path] rangeOfString:@"Resources"].location;
if (startOfResources == NSNotFound) {
return [file path];
} else {
return [[file path] substringFromIndex:startOfResources];
}
}
- (void)runTests {
if (self.testResults.count == 0) {
STFail(@"No test results");
}
NSArray *imageFiles = [self imageFiles];
int falsePositives[self.testResults.count];
memset(falsePositives, 0, self.testResults.count * sizeof(int));
for (NSURL *testImage in imageFiles) {
NSLog(@"Starting %@", [self pathInBundle:testImage]);
ZXImage *image = [[ZXImage alloc] initWithURL:testImage];
for (int x = 0; x < self.testResults.count; x++) {
NegativeTestResult *testResult = self.testResults[x];
if (![self checkForFalsePositives:image rotationInDegrees:testResult.rotation]) {
falsePositives[x]++;
}
}
}
int totalFalsePositives = 0;
int totalAllowed = 0;
for (int x = 0; x < self.testResults.count; x++) {
NegativeTestResult *testResult = self.testResults[x];
totalFalsePositives += falsePositives[x];
totalAllowed += testResult.falsePositivesAllowed;
}
if (totalFalsePositives < totalAllowed) {
NSLog(@" +++ Test too lax by %d images", totalAllowed - totalFalsePositives);
} else if (totalFalsePositives > totalAllowed) {
NSLog(@" --- Test failed by %d images", totalFalsePositives - totalAllowed);
}
for (int x = 0; x < self.testResults.count; x++) {
NegativeTestResult *testResult = self.testResults[x];
NSLog(@"Rotation %d degrees: %d of %d images were false positives (%d allowed)",
(int)testResult.rotation, falsePositives[x], (int)imageFiles.count,
testResult.falsePositivesAllowed);
STAssertTrue(falsePositives[x] <= testResult.falsePositivesAllowed,
@"Rotation %f degrees: Too many false positives found", testResult.rotation);
}
}
/**
* Make sure ZXing does NOT find a barcode in the image.
*/
- (BOOL)checkForFalsePositives:(ZXImage *)image rotationInDegrees:(CGFloat)rotationInDegrees {
ZXImage *rotatedImage = [self rotateImage:image degrees:rotationInDegrees];
ZXLuminanceSource *source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:rotatedImage.cgimage];
ZXBinaryBitmap *bitmap = [[ZXBinaryBitmap alloc] initWithBinarizer:[[ZXHybridBinarizer alloc] initWithSource:source]];
NSError *error = nil;
ZXResult *result = [self.barcodeReader decode:bitmap error:&error];
if (result) {
NSLog(@"Found false positive: '%@' with format '%@' (rotation: %d)",
result.text, [AbstractBlackBoxTestCase barcodeFormatAsString:result.barcodeFormat], (int) rotationInDegrees);
return NO;
}
// Try "try harder" getMode
ZXDecodeHints *hints = [ZXDecodeHints hints];
hints.tryHarder = YES;
result = [self.barcodeReader decode:bitmap hints:hints error:&error];
if (result) {
NSLog(@"Try harder found false positive: '%@' with format '%@' (rotation: %d)",
result.text, [AbstractBlackBoxTestCase barcodeFormatAsString:result.barcodeFormat], (int) rotationInDegrees);
return NO;
}
return YES;
}
@end