// // TestFastPath.m // IOHIDFamily // // Created by yg on 12/20/16. // // #import <XCTest/XCTest.h> #include "IOHIDUnitTestUtility.h" #include "IOHIDPrivateKeys.h" #import "IOHIDEventSystemTestController.h" #import "IOHIDUserDeviceTestController.h" #import "IOHIDDeviceTestController.h" #import "IOHIDUnitTestDescriptors.h" static NSString * deviceDescription = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" " <plist version=\"1.0\"> " " <dict> " " <key>VendorID</key> " " <integer>65280</integer> " " <key>ProductID</key> " " <integer>65280</integer> " " <key>ReportInterval</key> " " <integer>10000</integer> " " <key>RequestTimeout</key> " " <integer>5000000</integer> " " <key>UnitTestService</key> " " <true/> " " <key>Product</key> " " <string>10318C6F-6C4F-4B62-A8AB-4E706E9B50E0</string>" " </dict> " " </plist> "; static uint8_t descriptor[] = { HIDVendorMessage32BitDescriptor }; @interface TestFastPath : XCTestCase @property IOHIDUserDeviceTestController * sourceController; @property dispatch_queue_t eventControllerQueue; @property dispatch_queue_t rootQueue; @property NSString * uniqueID; @end @implementation TestFastPath - (void)setUp { [super setUp]; self.rootQueue = IOHIDUnitTestCreateRootQueue(31, 2); self.eventControllerQueue = dispatch_queue_create_with_target ("IOHIDEventSystemTestController", DISPATCH_QUEUE_SERIAL, self.rootQueue); HIDXCTAssertAndThrowTrue(self.eventControllerQueue != nil); NSData * descriptorData = [[NSData alloc] initWithBytes:descriptor length:sizeof(descriptor)]; self.uniqueID = [[[NSUUID alloc] init] UUIDString]; NSMutableDictionary* deviceConfig = [NSPropertyListSerialization propertyListWithData:[deviceDescription dataUsingEncoding:NSUTF8StringEncoding] options:NSPropertyListMutableContainers format:NULL error:NULL]; deviceConfig [@kIOHIDReportDescriptorKey] = descriptorData; deviceConfig [@kIOHIDPhysicalDeviceUniqueIDKey] = self.uniqueID; self.sourceController = [[IOHIDUserDeviceTestController alloc] initWithDeviceConfiguration:deviceConfig andQueue:nil]; HIDXCTAssertAndThrowTrue(self.sourceController != nil); } - (void)tearDown { [self.sourceController invalidate]; @autoreleasepool { self.sourceController = nil; } [super tearDown]; } - (void)CONDTIONAL_TEST_CASE(FastPathInit) { Boolean result; NSString *ioClassName; IOHIDEventSystemTestController * eventController = [[IOHIDEventSystemTestController alloc] initWithDeviceUniqueID:self.uniqueID AndQueue:self.eventControllerQueue]; HIDXCTAssertAndThrowTrue(eventController != nil); ioClassName = CFBridgingRelease(IOHIDServiceClientCopyProperty(eventController.eventService,CFSTR("IOClass"))); XCTAssertTrue (ioClassName && [ioClassName isEqualToString: @"IOHIDEventFastPathDriver"]); for (NSInteger index = 0; index < 10; index ++) { result = IOHIDServiceClientFastPathInit (eventController.eventService, NULL); XCTAssertTrue (result); IOHIDServiceClientFastPathInvalidate (eventController.eventService); } [eventController invalidate]; } - (void)CONDTIONAL_TEST_CASE(FastPathProperty) { Boolean result; CFTypeRef value; NSString *ioClassName; NSMutableArray *clients = [[NSMutableArray alloc] initWithCapacity:10]; for (NSUInteger index = 1 ; index < 10 ; index++) { IOHIDEventSystemTestController * eventController = [[IOHIDEventSystemTestController alloc] initWithDeviceUniqueID:self.uniqueID AndQueue:self.eventControllerQueue]; HIDXCTAssertAndThrowTrue(eventController != nil); [clients addObject:eventController]; ioClassName = CFBridgingRelease(IOHIDServiceClientCopyProperty(eventController.eventService,CFSTR("IOClass"))); HIDXCTAssertAndThrowTrue (ioClassName && [ioClassName isEqualToString: @"IOHIDEventFastPathDriver"]); NSNumber * clientIndex = [[NSNumber alloc] initWithLong:index]; NSDictionary * clientSpec = @{@"Client":clientIndex}; result = IOHIDServiceClientFastPathInit (eventController.eventService, (CFDictionaryRef)clientSpec); HIDXCTAssertAndThrowTrue (result); value = IOHIDServiceClientFastPathCopyProperty (eventController.eventService, CFSTR("Client")); XCTAssertTrue (value != NULL && CFEqual (value ,(CFNumberRef)clientIndex)); result = IOHIDServiceClientFastPathSetProperty (eventController.eventService, CFSTR("Test") , (CFNumberRef)clientIndex); XCTAssertTrue (result); value = IOHIDServiceClientFastPathCopyProperty (eventController.eventService, CFSTR("Test")); XCTAssertTrue (value != NULL && CFEqual (value ,(CFNumberRef)clientIndex)); [eventController invalidate]; } } - (void)CONDTIONAL_TEST_CASE(FastPathEventCopy) { Boolean result; NSString *ioClassName; __block IOHIDEventRef event; NSMutableArray *clients = [[NSMutableArray alloc] initWithCapacity:10]; for (NSUInteger index = 1 ; index < 10 ; index++) { IOHIDEventSystemTestController * eventController = [[IOHIDEventSystemTestController alloc] initWithDeviceUniqueID:self.uniqueID AndQueue:self.eventControllerQueue]; HIDXCTAssertAndThrowTrue(eventController != nil); [clients addObject:eventController]; ioClassName = CFBridgingRelease(IOHIDServiceClientCopyProperty(eventController.eventService,CFSTR("IOClass"))); HIDXCTAssertAndThrowTrue (ioClassName && [ioClassName isEqualToString: @"IOHIDEventFastPathDriver"]); result = IOHIDServiceClientFastPathInit (eventController.eventService, NULL); HIDXCTAssertAndThrowTrue (result); event = IOHIDServiceClientFastPathCopyEvent (eventController.eventService, NULL, 0); HIDXCTAssertAndThrowTrue (event != NULL); CFRelease (event); NSDictionary * dictCopySpec = @{@"NumberOfEventToCopy":@(index)}; event = IOHIDServiceClientFastPathCopyEvent (eventController.eventService, (__bridge CFDictionaryRef)dictCopySpec, 0); HIDXCTAssertAndThrowTrue (event != NULL); if (index > 1) { NSArray* children = (NSArray*)IOHIDEventGetChildren (event); XCTAssertTrue (children != NULL && children.count == index); } CFRelease (event); NSData * dataCopySpec = [NSData dataWithBytes: &index length:sizeof(index)]; event = IOHIDServiceClientFastPathCopyEvent (eventController.eventService, (__bridge CFDataRef)dataCopySpec, 0); HIDXCTAssertAndThrowTrue (event != NULL); if (index > 1) { NSArray* children = (NSArray*)IOHIDEventGetChildren (event); XCTAssertTrue (children != NULL && children.count == index); } CFRelease (event); [eventController invalidate]; } } - (void)CONDTIONAL_TEST_CASE(PerformanceOfCopyWithDictSpec) { Boolean result; IOHIDEventSystemTestController * eventController = [[IOHIDEventSystemTestController alloc] initWithDeviceUniqueID:self.uniqueID AndQueue:self.eventControllerQueue]; XCTAssertNotNil(eventController); result = IOHIDServiceClientFastPathInit (eventController.eventService, NULL); HIDXCTAssertAndThrowTrue (result); NSDictionary * copySpec = @{@"NumberOfEventToCopy":@(5)}; [self measureBlock:^{ IOHIDEventRef event = IOHIDServiceClientFastPathCopyEvent (eventController.eventService, (CFDictionaryRef)copySpec, 0); XCTAssertTrue (event != NULL); if (event) { CFRelease(event); } }]; [eventController invalidate]; } - (void)CONDTIONAL_TEST_CASE(PerformanceOfCopyWithNullSpec) { Boolean result; IOHIDEventSystemTestController * eventController = [[IOHIDEventSystemTestController alloc] initWithDeviceUniqueID:self.uniqueID AndQueue:self.eventControllerQueue]; HIDXCTAssertAndThrowTrue(eventController != nil); result = IOHIDServiceClientFastPathInit (eventController.eventService, NULL); XCTAssertTrue (result); [self measureBlock:^{ IOHIDEventRef event = IOHIDServiceClientFastPathCopyEvent (eventController.eventService, NULL, 0); XCTAssertTrue (event != NULL); if (event) { CFRelease(event); } }]; [eventController invalidate]; } - (void)CONDTIONAL_TEST_CASE(PerformanceOfCopyWithDataSpec) { Boolean result; IOHIDEventSystemTestController * eventController = [[IOHIDEventSystemTestController alloc] initWithDeviceUniqueID:self.uniqueID AndQueue:self.eventControllerQueue]; XCTAssertNotNil(eventController); result = IOHIDServiceClientFastPathInit (eventController.eventService, NULL); XCTAssertTrue (result); NSUInteger copyCount = 5; NSData * dataCopySpec = [NSData dataWithBytes: ©Count length:sizeof(copyCount)]; [self measureBlock:^{ IOHIDEventRef event = IOHIDServiceClientFastPathCopyEvent (eventController.eventService, (__bridge CFDataRef)dataCopySpec,0); XCTAssertTrue (event != NULL); if (event) { CFRelease(event); } }]; [eventController invalidate]; } @end