TestIOHIDPostEvent.m   [plain text]

//
// TestIOHIDPostEvent.m
// IOHIDFamilyUnitTests
//
// Created by Abhishek Nayyar on 3/5/18.
//

#import <XCTest/XCTest.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/hid/IOHIDEventSystemClientPrivate.h>
#include <IOKit/hid/IOHIDEventSystemKeysPrivate.h>
#include <IOKit/hid/IOHIDEventSystem.h>
#include <IOKit/hid/IOHIDEventSystemPrivate.h>
#include "AppleHIDUsageTables.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/hidsystem/IOHIDShared.h>
#import <IOKit/hidsystem/event_status_driver.h>
#include "IOHIDUnitTestUtility.h"
#include <TargetConditionals.h>

#define HIDPostEventTestThreshold 10

@interface TestIOHIDPostEvent : XCTestCase
#if TARGET_OS_OSX
@property IOHIDEventSystemClientRef eventSystem;
@property NXEventHandle eventDriver;
@property UInt32 eventCount;
-(void) handleIOHIDPostEvent:(IOHIDEventRef) event;
#endif
@end

@implementation TestIOHIDPostEvent
{}
- (void)setUp {

[super setUp];
}
- (void)tearDown {

[super tearDown];
}
#if TARGET_OS_OSX

IOHIDEventBlock eventBlock = ^(void * target __unused, __unused void * refcon, void * sender __unused, IOHIDEventRef event)
{
TestIOHIDPostEvent *me = (__bridge TestIOHIDPostEvent*)target;
[me handleIOHIDPostEvent:event];
};

- (void) testIOHIDPostEvent {

kern_return_t kr;
NXEventData event;
IOGPoint loc;

_eventSystem = IOHIDEventSystemClientCreateWithType(kCFAllocatorDefault, kIOHIDEventSystemClientTypeMonitor, NULL);

HIDXCTAssertAndThrowTrue(_eventSystem != NULL);

IOHIDEventSystemClientRegisterEventBlock(_eventSystem, eventBlock, (__bridge void*)self, NULL);

NSDictionary *matchingDict = @{@kIOHIDServiceDeviceUsagePageKey : @(kHIDPage_AppleVendor), @kIOHIDServiceDeviceUsageKey : @(kHIDUsage_AppleVendor_NXEvent)};

IOHIDEventSystemClientSetMatching(_eventSystem, (__bridge CFDictionaryRef)(matchingDict));

IOHIDEventSystemClientScheduleWithRunLoop(_eventSystem, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDEventSystemClientCopyProperty(_eventSystem, CFSTR (kIOHIDEventSystemClientIsUnresponsive));

_eventDriver = NXOpenEventStatus();

XCTAssert( MACH_PORT_NULL != _eventDriver);

loc.x = 200;
loc.y = 220;

//set key event
event.key.repeat = FALSE;
event.key.keyCode = 0;
event.key.charSet = NX_ASCIISET;
event.key.charCode = 'a';
event.key.origCharSet = event.key.charSet;
event.key.origCharCode = event.key.charCode;

kr = IOHIDPostEvent ( _eventDriver, NX_KEYUP, loc, &event, FALSE, 0, FALSE );

XCTAssert( KERN_SUCCESS == kr, "kr:%x", kr);

kr = IOHIDPostEvent ( _eventDriver, NX_KEYDOWN, loc, &event, FALSE, 0, FALSE );

XCTAssert( KERN_SUCCESS == kr, "kr:%x", kr);

CFRunLoopRunInMode(kCFRunLoopDefaultMode, HIDPostEventTestThreshold, false);

XCTAssert(_eventCount == 2);

// release resouce

IOHIDEventSystemClientUnscheduleWithRunLoop(_eventSystem, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRelease(_eventSystem);

NXCloseEventStatus(_eventDriver);
}
-(void) handleIOHIDPostEvent:(IOHIDEventRef) event
{
_eventCount++;

XCTAssert(IOHIDEventConformsTo (event, kIOHIDEventTypeVendorDefined));

CFIndex usage = IOHIDEventGetIntegerValue(event, kIOHIDEventFieldVendorDefinedUsage);

XCTAssert(usage == kHIDUsage_AppleVendor_NXEvent);

CFIndex usagePage = IOHIDEventGetIntegerValue(event, kIOHIDEventFieldVendorDefinedUsagePage);

XCTAssert(usagePage == kHIDPage_AppleVendor);

NXEventExt *nxEvent = NULL;
CFIndex nxEventLength = 0;
IOHIDEventGetVendorDefinedData (event, (uint8_t**)&nxEvent, &nxEventLength);

XCTAssert(nxEvent);

XCTAssert(nxEventLength == sizeof(NXEventExt), "lenght:%d", (int)nxEventLength);

XCTAssert(nxEvent->payload.location.x == 200);
XCTAssert(nxEvent->payload.location.y == 220);
XCTAssert(nxEvent->payload.data.key.charSet == NX_ASCIISET);

//verify audit trailer (pid)
XCTAssert(nxEvent->extension.audit.val[5] == getpid(), "pid:%d", nxEvent->extension.audit.val[5]);

}
#endif/*TARGET_OS_OSX*/
@end