-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added classes for artifact collection and processing. Updated contras…
…t and toouch target checks for accuracy. Changed all private method names to include appropriate prefix. Added the following classes GTXArtifactCollector, GTXArtifactProcessor, GTXError, GTXReport, GTXSnapshotBuffer, GTXSnapshotContainer. Updated all prefixes of private methods from "_" to "gtx_" or "gtxtest_" for tests. Updated contrast check calculation accuracy. Updated touch target check to include frame as well as accessibility frame. And minot refactoring.
- Loading branch information
Showing
40 changed files
with
2,483 additions
and
502 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// | ||
// Copyright 2019 Google Inc. | ||
// | ||
// 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 <Foundation/Foundation.h> | ||
|
||
#import "GTXChecking.h" | ||
#import "GTXSnapshotContainer.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
/** | ||
* A class to streamline snapshot collection for a given set of checks. | ||
*/ | ||
@interface GTXArtifactCollector : NSObject | ||
|
||
/** | ||
* Initializes an artifact collector to work with the given set of @c checks. | ||
*/ | ||
- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks; | ||
|
||
/** | ||
* @return a snapshot container with all the artifact snapshots needed by the checks. This method | ||
* must only be invoked on the main thread to allow for UI related artifacts to be | ||
* collected. | ||
*/ | ||
- (GTXSnapshotContainer *)snapshot; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// | ||
// Copyright 2019 Google Inc. | ||
// | ||
// 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 <Foundation/Foundation.h> | ||
|
||
#import "GTXArtifactCollector.h" | ||
#import "GTXAssertions.h" | ||
|
||
@implementation GTXArtifactCollector { | ||
NSArray<Class<GTXArtifactImplementing>> *_artifactClasses; | ||
} | ||
|
||
- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks { | ||
self = [super init]; | ||
if (self) { | ||
// Get the set of all (unique) Artifact classes that the checks need. | ||
NSMutableSet *classes = [[NSMutableSet alloc] init]; | ||
for (id<GTXChecking> check in checks) { | ||
if ([check respondsToSelector:@selector(requiredArtifactClasses)]) { | ||
[classes addObjectsFromArray:[check requiredArtifactClasses]]; | ||
} | ||
} | ||
_artifactClasses = [classes allObjects]; | ||
} | ||
return self; | ||
} | ||
|
||
- (GTXSnapshotContainer *)snapshot { | ||
GTX_ASSERT([NSThread isMainThread], @"Snapshots cannot be taken on non-main threads"); | ||
NSMutableArray<id<GTXArtifactImplementing>> *snapshots = [[NSMutableArray alloc] init]; | ||
for (Class<GTXArtifactImplementing> cls in _artifactClasses) { | ||
id<GTXArtifactImplementing> snapshot = [cls createArtifactSnapshot]; | ||
GTX_ASSERT(snapshot, @"Could not fetch a snapshot"); | ||
[snapshots addObject:snapshot]; | ||
} | ||
return snapshots.count > 0 ? [[GTXSnapshotContainer alloc] initWithSnapshots:snapshots] : nil; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// | ||
// Copyright 2019 Google Inc. | ||
// | ||
// 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 <UIKit/UIKit.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
/** | ||
* A protocol that all artifacts must implement to ensure that snapshots can be taken. | ||
*/ | ||
@protocol GTXArtifactImplementing <NSObject> | ||
|
||
/** | ||
* @return a new snapshot object with data captured at the time of invocation. This method is only | ||
* invoked on the main thread. | ||
*/ | ||
+ (instancetype)createArtifactSnapshot; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// | ||
// Copyright 2019 Google Inc. | ||
// | ||
// 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 <Foundation/Foundation.h> | ||
|
||
#import "GTXChecking.h" | ||
#import "GTXSnapshotContainer.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
/** | ||
* A delegate protocol for listening to events occurring in the @c GTXArtifactProcessor. | ||
*/ | ||
@protocol GTXArtifactProcessorDelegate <NSObject> | ||
|
||
- (void)artifactProcessorDidProcessSnapshotContainer; | ||
- (void)artifactProcessorDidShutdown; | ||
|
||
@end | ||
|
||
typedef void (^GTXArtifactProcessorReportFetchBlock)(GTXReport *report); | ||
|
||
/** | ||
* An artifact processor which can process artifacts on background threads. | ||
*/ | ||
@interface GTXArtifactProcessor : NSObject | ||
|
||
/** | ||
* Use initWithChecks:delegate: instead. | ||
*/ | ||
- (instancetype)init NS_UNAVAILABLE; | ||
|
||
/** | ||
* Initializes a new artifact processor to work with the given set of checks. | ||
* | ||
* @param checks The checks to be performed on the snapshots. | ||
* @param delegate An optional delegate to recieve callback of checks processing. | ||
* | ||
* @return a new artifact processor. | ||
*/ | ||
- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks | ||
delegate:(nullable id<GTXArtifactProcessorDelegate>)delegate; | ||
|
||
/** | ||
* Starts a background thread to process the submitted snapshots. | ||
*/ | ||
- (void)startProcessing; | ||
|
||
/** | ||
* Stops the backgorund processing of snapshots, any snapshots submitted after this call may not | ||
* be processed. | ||
*/ | ||
- (void)stopProcessing; | ||
|
||
/** | ||
* Fetches the latest report held by the processor and invokes the given callback with it. | ||
* | ||
* @param fetchBlock A callback to invoke once the report is prepared. | ||
*/ | ||
- (void)fetchLatestReportAsync:(GTXArtifactProcessorReportFetchBlock)fetchBlock; | ||
|
||
/** | ||
* Adds a snapshot container into the artifact processor's internal buffer for processing. | ||
* | ||
* @param container The snapshot container to be processed. | ||
* | ||
* @return @c YES if the container was successfully added, @c NO otherwise. | ||
*/ | ||
- (BOOL)addSnapshotContainerForProcessing:(GTXSnapshotContainer *)container; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// | ||
// Copyright 2019 Google Inc. | ||
// | ||
// 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 "GTXArtifactProcessor.h" | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
#import "GTXAssertions.h" | ||
#import "GTXSnapshotBuffer.h" | ||
|
||
@implementation GTXArtifactProcessor { | ||
NSArray<id<GTXChecking>> *_checks; | ||
id<GTXArtifactProcessorDelegate> _delegate; | ||
volatile BOOL _isShuttingDown; | ||
GTXSnapshotBuffer *_buffer; | ||
GTXReport *_report; | ||
|
||
// GTXArtifactProcessor uses a command buffer model to deal with multi-threading: all | ||
// processing and its associated tasks enqueue as commands on a command queue and are executed | ||
// from it. @c _queueKey and @c _queueContext are used to ensure that commands related code is | ||
// only invoked from the command queue context. | ||
dispatch_queue_t _commandQueue; | ||
void *_queueKey, *_queueContext; | ||
} | ||
|
||
- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks | ||
delegate:(id<GTXArtifactProcessorDelegate>)delegate { | ||
self = [super init]; | ||
if (self) { | ||
_checks = checks; | ||
_delegate = delegate; | ||
_buffer = [[GTXSnapshotBuffer alloc] init]; | ||
} | ||
return self; | ||
} | ||
|
||
- (void)startProcessing { | ||
GTX_ASSERT(!_commandQueue, @"GTXArtifactProcessor was already started"); | ||
_report = [[GTXReport alloc] init]; | ||
_commandQueue = | ||
dispatch_queue_create("com.google.gtxilib.artifactprocessor", DISPATCH_QUEUE_SERIAL); | ||
_queueKey = &_queueKey; | ||
_queueContext = &_queueContext; | ||
dispatch_queue_set_specific(_commandQueue, _queueKey, _queueContext, NULL); | ||
} | ||
|
||
- (void)stopProcessing { | ||
__weak typeof(self) weakSelf = self; | ||
dispatch_async(_commandQueue, ^{ | ||
[weakSelf gtx_commandForProcessorShutdown]; | ||
}); | ||
} | ||
|
||
- (BOOL)addSnapshotContainerForProcessing:(GTXSnapshotContainer *)container { | ||
if (_isShuttingDown) { | ||
return NO; | ||
} | ||
[_buffer putSnapshotsContainer:container]; | ||
__weak typeof(self) wSelf = self; | ||
dispatch_async(_commandQueue, ^{ | ||
[wSelf gtx_commandForProcessingNextSnapshot]; | ||
}); | ||
return YES; | ||
} | ||
|
||
- (void)fetchLatestReportAsync:(GTXArtifactProcessorReportFetchBlock)fetchBlock { | ||
__weak typeof(self) weakSelf = self; | ||
dispatch_async(_commandQueue, ^{ | ||
[weakSelf gtx_commandForReportFetch:fetchBlock]; | ||
}); | ||
} | ||
|
||
#pragma mark - Artifact Processor Command Implementations | ||
|
||
- (void)gtx_assertCallerIsCommandQueue { | ||
void *context = dispatch_queue_get_specific(_commandQueue, _queueKey); | ||
GTX_ASSERT(context == _queueContext, @"This method can only be executed from command queue."); | ||
} | ||
|
||
- (void)gtx_commandForProcessingNextSnapshot { | ||
[self gtx_assertCallerIsCommandQueue]; | ||
if (_isShuttingDown) { | ||
return; | ||
} | ||
GTXSnapshotContainer *container = [_buffer getNextSnapshotsContainer]; | ||
if (container) { | ||
// Process this container and add errors to the report. | ||
for (id<GTXChecking> check in _checks) { | ||
if ([check respondsToSelector:@selector(performCheckOnSnapshot:addingErrorsToReport:)]) { | ||
[check performCheckOnSnapshot:container addingErrorsToReport:_report]; | ||
// @TODO: Consider adding all passing elements to the report as well, it might be useful to | ||
// look at all the elements that were scanned. | ||
} | ||
} | ||
__weak typeof(self) weakSelf = self; | ||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
typeof(self) strongSelf = weakSelf; | ||
if (strongSelf) { | ||
[strongSelf->_delegate artifactProcessorDidProcessSnapshotContainer]; | ||
} | ||
}); | ||
} | ||
} | ||
|
||
- (void)gtx_commandForProcessorShutdown { | ||
[self gtx_assertCallerIsCommandQueue]; | ||
_isShuttingDown = YES; | ||
__weak typeof(self) weakSelf = self; | ||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
typeof(self) strongSelf = weakSelf; | ||
if (strongSelf) { | ||
[strongSelf->_delegate artifactProcessorDidShutdown]; | ||
} | ||
}); | ||
} | ||
|
||
- (void)gtx_commandForReportFetch:(GTXArtifactProcessorReportFetchBlock)fetchBlock { | ||
[self gtx_assertCallerIsCommandQueue]; | ||
GTXReport *reportCopy = [_report copy]; | ||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
fetchBlock(reportCopy); | ||
}); | ||
} | ||
|
||
@end |
Oops, something went wrong.