Flutter Engine
 
Loading...
Searching...
No Matches
GoldenTestManager.m
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6#import <XCTest/XCTest.h>
7
8@interface GoldenTestManager ()
9
10@property(readwrite, strong, nonatomic) GoldenImage* goldenImage;
11
12@end
13
14@implementation GoldenTestManager
15
16NSDictionary* launchArgsMap;
17const double kDefaultRmseThreshold = 0.5;
18
19- (instancetype)initWithLaunchArg:(NSString*)launchArg {
20 self = [super init];
21 if (self) {
22 // The launchArgsMap should match the one in the `PlatformVieGoldenTestManager`.
23 static NSDictionary<NSString*, NSString*>* launchArgsMap;
24 static dispatch_once_t onceToken;
25 dispatch_once(&onceToken, ^{
26 launchArgsMap = @{
27 @"--platform-view" : @"platform_view",
28 @"--platform-view-multiple" : @"platform_view_multiple",
29 @"--platform-view-multiple-background-foreground" :
30 @"platform_view_multiple_background_foreground",
31 @"--platform-view-cliprect" : @"platform_view_cliprect",
32 @"--platform-view-cliprect-multiple-clips" : @"platform_view_cliprect_multiple_clips",
33 @"--platform-view-cliprrect" : @"platform_view_cliprrect",
34 @"--platform-view-cliprrect-multiple-clips" : @"platform_view_cliprrect_multiple_clips",
35 @"--platform-view-large-cliprrect" : @"platform_view_large_cliprrect",
36 @"--platform-view-large-cliprrect-multiple-clips" :
37 @"platform_view_large_cliprrect_multiple_clips",
38 @"--platform-view-clippath" : @"platform_view_clippath",
39 @"--platform-view-clippath-multiple-clips" : @"platform_view_clippath_multiple_clips",
40 @"--platform-view-cliprrect-with-transform" : @"platform_view_cliprrect_with_transform",
41 @"--platform-view-cliprrect-with-transform-multiple-clips" :
42 @"platform_view_cliprrect_with_transform_multiple_clips",
43 @"--platform-view-large-cliprrect-with-transform" :
44 @"platform_view_large_cliprrect_with_transform",
45 @"--platform-view-large-cliprrect-with-transform-multiple-clips" :
46 @"platform_view_large_cliprrect_with_transform_multiple_clips",
47 @"--platform-view-cliprect-with-transform" : @"platform_view_cliprect_with_transform",
48 @"--platform-view-cliprect-with-transform-multiple-clips" :
49 @"platform_view_cliprect_with_transform_multiple_clips",
50 @"--platform-view-clippath-with-transform" : @"platform_view_clippath_with_transform",
51 @"--platform-view-clippath-with-transform-multiple-clips" :
52 @"platform_view_clippath_with_transform_multiple_clips",
53 @"--platform-view-transform" : @"platform_view_transform",
54 @"--platform-view-opacity" : @"platform_view_opacity",
55 @"--platform-view-with-other-backdrop-filter" : @"platform_view_with_other_backdrop_filter",
56 @"--two-platform-views-with-other-backdrop-filter" :
57 @"two_platform_views_with_other_backdrop_filter",
58 @"--platform-view-with-negative-backdrop-filter" :
59 @"platform_view_with_negative_backdrop_filter",
60 @"--platform-view-rotate" : @"platform_view_rotate",
61 @"--non-full-screen-flutter-view-platform-view" :
62 @"non_full_screen_flutter_view_platform_view",
63 @"--bogus-font-text" : @"bogus_font_text",
64 @"--spawn-engine-works" : @"spawn_engine_works",
65 @"--platform-view-cliprect-after-moved" : @"platform_view_cliprect_after_moved",
66 @"--platform-view-cliprect-after-moved-multiple-clips" :
67 @"platform_view_cliprect_after_moved_multiple_clips",
68 @"--two-platform-view-clip-rect" : @"two_platform_view_clip_rect",
69 @"--two-platform-view-clip-rect-multiple-clips" :
70 @"two_platform_view_clip_rect_multiple_clips",
71 @"--two-platform-view-clip-rrect" : @"two_platform_view_clip_rrect",
72 @"--two-platform-view-clip-rrect-multiple-clips" :
73 @"two_platform_view_clip_rrect_multiple_clips",
74 @"--two-platform-view-clip-path" : @"two_platform_view_clip_path",
75 @"--two-platform-view-clip-path-multiple-clips" :
76 @"two_platform_view_clip_path_multiple_clips",
77 @"--app-extension" : @"app_extension",
78 @"--darwin-system-font" : @"darwin_system_font",
79 };
80 });
81 _identifier = launchArgsMap[launchArg];
82
83 NSString* impeller = @"impeller_";
84 NSNumber* enableImpeller = [[NSBundle bundleWithIdentifier:@"dev.flutter.Scenarios"]
85 objectForInfoDictionaryKey:@"FLTEnableImpeller"];
86 if (enableImpeller != nil && !enableImpeller.boolValue) {
87 impeller = @"";
88 NSLog(@"Testing Skia: FLTEnableImpeller is NO");
89 } else {
90 NSLog(@"Testing Impeller");
91 }
92
93 NSString* prefix = [NSString stringWithFormat:@"golden_%@_%@", _identifier, impeller];
94 _goldenImage = [[GoldenImage alloc] initWithGoldenNamePrefix:prefix];
95 _launchArg = launchArg;
96 }
97 return self;
98}
99
100- (void)checkGoldenForTest:(XCTestCase*)test rmesThreshold:(double)rmesThreshold {
101 XCUIScreenshot* screenshot = [[XCUIScreen mainScreen] screenshot];
102 if (!_goldenImage.image) {
103 XCTAttachment* attachment = [XCTAttachment attachmentWithScreenshot:screenshot];
104 attachment.name = [_goldenImage.goldenName stringByAppendingString:@"_new.png"];
105 attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
106 [test addAttachment:attachment];
107 // Instead of XCTFail because that definition changed between Xcode 11 and 12 whereas this impl
108 // is stable.
109 _XCTPrimitiveFail(test,
110 @"This test will fail - no golden named %@ found. "
111 @"Follow the steps in the README to add a new golden.",
112 _goldenImage.goldenName);
113 }
114
115 if (![_goldenImage compareGoldenToImage:screenshot.image rmesThreshold:rmesThreshold]) {
116 XCTAttachment* screenshotAttachment = [XCTAttachment attachmentWithImage:screenshot.image];
117 screenshotAttachment.name = [_goldenImage.goldenName stringByAppendingString:@"_actual.png"];
118 screenshotAttachment.lifetime = XCTAttachmentLifetimeKeepAlways;
119 [test addAttachment:screenshotAttachment];
120
121 _XCTPrimitiveFail(test,
122 @"Goldens do not match. Follow the steps in the "
123 @"README to update golden named %@ if needed.",
124 _goldenImage.goldenName);
125 }
126}
127
128@end
int64_t _identifier
NS_ASSUME_NONNULL_BEGIN NSDictionary * launchArgsMap
const double kDefaultRmseThreshold
NSDictionary * launchArgsMap
FlutterVulkanImage * image
GoldenImage * goldenImage