Conversation
Allows test writers to completely clear all persistence locations in a single call, using default values for underlying methods
…g a default list of locations otherwise
Sources/FileManager+Testable.swift
Outdated
| for cacheItem in cacheItems { | ||
| do { | ||
| try self.removeItem(at: URL(fileURLWithPath: "\(url.relativePath)/\(cacheItem)")) | ||
| try self.removeItem(at: URL(fileURLWithPath: "Library/Caches/\(cacheItem.name)", isDirectory: cacheItem.isDirectory)) |
There was a problem hiding this comment.
Should this still be \(url.relativePath)/\(cacheItem) instead of hard coding to Library/Caches/?
There was a problem hiding this comment.
Sorry I wasn't sure if Library/Caches/ was equivalent to url.relativePath as I was referring to the Core cache clearing helper logic here: https://github.com/adobe/aepsdk-core-ios/blob/d91de55cd052b1141a5d78d4a4d433fb486c8fac/AEPServices/Mocks/DatastoreUtilities.swift#L31
I've reverted the change back to use the relativePath value instead
Sources/FileManager+Testable.swift
Outdated
| for cacheItem in cacheItems { | ||
| do { | ||
| try self.removeItem(at: URL(fileURLWithPath: "\(url.relativePath)/\(cacheItem)")) | ||
| try self.removeItem(at: URL(fileURLWithPath: "Library/Caches/\(cacheItem.name)", isDirectory: cacheItem.isDirectory)) |
There was a problem hiding this comment.
Per your comment on the logged errors, is it possible to check if the directory exists before attempting to delete it so an error isn't logged?
There was a problem hiding this comment.
Apple recommends against checking for file existing when predicating behavior: https://developer.apple.com/documentation/foundation/filemanager/1410277-fileexists
Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended. Doing so can cause odd behavior or race conditions. It’s far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed. For more information on file-system race conditions, see Race Conditions and Secure File Operations in Secure Coding Guide.
There was a problem hiding this comment.
Yes, saw this in the PR: adobe/aepsdk-core-ios#966, specifically:
adobe/aepsdk-core-ios#966 (comment)
So chose to emit an error log in this case, is this enough error handling or should we add more logic here?
There was a problem hiding this comment.
nit: the file names sometimes use "+Test" and sometimes use "+Testable". Is there a rhyme or reason for this? I'm wondering if it would be more clear to use "+TestApis" to specify these files just add APIs for testing?
There was a problem hiding this comment.
I think renaming the helper files that have the + (extensions) for consistency would be great!
@kevinlind are you ok with "+TestHelper"? I was thinking "+TestApis" could be interpreted as the file exposing or mocking existing APIs from the class for testing purposes - when it's actually providing helper methods that do testing setup/teardown etc?
|
Regarding question 2, |
Sources/FileManager+Testable.swift
Outdated
|
|
||
| guard let directoryUrl = directoryUrl else { | ||
| Log.error(label: LOG_TAG, "Could not compute the directory URL for removal.") | ||
| Log.error(label: LOG_TAG, "Could not compute the directory URL for \(directoryName) for removal.") |
There was a problem hiding this comment.
Github isn't letting me mark the name of the function as the line. But, can we change the name of the function. Technically, this function isn't clearing the "cache", it is clearing the fileSystemStorage which is actually found in the Library directory (not cache). As far as the implementation, have you tested that this actually clears all of the directories? The implementation in the Core helper is different currently. See here.
There was a problem hiding this comment.
What do you think of the name:
clearDirectory(_ name: String = "com.adobe.aep.datastore", inAppGroup appGroup: String? = nil)
Notes:
clearinstead ofremoveto align with the other helper methods that have similar functionality of clearing peristence values- Since this method is an extension on FileManager, hopefully just
clearDirectoryis enough context without includingfileSystemin the method name?
Please note that this will be a breaking change, so adopters of this change who have already migrated to use AEPTestUtils will have to update
As for the testing, that is something that was discussed - whether we want separate tests for the test utilities - but we decided against it in favor of having the extension test suites be the "tests" for the utilities working properly (for example, there are functional test cases in Edge that rely on the file system storage being cleared properly between test cases, otherwise they fail - which was used to validate this particular implementation)
What are your thoughts on this approach?
In terms of this particular file system removal implementation, the default args should follow the same logic as the current helper in Core, with the difference being that this one removes the directory altogether, and Core's removes each item in the directory, leaving the directory itself in place. However, this method also allows flexibility in terms of compatibility with app groups, so if extensions need to test that kind of environment the capability is available
timkimadobe
left a comment
There was a problem hiding this comment.
Thanks so much for the reviews @kevinlind and @cdhoffmann! Updated based on feedback, please let me know what you think
Sources/FileManager+Testable.swift
Outdated
| for cacheItem in cacheItems { | ||
| do { | ||
| try self.removeItem(at: URL(fileURLWithPath: "\(url.relativePath)/\(cacheItem)")) | ||
| try self.removeItem(at: URL(fileURLWithPath: "Library/Caches/\(cacheItem.name)", isDirectory: cacheItem.isDirectory)) |
There was a problem hiding this comment.
Sorry I wasn't sure if Library/Caches/ was equivalent to url.relativePath as I was referring to the Core cache clearing helper logic here: https://github.com/adobe/aepsdk-core-ios/blob/d91de55cd052b1141a5d78d4a4d433fb486c8fac/AEPServices/Mocks/DatastoreUtilities.swift#L31
I've reverted the change back to use the relativePath value instead
Sources/FileManager+Testable.swift
Outdated
| for cacheItem in cacheItems { | ||
| do { | ||
| try self.removeItem(at: URL(fileURLWithPath: "\(url.relativePath)/\(cacheItem)")) | ||
| try self.removeItem(at: URL(fileURLWithPath: "Library/Caches/\(cacheItem.name)", isDirectory: cacheItem.isDirectory)) |
There was a problem hiding this comment.
Yes, saw this in the PR: adobe/aepsdk-core-ios#966, specifically:
adobe/aepsdk-core-ios#966 (comment)
So chose to emit an error log in this case, is this enough error handling or should we add more logic here?
Sources/FileManager+Testable.swift
Outdated
|
|
||
| guard let directoryUrl = directoryUrl else { | ||
| Log.error(label: LOG_TAG, "Could not compute the directory URL for removal.") | ||
| Log.error(label: LOG_TAG, "Could not compute the directory URL for \(directoryName) for removal.") |
There was a problem hiding this comment.
What do you think of the name:
clearDirectory(_ name: String = "com.adobe.aep.datastore", inAppGroup appGroup: String? = nil)
Notes:
clearinstead ofremoveto align with the other helper methods that have similar functionality of clearing peristence values- Since this method is an extension on FileManager, hopefully just
clearDirectoryis enough context without includingfileSystemin the method name?
Please note that this will be a breaking change, so adopters of this change who have already migrated to use AEPTestUtils will have to update
As for the testing, that is something that was discussed - whether we want separate tests for the test utilities - but we decided against it in favor of having the extension test suites be the "tests" for the utilities working properly (for example, there are functional test cases in Edge that rely on the file system storage being cleared properly between test cases, otherwise they fail - which was used to validate this particular implementation)
What are your thoughts on this approach?
In terms of this particular file system removal implementation, the default args should follow the same logic as the current helper in Core, with the difference being that this one removes the directory altogether, and Core's removes each item in the directory, leaving the directory itself in place. However, this method also allows flexibility in terms of compatibility with app groups, so if extensions need to test that kind of environment the capability is available
There was a problem hiding this comment.
I think renaming the helper files that have the + (extensions) for consistency would be great!
@kevinlind are you ok with "+TestHelper"? I was thinking "+TestApis" could be interpreted as the file exposing or mocking existing APIs from the class for testing purposes - when it's actually providing helper methods that do testing setup/teardown etc?
cdhoffmann
left a comment
There was a problem hiding this comment.
Looks great Tim. Thanks for resolving the comments.
Note
This PR also includes an important (unrelated to the features in this PR) bug fix for
MockNetworkServicedouble recording sent network requests.Description
This PR creates a new cache clearing helper as an extension to
NamedCollectionDataStore, calledclear(). The intent of the changes are:UserDefaultsmigration (iOS only))Modeled off of the Core implementation: https://github.com/adobe/aepsdk-core-ios/blob/d91de55cd052b1141a5d78d4a4d433fb486c8fac/AEPServices/Mocks/DatastoreUtilities.swift#L40
Changes
NamedCollectionDataStore.clear()- new method that uses the default args for all underlying calls:FileManager.clearCacheupdated to allow for passing custom list of cache locations andisDirectoryflag, with default locations if not specifiedQuestions for reviewers
NamedCollectionDataStore.clear()removes each item in the cache directory individually vs the entire top level cache directory; is that preferable to removing the entire"com.adobe.aep.datastore"directory?FileSystemNamedCollectionroute throughfindOrCreateAdobeSubdirectory, removal of the entire directory itself shouldn’t pose an issue?FileManagerclearCachealso usesServiceProvider.shared.dataQueueServiceand removes the key for each cache item name, is this required?FileManager.clearCachelist?Related Issue
Motivation and Context
How Has This Been Tested?
Screenshots (if appropriate):
Types of changes
Checklist: