appium-webdriveragent 3.9.2 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PrivateHeaders/.DS_Store +0 -0
- package/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +3 -0
- package/README.md +0 -1
- package/WebDriverAgent.xcodeproj/project.pbxproj +56 -56
- package/WebDriverAgent.xcodeproj/project.xcworkspace/xcuserdata/elf.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +51 -0
- package/WebDriverAgent.xcodeproj/xcuserdata/{kazuaki.xcuserdatad → elf.xcuserdatad}/xcschemes/xcschememanagement.plist +23 -8
- package/WebDriverAgentLib/.DS_Store +0 -0
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +0 -17
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +0 -16
- package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +28 -14
- package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h +37 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +51 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +8 -2
- package/WebDriverAgentLib/Commands/FBElementCommands.m +3 -1
- package/WebDriverAgentLib/Commands/FBOrientationCommands.m +20 -9
- package/WebDriverAgentLib/Commands/FBSessionCommands.m +119 -99
- package/WebDriverAgentLib/FBApplication.m +1 -1
- package/WebDriverAgentLib/Routing/FBElementCache.m +42 -11
- package/WebDriverAgentLib/Routing/FBResponsePayload.m +9 -3
- package/WebDriverAgentLib/Routing/FBSession.h +6 -0
- package/WebDriverAgentLib/Routing/FBSession.m +45 -55
- package/WebDriverAgentLib/Utilities/FBAlertsMonitor.h +1 -3
- package/WebDriverAgentLib/Utilities/FBAlertsMonitor.m +6 -13
- package/WebDriverAgentLib/Utilities/FBCapabilities.h +23 -0
- package/WebDriverAgentLib/Utilities/FBCapabilities.m +23 -0
- package/WebDriverAgentLib/Utilities/FBConfiguration.m +6 -1
- package/WebDriverAgentLib/Utilities/FBScreenshot.m +125 -14
- package/WebDriverAgentLib/Utilities/FBSettings.h +23 -23
- package/WebDriverAgentLib/Utilities/FBSettings.m +23 -23
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +16 -0
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +16 -0
- package/WebDriverAgentLib/Utilities/FBXPath.m +15 -44
- package/WebDriverAgentLib/Utilities/LRUCache/.DS_Store +0 -0
- package/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h +59 -0
- package/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m +104 -0
- package/WebDriverAgentLib/Utilities/LRUCache/LRUCacheNode.h +43 -0
- package/WebDriverAgentLib/Utilities/LRUCache/LRUCacheNode.m +59 -0
- package/WebDriverAgentLib/Vendor/.DS_Store +0 -0
- package/WebDriverAgentRunner/.DS_Store +0 -0
- package/WebDriverAgentRunner-Runner.app.zip +0 -0
- package/WebDriverAgentTests/IntegrationApp/Resources/.DS_Store +0 -0
- package/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +20 -16
- package/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +2 -1
- package/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +11 -0
- package/WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.h +3 -0
- package/WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.m +15 -0
- package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +1 -0
- package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +1 -0
- package/WebDriverAgentTests/UnitTests/FBSessionTests.m +11 -1
- package/WebDriverAgentTests/UnitTests/FBXPathTests.m +3 -1
- package/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h +1 -0
- package/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.m +1 -0
- package/package.json +3 -3
- package/WebDriverAgent.xcodeproj/project.xcworkspace/xcuserdata/kazuaki.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/WebDriverAgent.xcodeproj/project.xcworkspace/xcuserdata/kazuaki.xcuserdatad/WorkspaceSettings.xcsettings +0 -20
- package/WebDriverAgent.xcodeproj/xcuserdata/kazuaki.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -906
- package/WebDriverAgentLib/Vendor/YYCache/YYCache.h +0 -206
- package/WebDriverAgentLib/Vendor/YYCache/YYCache.m +0 -140
- package/WebDriverAgentLib/Vendor/YYCache/YYDiskCache.h +0 -412
- package/WebDriverAgentLib/Vendor/YYCache/YYDiskCache.m +0 -462
- package/WebDriverAgentLib/Vendor/YYCache/YYKVStorage.h +0 -325
- package/WebDriverAgentLib/Vendor/YYCache/YYKVStorage.m +0 -1068
- package/WebDriverAgentLib/Vendor/YYCache/YYMemoryCache.h +0 -213
- package/WebDriverAgentLib/Vendor/YYCache/YYMemoryCache.m +0 -508
|
@@ -13,30 +13,30 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
13
13
|
|
|
14
14
|
// See FBConfiguration.h for more details on the meaning of each setting
|
|
15
15
|
|
|
16
|
-
extern NSString* const
|
|
17
|
-
extern NSString* const
|
|
18
|
-
extern NSString* const
|
|
19
|
-
extern NSString* const
|
|
20
|
-
extern NSString* const
|
|
21
|
-
extern NSString* const
|
|
22
|
-
extern NSString* const
|
|
23
|
-
extern NSString* const
|
|
16
|
+
extern NSString* const FB_SETTING_USE_COMPACT_RESPONSES;
|
|
17
|
+
extern NSString* const FB_SETTING_ELEMENT_RESPONSE_ATTRIBUTES;
|
|
18
|
+
extern NSString* const FB_SETTING_MJPEG_SERVER_SCREENSHOT_QUALITY;
|
|
19
|
+
extern NSString* const FB_SETTING_MJPEG_SERVER_FRAMERATE;
|
|
20
|
+
extern NSString* const FB_SETTING_MJPEG_SCALING_FACTOR;
|
|
21
|
+
extern NSString* const FB_SETTING_SCREENSHOT_QUALITY;
|
|
22
|
+
extern NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION;
|
|
23
|
+
extern NSString* const FB_SETTING_KEYBOARD_PREDICTION;
|
|
24
24
|
// This setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead
|
|
25
|
-
extern NSString* const
|
|
26
|
-
extern NSString* const
|
|
27
|
-
extern NSString* const
|
|
28
|
-
extern NSString* const
|
|
29
|
-
extern NSString* const
|
|
30
|
-
extern NSString* const
|
|
31
|
-
extern NSString* const
|
|
32
|
-
extern NSString* const
|
|
33
|
-
extern NSString* const
|
|
34
|
-
extern NSString* const
|
|
35
|
-
extern NSString* const
|
|
36
|
-
extern NSString* const
|
|
37
|
-
extern NSString* const
|
|
38
|
-
extern NSString* const
|
|
39
|
-
extern NSString* const
|
|
25
|
+
extern NSString* const FB_SETTING_SNAPSHOT_TIMEOUT;
|
|
26
|
+
extern NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT;
|
|
27
|
+
extern NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH;
|
|
28
|
+
extern NSString* const FB_SETTING_USE_FIRST_MATCH;
|
|
29
|
+
extern NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX;
|
|
30
|
+
extern NSString* const FB_SETTING_REDUCE_MOTION;
|
|
31
|
+
extern NSString* const FB_SETTING_DEFAULT_ACTIVE_APPLICATION;
|
|
32
|
+
extern NSString* const FB_SETTING_ACTIVE_APP_DETECTION_POINT;
|
|
33
|
+
extern NSString* const FB_SETTING_INCLUDE_NON_MODAL_ELEMENTS;
|
|
34
|
+
extern NSString* const FB_SETTING_DEFAULT_ALERT_ACTION;
|
|
35
|
+
extern NSString* const FB_SETTING_ACCEPT_ALERT_BUTTON_SELECTOR;
|
|
36
|
+
extern NSString* const FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR;
|
|
37
|
+
extern NSString* const FB_SETTING_SCREENSHOT_ORIENTATION;
|
|
38
|
+
extern NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT;
|
|
39
|
+
extern NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT;
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
NS_ASSUME_NONNULL_END
|
|
@@ -9,26 +9,26 @@
|
|
|
9
9
|
|
|
10
10
|
#import "FBSettings.h"
|
|
11
11
|
|
|
12
|
-
NSString* const
|
|
13
|
-
NSString* const
|
|
14
|
-
NSString* const
|
|
15
|
-
NSString* const
|
|
16
|
-
NSString* const
|
|
17
|
-
NSString* const
|
|
18
|
-
NSString* const
|
|
19
|
-
NSString* const
|
|
20
|
-
NSString* const
|
|
21
|
-
NSString* const
|
|
22
|
-
NSString* const
|
|
23
|
-
NSString* const
|
|
24
|
-
NSString* const
|
|
25
|
-
NSString* const
|
|
26
|
-
NSString* const
|
|
27
|
-
NSString* const
|
|
28
|
-
NSString* const
|
|
29
|
-
NSString* const
|
|
30
|
-
NSString* const
|
|
31
|
-
NSString* const
|
|
32
|
-
NSString* const
|
|
33
|
-
NSString* const
|
|
34
|
-
NSString* const
|
|
12
|
+
NSString* const FB_SETTING_USE_COMPACT_RESPONSES = @"shouldUseCompactResponses";
|
|
13
|
+
NSString* const FB_SETTING_ELEMENT_RESPONSE_ATTRIBUTES = @"elementResponseAttributes";
|
|
14
|
+
NSString* const FB_SETTING_MJPEG_SERVER_SCREENSHOT_QUALITY = @"mjpegServerScreenshotQuality";
|
|
15
|
+
NSString* const FB_SETTING_MJPEG_SERVER_FRAMERATE = @"mjpegServerFramerate";
|
|
16
|
+
NSString* const FB_SETTING_MJPEG_SCALING_FACTOR = @"mjpegScalingFactor";
|
|
17
|
+
NSString* const FB_SETTING_SCREENSHOT_QUALITY = @"screenshotQuality";
|
|
18
|
+
NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION = @"keyboardAutocorrection";
|
|
19
|
+
NSString* const FB_SETTING_KEYBOARD_PREDICTION = @"keyboardPrediction";
|
|
20
|
+
NSString* const FB_SETTING_SNAPSHOT_TIMEOUT = @"snapshotTimeout";
|
|
21
|
+
NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT = @"customSnapshotTimeout";
|
|
22
|
+
NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH = @"snapshotMaxDepth";
|
|
23
|
+
NSString* const FB_SETTING_USE_FIRST_MATCH = @"useFirstMatch";
|
|
24
|
+
NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX = @"boundElementsByIndex";
|
|
25
|
+
NSString* const FB_SETTING_REDUCE_MOTION = @"reduceMotion";
|
|
26
|
+
NSString* const FB_SETTING_DEFAULT_ACTIVE_APPLICATION = @"defaultActiveApplication";
|
|
27
|
+
NSString* const FB_SETTING_ACTIVE_APP_DETECTION_POINT = @"activeAppDetectionPoint";
|
|
28
|
+
NSString* const FB_SETTING_INCLUDE_NON_MODAL_ELEMENTS = @"includeNonModalElements";
|
|
29
|
+
NSString* const FB_SETTING_DEFAULT_ALERT_ACTION = @"defaultAlertAction";
|
|
30
|
+
NSString* const FB_SETTING_ACCEPT_ALERT_BUTTON_SELECTOR = @"acceptAlertButtonSelector";
|
|
31
|
+
NSString* const FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR = @"dismissAlertButtonSelector";
|
|
32
|
+
NSString* const FB_SETTING_SCREENSHOT_ORIENTATION = @"screenshotOrientation";
|
|
33
|
+
NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT = @"waitForIdleTimeout";
|
|
34
|
+
NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT = @"animationCoolOffTimeout";
|
|
@@ -10,6 +10,22 @@
|
|
|
10
10
|
#import <WebDriverAgentLib/WebDriverAgentLib.h>
|
|
11
11
|
#import "XCPointerEvent.h"
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
The version of testmanagerd process which is running on the device.
|
|
15
|
+
|
|
16
|
+
Potentially, we can handle processes based on this version instead of iOS versions,
|
|
17
|
+
iOS 10.1 -> 6
|
|
18
|
+
iOS 11.0.1 -> 18
|
|
19
|
+
iOS 11.4 -> 22
|
|
20
|
+
iOS 12.1, 12.4 -> 26
|
|
21
|
+
iOS 13.0, 13.4.1 -> 28
|
|
22
|
+
|
|
23
|
+
tvOS 13.3 -> 28
|
|
24
|
+
|
|
25
|
+
@return The version of testmanagerd
|
|
26
|
+
*/
|
|
27
|
+
NSInteger FBTestmanagerdVersion(void);
|
|
28
|
+
|
|
13
29
|
NS_ASSUME_NONNULL_BEGIN
|
|
14
30
|
|
|
15
31
|
/**
|
|
@@ -193,3 +193,19 @@ static dispatch_once_t onceAppWithPIDToken;
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
@end
|
|
196
|
+
|
|
197
|
+
NSInteger FBTestmanagerdVersion(void)
|
|
198
|
+
{
|
|
199
|
+
static dispatch_once_t getTestmanagerdVersion;
|
|
200
|
+
static NSInteger testmanagerdVersion;
|
|
201
|
+
dispatch_once(&getTestmanagerdVersion, ^{
|
|
202
|
+
id<XCTestManager_ManagerInterface> proxy = [FBXCTestDaemonsProxy testRunnerProxy];
|
|
203
|
+
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
|
|
204
|
+
[proxy _XCT_exchangeProtocolVersion:testmanagerdVersion reply:^(unsigned long long code) {
|
|
205
|
+
testmanagerdVersion = (NSInteger) code;
|
|
206
|
+
dispatch_semaphore_signal(sem);
|
|
207
|
+
}];
|
|
208
|
+
dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)));
|
|
209
|
+
});
|
|
210
|
+
return testmanagerdVersion;
|
|
211
|
+
}
|
|
@@ -136,7 +136,9 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
136
136
|
xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
|
|
137
137
|
xmlFreeTextWriter(writer);
|
|
138
138
|
xmlFreeDoc(doc);
|
|
139
|
-
|
|
139
|
+
NSString *result = [NSString stringWithCString:(const char *)xmlbuff encoding:NSUTF8StringEncoding];
|
|
140
|
+
xmlFree(xmlbuff);
|
|
141
|
+
return result;
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
+ (NSArray<XCElementSnapshot *> *)matchesWithRootElement:(id<FBElement>)root forQuery:(NSString *)xpathQuery
|
|
@@ -183,7 +185,7 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
183
185
|
return @[];
|
|
184
186
|
}
|
|
185
187
|
NSMutableArray *matchingSnapshots = [NSMutableArray array];
|
|
186
|
-
const xmlChar *indexPathKeyName =
|
|
188
|
+
const xmlChar *indexPathKeyName = (xmlChar *)[kXMLIndexPathKey UTF8String];
|
|
187
189
|
for (NSInteger i = 0; i < nodeSet->nodeNr; i++) {
|
|
188
190
|
xmlNodePtr currentNode = nodeSet->nodeTab[i];
|
|
189
191
|
xmlChar *attrValue = xmlGetProp(currentNode, indexPathKeyName);
|
|
@@ -195,6 +197,7 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
195
197
|
if (element) {
|
|
196
198
|
[matchingSnapshots addObject:element];
|
|
197
199
|
}
|
|
200
|
+
xmlFree(attrValue);
|
|
198
201
|
}
|
|
199
202
|
return matchingSnapshots.copy;
|
|
200
203
|
}
|
|
@@ -263,37 +266,6 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
263
266
|
return 0;
|
|
264
267
|
}
|
|
265
268
|
|
|
266
|
-
+ (xmlChar *)xmlCharPtrForInput:(const char *)input
|
|
267
|
-
{
|
|
268
|
-
if (0 == input) {
|
|
269
|
-
return NULL;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
xmlCharEncodingHandlerPtr handler = xmlFindCharEncodingHandler(_UTF8Encoding);
|
|
273
|
-
if (!handler) {
|
|
274
|
-
[FBLogger log:@"Failed to invoke libxml2>xmlFindCharEncodingHandler"];
|
|
275
|
-
return NULL;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
int size = (int) strlen(input) + 1;
|
|
279
|
-
int outputSize = size * 2 - 1;
|
|
280
|
-
xmlChar *output = (unsigned char *) xmlMalloc((size_t) outputSize);
|
|
281
|
-
|
|
282
|
-
if (0 != output) {
|
|
283
|
-
int temp = size - 1;
|
|
284
|
-
int ret = handler->input(output, &outputSize, (const xmlChar *) input, &temp);
|
|
285
|
-
if ((ret < 0) || (temp - size + 1)) {
|
|
286
|
-
xmlFree(output);
|
|
287
|
-
output = 0;
|
|
288
|
-
} else {
|
|
289
|
-
output = (unsigned char *) xmlRealloc(output, outputSize + 1);
|
|
290
|
-
output[outputSize] = 0;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return output;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
269
|
+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery document:(xmlDocPtr)doc
|
|
298
270
|
{
|
|
299
271
|
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
|
|
@@ -303,7 +275,7 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
303
275
|
}
|
|
304
276
|
xpathCtx->node = doc->children;
|
|
305
277
|
|
|
306
|
-
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(
|
|
278
|
+
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar *)[xpathQuery UTF8String], xpathCtx);
|
|
307
279
|
if (NULL == xpathObj) {
|
|
308
280
|
xmlXPathFreeContext(xpathCtx);
|
|
309
281
|
[FBLogger logFmt:@"Failed to invoke libxml2>xmlXPathEvalExpression for XPath query \"%@\"", xpathQuery];
|
|
@@ -313,14 +285,9 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
313
285
|
return xpathObj;
|
|
314
286
|
}
|
|
315
287
|
|
|
316
|
-
+ (
|
|
288
|
+
+ (nullable NSString *)safeXmlStringWithString:(NSString *)str
|
|
317
289
|
{
|
|
318
|
-
|
|
319
|
-
return NULL;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
NSString *safeString = [str fb_xmlSafeStringWithReplacement:@""];
|
|
323
|
-
return [self.class xmlCharPtrForInput:[safeString cStringUsingEncoding:NSUTF8StringEncoding]];
|
|
290
|
+
return [str fb_xmlSafeStringWithReplacement:@""];
|
|
324
291
|
}
|
|
325
292
|
|
|
326
293
|
+ (int)recordElementAttributes:(xmlTextWriterPtr)writer forElement:(XCElementSnapshot *)element indexPath:(nullable NSString *)indexPath includedAttributes:(nullable NSSet<Class> *)includedAttributes
|
|
@@ -374,7 +341,7 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
374
341
|
[elementStore setObject:currentSnapshot forKey:topNodeIndexPath];
|
|
375
342
|
}
|
|
376
343
|
|
|
377
|
-
int rc = xmlTextWriterStartElement(writer,
|
|
344
|
+
int rc = xmlTextWriterStartElement(writer, (xmlChar *)[currentSnapshot.wdType UTF8String]);
|
|
378
345
|
if (rc < 0) {
|
|
379
346
|
[FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterStartElement for the tag value '%@'. Error code: %d", currentSnapshot.wdType, rc];
|
|
380
347
|
return rc;
|
|
@@ -447,7 +414,9 @@ static NSString *const FBAbstractMethodInvocationException = @"AbstractMethodInv
|
|
|
447
414
|
// Skip the attribute if the value equals to nil
|
|
448
415
|
return 0;
|
|
449
416
|
}
|
|
450
|
-
int rc = xmlTextWriterWriteAttribute(writer,
|
|
417
|
+
int rc = xmlTextWriterWriteAttribute(writer,
|
|
418
|
+
(xmlChar *)[[FBXPath safeXmlStringWithString:[self name]] UTF8String],
|
|
419
|
+
(xmlChar *)[[FBXPath safeXmlStringWithString:value] UTF8String]);
|
|
451
420
|
if (rc < 0) {
|
|
452
421
|
[FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterWriteAttribute(%@='%@'). Error code: %d", [self name], value, rc];
|
|
453
422
|
}
|
|
@@ -672,7 +641,9 @@ static NSString *const FBAbstractMethodInvocationException = @"AbstractMethodInv
|
|
|
672
641
|
// Skip the attribute if the value equals to nil
|
|
673
642
|
return 0;
|
|
674
643
|
}
|
|
675
|
-
int rc = xmlTextWriterWriteAttribute(writer,
|
|
644
|
+
int rc = xmlTextWriterWriteAttribute(writer,
|
|
645
|
+
(xmlChar *)[[FBXPath safeXmlStringWithString:[self name]] UTF8String],
|
|
646
|
+
(xmlChar *)[[FBXPath safeXmlStringWithString:value] UTF8String]);
|
|
676
647
|
if (rc < 0) {
|
|
677
648
|
[FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterWriteAttribute(%@='%@'). Error code: %d", [self name], value, rc];
|
|
678
649
|
}
|
|
Binary file
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* See the NOTICE file distributed with this work for additional
|
|
5
|
+
* information regarding copyright ownership.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#import <Foundation/Foundation.h>
|
|
18
|
+
|
|
19
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
20
|
+
|
|
21
|
+
@interface LRUCache : NSObject
|
|
22
|
+
|
|
23
|
+
/*! Maximum cache capacity. Could only be set in the constructor */
|
|
24
|
+
@property (nonatomic, readonly) NSUInteger capacity;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
Constructs a new LRU cache instance with the given capacity
|
|
28
|
+
|
|
29
|
+
@param capacity Maximum cache capacity
|
|
30
|
+
*/
|
|
31
|
+
- (instancetype)initWithCapacity:(NSUInteger)capacity;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
Puts a new object into the cache. nil cannot be stored in the cache.
|
|
35
|
+
|
|
36
|
+
@param object Object to put
|
|
37
|
+
@param key Object's key
|
|
38
|
+
*/
|
|
39
|
+
- (void)setObject:(id)object forKey:(id<NSCopying>)key;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
Retrieves an object from the cache. Every time this method is called the matched
|
|
43
|
+
object is bumped in the cache (if exists)
|
|
44
|
+
|
|
45
|
+
@param key Object's key
|
|
46
|
+
@returns Either the stored instance or nil if the object does not exist or has expired
|
|
47
|
+
*/
|
|
48
|
+
- (nullable id)objectForKey:(id<NSCopying>)key;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
Retrieves all values from the cache. No bump is performed
|
|
52
|
+
|
|
53
|
+
@return Array of all cache values
|
|
54
|
+
*/
|
|
55
|
+
- (NSArray *)allObjects;
|
|
56
|
+
|
|
57
|
+
@end
|
|
58
|
+
|
|
59
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* See the NOTICE file distributed with this work for additional
|
|
5
|
+
* information regarding copyright ownership.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#import "LRUCache.h"
|
|
18
|
+
#import "LRUCacheNode.h"
|
|
19
|
+
|
|
20
|
+
@interface LRUCache ()
|
|
21
|
+
@property (nonatomic) NSMutableDictionary *store;
|
|
22
|
+
@property (nonatomic, nullable) LRUCacheNode *headNode;
|
|
23
|
+
@property (nonatomic, nullable) LRUCacheNode *tailNode;
|
|
24
|
+
@property (nonatomic) NSUInteger size;
|
|
25
|
+
@end
|
|
26
|
+
|
|
27
|
+
@implementation LRUCache
|
|
28
|
+
|
|
29
|
+
- (instancetype)initWithCapacity:(NSUInteger)capacity
|
|
30
|
+
{
|
|
31
|
+
if ((self = [super init])) {
|
|
32
|
+
_store = [NSMutableDictionary dictionary];
|
|
33
|
+
_capacity = capacity;
|
|
34
|
+
}
|
|
35
|
+
return self;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (void)setObject:(id)object forKey:(id<NSCopying>)key
|
|
39
|
+
{
|
|
40
|
+
NSAssert(nil != object, @"LRUCache cannot store nil objects");
|
|
41
|
+
|
|
42
|
+
LRUCacheNode *previousNode = self.store[key];
|
|
43
|
+
LRUCacheNode *newNode = [LRUCacheNode nodeWithValue:object key:key];
|
|
44
|
+
self.store[key] = newNode;
|
|
45
|
+
if (nil == previousNode) {
|
|
46
|
+
++self.size;
|
|
47
|
+
}
|
|
48
|
+
if (previousNode == self.tailNode) {
|
|
49
|
+
self.tailNode = newNode;
|
|
50
|
+
}
|
|
51
|
+
if (previousNode == self.headNode) {
|
|
52
|
+
self.headNode = newNode;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
[self bumpNode:newNode];
|
|
56
|
+
[self alignSize];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
- (id)objectForKey:(id<NSCopying>)key
|
|
60
|
+
{
|
|
61
|
+
LRUCacheNode *node = self.store[key];
|
|
62
|
+
if (nil != node) {
|
|
63
|
+
[self bumpNode:node];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return node.value;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
- (NSArray *)allObjects
|
|
70
|
+
{
|
|
71
|
+
return (NSArray *)[self.store.allValues valueForKeyPath:@"value"];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
- (void)bumpNode:(LRUCacheNode *)node
|
|
75
|
+
{
|
|
76
|
+
if (node == self.headNode) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (node == self.tailNode) {
|
|
81
|
+
self.tailNode = self.tailNode.prev;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
self.headNode.prev.next = node.next;
|
|
85
|
+
|
|
86
|
+
LRUCacheNode *prevHead = self.headNode;
|
|
87
|
+
self.headNode = node;
|
|
88
|
+
self.headNode.next = prevHead;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
- (void)alignSize
|
|
92
|
+
{
|
|
93
|
+
if (self.size <= self.capacity) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
LRUCacheNode *nextTail = self.tailNode.prev;
|
|
98
|
+
[self.store removeObjectForKey:(id)self.tailNode.key];
|
|
99
|
+
self.tailNode = nextTail;
|
|
100
|
+
self.tailNode.next = nil;
|
|
101
|
+
--self.size;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* See the NOTICE file distributed with this work for additional
|
|
5
|
+
* information regarding copyright ownership.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#import <Foundation/Foundation.h>
|
|
18
|
+
|
|
19
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
20
|
+
|
|
21
|
+
@interface LRUCacheNode : NSObject
|
|
22
|
+
|
|
23
|
+
/*! Node value */
|
|
24
|
+
@property (nonatomic, readonly) id value;
|
|
25
|
+
/*! Node key */
|
|
26
|
+
@property (nonatomic, readonly) id<NSCopying> key;
|
|
27
|
+
/*! Pointer to the next node */
|
|
28
|
+
@property (nonatomic, nullable) LRUCacheNode *next;
|
|
29
|
+
/*! Pointer to the previous node */
|
|
30
|
+
@property (nonatomic, nullable) LRUCacheNode *prev;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
Factory method to create a new cache node with the given value and key
|
|
34
|
+
|
|
35
|
+
@param value Node value
|
|
36
|
+
@param key Node key
|
|
37
|
+
@returns Cache node instance
|
|
38
|
+
*/
|
|
39
|
+
+ (instancetype)nodeWithValue:(id)value key:(id<NSCopying>)key;
|
|
40
|
+
|
|
41
|
+
@end
|
|
42
|
+
|
|
43
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* See the NOTICE file distributed with this work for additional
|
|
5
|
+
* information regarding copyright ownership.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#import "LRUCacheNode.h"
|
|
18
|
+
|
|
19
|
+
@interface LRUCacheNode ()
|
|
20
|
+
@property (nonatomic, readwrite) id value;
|
|
21
|
+
@property (nonatomic, readwrite) id<NSCopying> key;
|
|
22
|
+
|
|
23
|
+
- (instancetype)initWithValue:(id)value key:(id<NSCopying>)key;
|
|
24
|
+
@end
|
|
25
|
+
|
|
26
|
+
@implementation LRUCacheNode
|
|
27
|
+
|
|
28
|
+
- (instancetype)initWithValue:(id)value key:(id<NSCopying>)key
|
|
29
|
+
{
|
|
30
|
+
if (nil == value) {
|
|
31
|
+
return nil;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if ((self = [super init])) {
|
|
35
|
+
_value = value;
|
|
36
|
+
_key = key;
|
|
37
|
+
}
|
|
38
|
+
return self;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
+ (instancetype)nodeWithValue:(id)value key:(id<NSCopying>)key
|
|
42
|
+
{
|
|
43
|
+
return [[LRUCacheNode alloc] initWithValue:value key:key];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
- (NSString *)description
|
|
47
|
+
{
|
|
48
|
+
return [NSString stringWithFormat:@"%@ %@", self.value, self.next];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
- (void)setNext:(LRUCacheNode *)next
|
|
52
|
+
{
|
|
53
|
+
if (_next != next) {
|
|
54
|
+
_next = next;
|
|
55
|
+
next.prev = self;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -19,8 +19,6 @@
|
|
|
19
19
|
|
|
20
20
|
@interface FBSession (Tests)
|
|
21
21
|
|
|
22
|
-
@property (nonatomic) NSDictionary<NSString *, FBApplication *> *applications;
|
|
23
|
-
|
|
24
22
|
@end
|
|
25
23
|
|
|
26
24
|
@interface FBSessionIntegrationTests : FBIntegrationTestCase
|
|
@@ -36,7 +34,14 @@ static NSString *const SETTINGS_BUNDLE_ID = @"com.apple.Preferences";
|
|
|
36
34
|
{
|
|
37
35
|
[super setUp];
|
|
38
36
|
[self launchApplication];
|
|
39
|
-
|
|
37
|
+
FBApplication *app = [[FBApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID];
|
|
38
|
+
self.session = [FBSession initWithApplication:app];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
- (void)tearDown
|
|
42
|
+
{
|
|
43
|
+
[self.session kill];
|
|
44
|
+
[super tearDown];
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
- (void)testSettingsAppCanBeOpenedInScopeOfTheCurrentSession
|
|
@@ -46,28 +51,28 @@ static NSString *const SETTINGS_BUNDLE_ID = @"com.apple.Preferences";
|
|
|
46
51
|
shouldWaitForQuiescence:nil
|
|
47
52
|
arguments:nil
|
|
48
53
|
environment:nil];
|
|
49
|
-
|
|
54
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
|
|
50
55
|
XCTAssertEqual([self.session applicationStateWithBundleId:SETTINGS_BUNDLE_ID], 4);
|
|
51
56
|
[self.session activateApplicationWithBundleId:testedApp.bundleID];
|
|
52
|
-
|
|
57
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString: testedApp.bundleID]);
|
|
53
58
|
XCTAssertEqual([self.session applicationStateWithBundleId:testedApp.bundleID], 4);
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
- (void)testSettingsAppCanBeReopenedInScopeOfTheCurrentSession
|
|
57
62
|
{
|
|
58
|
-
FBApplication *systemApp =
|
|
63
|
+
FBApplication *systemApp = self.springboard;
|
|
59
64
|
[self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID
|
|
60
65
|
shouldWaitForQuiescence:nil
|
|
61
66
|
arguments:nil
|
|
62
67
|
environment:nil];
|
|
63
|
-
FBAssertWaitTillBecomesTrue([
|
|
68
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
|
|
64
69
|
XCTAssertTrue([self.session terminateApplicationWithBundleId:SETTINGS_BUNDLE_ID]);
|
|
65
70
|
FBAssertWaitTillBecomesTrue([systemApp.bundleID isEqualToString:self.session.activeApplication.bundleID]);
|
|
66
71
|
[self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID
|
|
67
72
|
shouldWaitForQuiescence:nil
|
|
68
73
|
arguments:nil
|
|
69
74
|
environment:nil];
|
|
70
|
-
|
|
75
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
- (void)testMainAppCanBeReactivatedInScopeOfTheCurrentSession
|
|
@@ -77,28 +82,27 @@ static NSString *const SETTINGS_BUNDLE_ID = @"com.apple.Preferences";
|
|
|
77
82
|
shouldWaitForQuiescence:nil
|
|
78
83
|
arguments:nil
|
|
79
84
|
environment:nil];
|
|
80
|
-
|
|
85
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:SETTINGS_BUNDLE_ID]);
|
|
81
86
|
[self.session activateApplicationWithBundleId:testedApp.bundleID];
|
|
82
|
-
|
|
87
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]);
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
- (void)testMainAppCanBeRestartedInScopeOfTheCurrentSession
|
|
86
91
|
{
|
|
87
|
-
FBApplication *systemApp =
|
|
88
|
-
FBApplication *testedApp = FBApplication.
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
FBApplication *systemApp = self.springboard;
|
|
93
|
+
FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID];
|
|
94
|
+
[self.session terminateApplicationWithBundleId:testedApp.bundleID];
|
|
95
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:systemApp.bundleID]);
|
|
91
96
|
[self.session launchApplicationWithBundleId:testedApp.bundleID
|
|
92
97
|
shouldWaitForQuiescence:nil
|
|
93
98
|
arguments:nil
|
|
94
99
|
environment:nil];
|
|
95
|
-
|
|
100
|
+
FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]);
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
- (void)testLaunchUnattachedApp
|
|
99
104
|
{
|
|
100
105
|
[FBUnattachedAppLauncher launchAppWithBundleId:SETTINGS_BUNDLE_ID];
|
|
101
|
-
XCTAssertNil(self.session.applications[SETTINGS_BUNDLE_ID]);
|
|
102
106
|
[self.session kill];
|
|
103
107
|
XCTAssertEqualObjects(SETTINGS_BUNDLE_ID, FBApplication.fb_activeApplication.bundleID);
|
|
104
108
|
}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
#import "FBTestMacros.h"
|
|
18
18
|
#import "XCUIApplication+FBHelpers.h"
|
|
19
19
|
#import "XCUIElement+FBIsVisible.h"
|
|
20
|
+
#import "FBXCodeCompatibility.h"
|
|
20
21
|
|
|
21
22
|
@interface XCUIApplicationHelperTests : FBIntegrationTestCase
|
|
22
23
|
@end
|
|
@@ -90,7 +91,7 @@
|
|
|
90
91
|
|
|
91
92
|
- (void)testTestmanagerdVersion
|
|
92
93
|
{
|
|
93
|
-
XCTAssertGreaterThan(
|
|
94
|
+
XCTAssertGreaterThan(FBTestmanagerdVersion(), 0);
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
@end
|