/* * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3.0 only, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * version 3.0 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3.0 along with this program. If not, see * . */ #include "config.h" #import "ObjFW.h" #import "ObjFWTest.h" #ifdef HAVE_KQUEUE # import "OFKqueueKernelEventObserver.h" #endif #ifdef HAVE_EPOLL # import "OFEpollKernelEventObserver.h" #endif #ifdef HAVE_POLL # import "OFPollKernelEventObserver.h" #endif #ifdef HAVE_SELECT # import "OFSelectKernelEventObserver.h" #endif @interface OFKernelEventObserverTests: OTTestCase { OFTCPSocket *_server, *_client, *_accepted; OFKernelEventObserver *_observer; size_t _events; } @end static const size_t numExpectedEvents = 3; @implementation OFKernelEventObserverTests - (void)setUp { OFSocketAddress address; [super setUp]; _server = [[OFTCPSocket alloc] init]; address = [_server bindToHost: @"127.0.0.1" port: 0]; [_server listen]; _client = [[OFTCPSocket alloc] init]; [_client connectToHost: @"127.0.0.1" port: OFSocketAddressIPPort(&address)]; [_client writeBuffer: "0" length: 1]; } - (void)dealloc { [_client release]; [_server release]; [_accepted release]; [_observer release]; [super dealloc]; } - (void)testKernelEventObserverWithClass: (Class)class { bool deadlineExceeded = false; OFDate *deadline; _observer = [[class alloc] init]; _observer.delegate = self; [_observer addObjectForReading: _server]; deadline = [OFDate dateWithTimeIntervalSinceNow: 1]; while (_events < numExpectedEvents) { if (deadline.timeIntervalSinceNow < 0) { deadlineExceeded = true; break; } [_observer observeForTimeInterval: 0.01]; } OTAssertFalse(deadlineExceeded); OTAssertEqual(_events, numExpectedEvents); } - (void)objectIsReadyForReading: (id)object { char buffer; switch (_events++) { case 0: OTAssertEqual(object, _server); _accepted = [[object accept] retain]; [_observer addObjectForReading: _accepted]; break; case 1: OTAssert(object, _accepted); OTAssertEqual([object readIntoBuffer: &buffer length: 1], 1); OTAssertEqual(buffer, '0'); [_client close]; break; case 2: OTAssertEqual(object, _accepted); OTAssertEqual([object readIntoBuffer: &buffer length: 1], 0); break; default: OTAssert(false); } } #ifdef HAVE_SELECT - (void)testSelectKernelEventObserver { [self testKernelEventObserverWithClass: [OFSelectKernelEventObserver class]]; } #endif #ifdef HAVE_POLL - (void)testPollKernelEventObserver { [self testKernelEventObserverWithClass: [OFPollKernelEventObserver class]]; } #endif #ifdef HAVE_EPOLL - (void)testEpollKernelEventObserver { [self testKernelEventObserverWithClass: [OFEpollKernelEventObserver class]]; } #endif #ifdef HAVE_KQUEUE - (void)testKqueueKernelEventObserver { [self testKernelEventObserverWithClass: [OFKqueueKernelEventObserver class]]; } #endif @end