// Include the production implementation so batching can be inspected without // starting a real network connection. Unused transport code is linker-collected. #include "InputStream.c" #undef NDEBUG #include static PPACKET_HOLDER pop(void) { PPACKET_HOLDER holder = NULL; assert(LbqPollQueueElement(&packetQueue, (void**)&holder) == LBQ_SUCCESS); return holder; } static void expectPosition(int x) { PPACKET_HOLDER holder = pop(); assert(holder->packet.header.magic == LE32(MOUSE_MOVE_ABS_MAGIC)); latchAbsoluteMousePacket(holder); assert(holder->packet.mouseMoveAbs.x == BE16(x)); assert((uint16_t)holder->packet.mouseMoveAbs.width == (uint16_t)BE16(2559)); freePacketHolder(holder); } int main(void) { AppVersionQuad[0] = 7; LbqInitializeLinkedBlockingQueue(&packetQueue, MAX_QUEUED_INPUT_PACKETS); LbqInitializeLinkedBlockingQueue(&packetHolderFreeList, MAX_QUEUED_INPUT_PACKETS); PltCreateMutex(&batchedInputMutex); initialized = true; for (int i = 0; i < 1000; ++i) { // A deliberately stalled sender must preserve each click's coordinates. assert(LiSendMousePositionEvent(10, 10, 2560, 1440) == 0); assert(LiSendMousePositionEvent(20, 20, 2560, 1440) == 0); assert(LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT) == 0); assert(LiSendMousePositionEvent(30, 30, 2560, 1440) == 0); assert(LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT) == 0); assert(LiSendMousePositionEvent(40, 40, 2560, 1440) == 0); expectPosition(20); PPACKET_HOLDER press = pop(); assert(press->packet.header.magic == LE32(BUTTON_ACTION_PRESS + 1)); freePacketHolder(press); expectPosition(30); PPACKET_HOLDER release = pop(); assert(release->packet.header.magic == LE32(BUTTON_ACTION_RELEASE + 1)); freePacketHolder(release); // Latching an older packet above must not prevent the latest batch // from still absorbing newer positions. assert(LiSendMousePositionEvent(50, 50, 2560, 1440) == 0); expectPosition(50); PPACKET_HOLDER empty; assert(LbqPollQueueElement(&packetQueue, (void**)&empty) == LBQ_NO_ELEMENT); } initialized = false; PLINKED_BLOCKING_QUEUE_ENTRY entry = LbqDestroyLinkedBlockingQueue(&packetQueue); assert(entry == NULL); entry = LbqDestroyLinkedBlockingQueue(&packetHolderFreeList); while (entry) { PLINKED_BLOCKING_QUEUE_ENTRY next = entry->flink; free(entry->data); entry = next; } PltDeleteMutex(&batchedInputMutex); puts("PASS: 1000 queued move/press/move/release cycles preserve positions"); return 0; }