Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Unified Diff: native_client_sdk/src/tests/nacl_io_test/event_test.cc

Issue 23498015: [NaCl SDK] Support non blocking TCP/UDP (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove event friends, rename EventListenerPoll Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/tests/nacl_io_test/event_test.cc
diff --git a/native_client_sdk/src/tests/nacl_io_test/event_test.cc b/native_client_sdk/src/tests/nacl_io_test/event_test.cc
index 11326bf0832b44031084bdca2fdf5b7d582513eb..a4471ad1a80bc50fcb300a5c38c109fd27ddd91d 100644
--- a/native_client_sdk/src/tests/nacl_io_test/event_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/event_test.cc
@@ -17,465 +17,225 @@
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/kernel_proxy.h"
#include "nacl_io/kernel_wrap.h"
+#include "nacl_io/mount_node_pipe.h"
+#include "nacl_io/mount_stream.h"
+
+#include "ppapi_simple/ps.h"
using namespace nacl_io;
using namespace sdk_util;
-class EventEmitterTester : public MountNode {
+
+class EventListenerTester : public EventListener {
public:
- EventEmitterTester() : MountNode(NULL), event_status_(0), event_cnt_(0) {}
+ EventListenerTester() : EventListener(), events_(0) {};
+
+ virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events) {
+ events_ |= events;
+ }
- void SetEventStatus(uint32_t bits) { event_status_ = bits; }
- uint32_t GetEventStatus() { return event_status_; }
+ uint32_t Events() {
+ return events_;
+ }
- Error Ioctl(int request, char* arg) {
- event_status_ = static_cast<uint32_t>(request);
- return 0;
+ void Clear() {
+ events_ = 0;
}
- int GetType() { return S_IFSOCK; }
- int NumEvents() { return event_cnt_; }
+ uint32_t events_;
+};
+class EventEmitterTester : public EventEmitter {
public:
- // Make this function public for testing
- void RaiseEvent(uint32_t events) {
- EventEmitter::RaiseEvent(events);
+ void RegisterListener(EventListener* listener, uint32_t events) {
binji 2013/09/12 01:47:57 using EventEmitter::RegisterListener; This makes
noelallen1 2013/09/12 23:19:03 Done.
+ EventEmitter::RegisterListener(listener, events);
}
-
- // Called after registering locally, but while lock is still held.
- void ChainRegisterEventInfo(const ScopedEventInfo& event) {
- event_cnt_++;
+ void UnregisterListener(EventListener* listener) {
binji 2013/09/12 01:47:57 ditto
noelallen1 2013/09/12 23:19:03 Done.
+ EventEmitter::UnregisterListener(listener);
}
- // Called before unregistering locally, but while lock is still held.
- void ChainUnregisterEventInfo(const ScopedEventInfo& event) {
- event_cnt_--;
- }
+ uint32_t GetEventStatus() { return 0; }
- protected:
- uint32_t event_status_;
- uint32_t event_cnt_;
+ void Raise(uint32_t events) {
+ AUTO_LOCK(emitter_lock_);
+ RaiseEvents_Locked(events);
+ }
};
+TEST(Emitter, Basic) {
+ EventListenerTester listenerA;
binji 2013/09/12 01:47:57 nit: listener_a
noelallen1 2013/09/12 23:19:03 Done.
+ EventListenerTester listenerB;
+ EventEmitterTester emitter;
-const int MAX_EVENTS = 8;
-
-// IDs for Emitters
-const int ID_EMITTER = 5;
-const int ID_LISTENER = 6;
-const int ID_EMITTER_DUP = 7;
-
-// Kernel Event values
-const uint32_t KE_EXPECTED = 4;
-const uint32_t KE_FILTERED = 2;
-const uint32_t KE_NONE = 0;
-
-// User Data values
-const uint64_t USER_DATA_A = 1;
-const uint64_t USER_DATA_B = 5;
-
-// Timeout durations
-const int TIMEOUT_IMMEDIATE = 0;
-const int TIMEOUT_SHORT= 100;
-const int TIMEOUT_LONG = 500;
-const int TIMEOUT_NEVER = -1;
-const int TIMEOUT_VERY_LONG = 1000;
-
-// We subtract TIMEOUT_SLOP from the expected minimum timed due to rounding
-// and clock drift converting between absolute and relative time. This should
-// only be 1 for Less Than, and 1 for rounding, but we use 10 since we don't
-// care about real precision, aren't testing of the underlying
-// implementations and don't want flakiness.
-const int TIMEOUT_SLOP = 10;
-
-TEST(EventTest, EmitterBasic) {
- ScopedRef<EventEmitterTester> emitter(new EventEmitterTester());
- ScopedRef<EventEmitter> null_emitter;
-
- ScopedEventListener listener(new EventListener);
-
- // Verify construction
- EXPECT_EQ(0, emitter->NumEvents());
- EXPECT_EQ(0, emitter->GetEventStatus());
-
- // Verify status
- emitter->SetEventStatus(KE_EXPECTED);
- EXPECT_EQ(KE_EXPECTED, emitter->GetEventStatus());
-
- // Fail to update or free an ID not in the set
- EXPECT_EQ(ENOENT, listener->Update(ID_EMITTER, KE_EXPECTED, USER_DATA_A));
- EXPECT_EQ(ENOENT, listener->Free(ID_EMITTER));
-
- // Fail to Track self
- EXPECT_EQ(EINVAL, listener->Track(ID_LISTENER,
- listener,
- KE_EXPECTED,
- USER_DATA_A));
-
- // Set the emitter filter and data
- EXPECT_EQ(0, listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A));
- EXPECT_EQ(1, emitter->NumEvents());
-
- // Fail to add the same ID
- EXPECT_EQ(EEXIST,
- listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A));
- EXPECT_EQ(1, emitter->NumEvents());
-
- int event_cnt = 0;
- EventData ev[MAX_EVENTS];
-
- // Do not allow a wait with a zero events count.
- EXPECT_EQ(EINVAL, listener->Wait(ev, 0, TIMEOUT_IMMEDIATE, &event_cnt));
-
- // Do not allow a wait with a negative events count.
- EXPECT_EQ(EINVAL, listener->Wait(ev, -1, TIMEOUT_IMMEDIATE, &event_cnt));
-
- // Do not allow a wait with a NULL EventData pointer
- EXPECT_EQ(EFAULT,
- listener->Wait(NULL, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt));
-
- // Return with no events if the Emitter has no signals set.
- memset(ev, 0, sizeof(ev));
- event_cnt = 100;
- emitter->SetEventStatus(KE_NONE);
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt));
- EXPECT_EQ(0, event_cnt);
-
- // Return with no events if the Emitter has a filtered signals set.
- memset(ev, 0, sizeof(ev));
- event_cnt = 100;
- emitter->SetEventStatus(KE_FILTERED);
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt));
- EXPECT_EQ(0, event_cnt);
-
- // Return with one event if the Emitter has the expected signal set.
- memset(ev, 0, sizeof(ev));
- event_cnt = 100;
- emitter->SetEventStatus(KE_EXPECTED);
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt));
- EXPECT_EQ(1, event_cnt);
- EXPECT_EQ(USER_DATA_A, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
-
- // Return with one event containing only the expected signal.
- memset(ev, 0, sizeof(ev));
- event_cnt = 100;
- emitter->SetEventStatus(KE_EXPECTED | KE_FILTERED);
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt));
- EXPECT_EQ(1, event_cnt);
- EXPECT_EQ(USER_DATA_A, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
-
- // Change the USER_DATA on an existing event
- EXPECT_EQ(0, listener->Update(ID_EMITTER, KE_EXPECTED, USER_DATA_B));
-
- // Return with one event signaled with the alternate USER DATA
- memset(ev, 0, sizeof(ev));
- event_cnt = 100;
- emitter->SetEventStatus(KE_EXPECTED | KE_FILTERED);
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, 0, &event_cnt));
- EXPECT_EQ(1, event_cnt);
- EXPECT_EQ(USER_DATA_B, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
-
- // Reset the USER_DATA.
- EXPECT_EQ(0, listener->Update(ID_EMITTER, KE_EXPECTED, USER_DATA_A));
-
- // Support adding a DUP.
- EXPECT_EQ(0, listener->Track(ID_EMITTER_DUP,
- emitter,
- KE_EXPECTED,
- USER_DATA_A));
- EXPECT_EQ(2, emitter->NumEvents());
-
- // Return unsignaled.
- memset(ev, 0, sizeof(ev));
- emitter->SetEventStatus(KE_NONE);
- event_cnt = 100;
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt));
- EXPECT_EQ(0, event_cnt);
-
- // Return with two event signaled with expected data.
- memset(ev, 0, sizeof(ev));
- emitter->SetEventStatus(KE_EXPECTED);
- event_cnt = 100;
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt));
- EXPECT_EQ(2, event_cnt);
- EXPECT_EQ(USER_DATA_A, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
- EXPECT_EQ(USER_DATA_A, ev[1].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[1].events);
-}
-
-long Duration(struct timeval* start, struct timeval* end) {
- if (start->tv_usec > end->tv_usec) {
- end->tv_sec -= 1;
- end->tv_usec += 1000000;
- }
- long cur_time = 1000 * (end->tv_sec - start->tv_sec);
- cur_time += (end->tv_usec - start->tv_usec) / 1000;
- return cur_time;
-}
+ emitter.RegisterListener(&listenerA, POLLIN | POLLOUT | POLLERR);
+ emitter.RegisterListener(&listenerB, POLLIN | POLLOUT | POLLERR);
+ EXPECT_EQ(0, emitter.GetEventStatus());
+ EXPECT_EQ(0, listenerA.Events());
-// Run a timed wait, and return the average of 8 iterations to reduce
-// chance of false negative on outlier.
-const int TRIES_TO_AVERAGE = 8;
-bool TimedListen(ScopedEventListener& listen,
- EventData* ev,
- int ev_max,
- int ev_expect,
- int ms_wait,
- long* duration) {
+ emitter.Raise(POLLIN);
+ EXPECT_EQ(POLLIN, listenerA.Events());
- struct timeval start;
- struct timeval end;
- long total_time = 0;
+ listenerA.Clear();
- for (int a=0; a < TRIES_TO_AVERAGE; a++) {
- gettimeofday(&start, NULL);
+ emitter.Raise(POLLOUT);
+ EXPECT_EQ(POLLOUT, listenerA.Events());
+ EXPECT_EQ(POLLIN | POLLOUT, listenerB.Events());
+}
- int signaled;
- EXPECT_EQ(0, listen->Wait(ev, ev_max, ms_wait, &signaled));
- EXPECT_EQ(signaled, ev_expect);
+TEST(PipeTest, Listener) {
+ const char hello[] = "Hello World.";
+ char tmp[64] = "Goodbye";
- if (signaled != ev_expect) {
- return false;
- }
+ EventEmitterPipe* pipe = new EventEmitterPipe(32);
binji 2013/09/12 01:47:57 If you're going to ignore the ref-count, why not j
noelallen1 2013/09/12 23:19:03 Done.
- gettimeofday(&end, NULL);
+ // Expect to time out on input.
+ {
+ EventListenerLock locker(pipe);
+ EXPECT_EQ(ETIMEDOUT, locker.WaitOnEvent(POLLIN, 0));
+ }
- long cur_time = Duration(&start, &end);
- total_time += cur_time;
+ // Output should be ready to go.
+ {
+ EventListenerLock locker(pipe);
+ EXPECT_EQ(0, locker.WaitOnEvent(POLLOUT, 0));
+ EXPECT_EQ(sizeof(hello), pipe->Write_Locked(hello, sizeof(hello)));
}
- *duration = total_time / TRIES_TO_AVERAGE;
- return true;
-}
+ // We should now be able to poll
+ {
+ EventListenerLock locker(pipe);
+ EXPECT_EQ(0, locker.WaitOnEvent(POLLIN, 0));
+ EXPECT_EQ(sizeof(hello), pipe->Read_Locked(tmp, sizeof(tmp)));
+ }
+ // Verify we can read it correctly.
+ EXPECT_EQ(0, strcmp(hello, tmp));
-// NOTE: These timing tests are potentially flaky, the real test is
-// for the zero timeout should be, has the ConditionVariable been waited on?
-// Once we provide a debuggable SimpleCond and SimpleLock we can actually test
-// the correct thing.
-
-// Normal scheduling would expect us to see ~10ms accuracy, but we'll
-// use a much bigger number (yet smaller than the MAX_MS_TIMEOUT).
-const int SCHEDULING_GRANULARITY = 100;
-
-const int EXPECT_ONE_EVENT = 1;
-const int EXPECT_NO_EVENT = 0;
-
-TEST(EventTest, EmitterTimeout) {
- ScopedRef<EventEmitterTester> emitter(new EventEmitterTester());
- ScopedEventListener listener(new EventListener());
- long duration;
-
- EventData ev[MAX_EVENTS];
- memset(ev, 0, sizeof(ev));
- EXPECT_EQ(0, listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A));
-
- // Return immediately when emitter is signaled, with no timeout
- emitter->SetEventStatus(KE_EXPECTED);
- memset(ev, 0, sizeof(ev));
- EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_ONE_EVENT,
- TIMEOUT_IMMEDIATE, &duration));
- EXPECT_EQ(USER_DATA_A, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
- EXPECT_EQ(0, duration);
-
- // Return immediately when emitter is signaled, even with timeout
- emitter->SetEventStatus(KE_EXPECTED);
- memset(ev, 0, sizeof(ev));
- EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_ONE_EVENT,
- TIMEOUT_LONG, &duration));
- EXPECT_EQ(USER_DATA_A, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
- EXPECT_GT(SCHEDULING_GRANULARITY, duration);
-
- // Return immediately if Emiiter is already signaled when blocking forever.
- emitter->SetEventStatus(KE_EXPECTED);
- memset(ev, 0, sizeof(ev));
- EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_ONE_EVENT,
- TIMEOUT_NEVER, &duration));
- EXPECT_EQ(USER_DATA_A, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
- EXPECT_GT(SCHEDULING_GRANULARITY, duration);
-
- // Return immediately if Emitter is no signaled when not blocking.
- emitter->SetEventStatus(KE_NONE);
- memset(ev, 0, sizeof(ev));
- EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_NO_EVENT,
- TIMEOUT_IMMEDIATE, &duration));
- EXPECT_EQ(0, duration);
-
- // Wait TIMEOUT_LONG if the emitter is not in a signaled state.
- emitter->SetEventStatus(KE_NONE);
- memset(ev, 0, sizeof(ev));
- EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_NO_EVENT,
- TIMEOUT_LONG, &duration));
- EXPECT_LT(TIMEOUT_LONG - TIMEOUT_SLOP, duration);
- EXPECT_GT(TIMEOUT_LONG + SCHEDULING_GRANULARITY, duration);
+ delete pipe;
}
-struct SignalInfo {
- EventEmitterTester* em;
- unsigned int ms_wait;
- uint32_t events;
-};
-static void *SignalEmitterThread(void *ptr) {
- SignalInfo* info = (SignalInfo*) ptr;
- struct timespec ts;
- ts.tv_sec = 0;
- ts.tv_nsec = info->ms_wait * 1000000;
+class TestMountStream : public MountStream {
+ public:
binji 2013/09/12 01:47:57 nit: 1 space
noelallen1 2013/09/12 23:19:03 Done.
+ TestMountStream() {};
binji 2013/09/12 01:47:57 2 spaces
binji 2013/09/12 01:47:57 remove ;
noelallen1 2013/09/12 23:19:03 Done.
noelallen1 2013/09/12 23:19:03 Done.
+};
- nanosleep(&ts, NULL);
+TEST(PipeNodeTest, Basic) {
+ ScopedMount mnt(new TestMountStream());
- info->em->RaiseEvent(info->events);
- return NULL;
-}
+ MountNodePipe* pipe_node = new MountNodePipe(mnt.get());
+ ScopedRef<MountNodePipe> pipe(pipe_node);
-TEST(EventTest, EmitterSignalling) {
- ScopedRef<EventEmitterTester> emitter(new EventEmitterTester());
- ScopedEventListener listener(new EventListener);
-
- SignalInfo siginfo;
- struct timeval start;
- struct timeval end;
- long duration;
-
- EventData ev[MAX_EVENTS];
- memset(ev, 0, sizeof(ev));
- EXPECT_EQ(0, listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A));
-
- // Setup another thread to wait 1/4 of the max time, and signal both
- // an expected, and unexpected value.
- siginfo.em = emitter.get();
- siginfo.ms_wait = TIMEOUT_SHORT;
- siginfo.events = KE_EXPECTED | KE_FILTERED;
- pthread_t tid;
- pthread_create(&tid, NULL, SignalEmitterThread, &siginfo);
-
- // Wait for the signal from the other thread and time it.
- gettimeofday(&start, NULL);
- int cnt = 0;
- EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_VERY_LONG, &cnt));
- EXPECT_EQ(1, cnt);
- gettimeofday(&end, NULL);
-
- // Verify the wait duration, and that we only recieved the expected signal.
- duration = Duration(&start, &end);
- EXPECT_GT(TIMEOUT_SHORT + SCHEDULING_GRANULARITY, duration);
- EXPECT_LT(TIMEOUT_SHORT - TIMEOUT_SLOP, duration);
- EXPECT_EQ(USER_DATA_A, ev[0].user_data);
- EXPECT_EQ(KE_EXPECTED, ev[0].events);
+ EXPECT_EQ(POLLOUT, pipe_node->GetEventStatus());
}
-namespace {
-class KernelProxyPolling : public KernelProxy {
- public:
- virtual int socket(int domain, int type, int protocol) {
- ScopedMount mnt;
- ScopedMountNode node(new EventEmitterTester());
- ScopedKernelHandle handle(new KernelHandle(mnt, node));
-
- Error error = handle->Init(0);
- if (error) {
- errno = error;
- return -1;
- }
-
- return AllocateFD(handle);
- }
-};
-
-class KernelProxyPollingTest : public ::testing::Test {
+#define MAX_FDS 32
binji 2013/09/12 01:47:57 use const instead of define
noelallen1 2013/09/12 23:19:03 Done.
+class SelectPollTest : public ::testing::Test {
public:
void SetUp() {
- ki_init(&kp_);
+ kp = new KernelProxy();
+ kp->Init(NULL);
+ EXPECT_EQ(0, kp->umount("/"));
+ EXPECT_EQ(0, kp->mount("", "/", "memfs", 0, NULL));
+
+ memset(&tv, 0, sizeof(tv));
}
void TearDown() {
- ki_uninit();
+ delete kp;
}
- protected:
- KernelProxyPolling kp_;
-};
-
-} // namespace
-
+ void SetFDs(int* fds, int cnt) {
+ FD_ZERO(&rd_set);
+ FD_ZERO(&wr_set);
+ FD_ZERO(&ex_set);
-#define SOCKET_CNT 4
-void SetFDs(fd_set* set, int* fds) {
- FD_ZERO(set);
+ for (int index = 0; index < cnt; index++) {
+ EXPECT_NE(-1, fds[index]);
+ FD_SET(fds[index], &rd_set);
+ FD_SET(fds[index], &wr_set);
+ FD_SET(fds[index], &ex_set);
- FD_SET(0, set);
- FD_SET(1, set);
- FD_SET(2, set);
+ pollfds[index].fd = fds[0];
binji 2013/09/12 01:47:57 fds[index]?
noelallen1 2013/09/12 23:19:03 doh!
+ pollfds[index].events = POLLIN | POLLOUT;
+ pollfds[index].revents = -1;
+ }
+ }
- for (int index = 0; index < SOCKET_CNT; index++)
- FD_SET(fds[index], set);
-}
+ void CloseFDs(int* fds, int cnt) {
+ for (int index = 0; index < cnt; index++)
+ kp->close(fds[index]);
+ }
-TEST_F(KernelProxyPollingTest, Select) {
- int fds[SOCKET_CNT];
+ protected:
+ KernelProxy* kp;
+ timeval tv;
fd_set rd_set;
fd_set wr_set;
+ fd_set ex_set;
+ struct pollfd pollfds[MAX_FDS];
+};
- FD_ZERO(&rd_set);
- FD_ZERO(&wr_set);
+TEST_F(SelectPollTest, PollMemPipe) {
+ int fds[2];
- FD_SET(0, &rd_set);
- FD_SET(1, &rd_set);
- FD_SET(2, &rd_set);
+ // Both FDs for regular files should be read/write but not exception.
+ fds[0] = kp->open("/test.txt", O_CREAT | O_WRONLY);
+ fds[1] = kp->open("/test.txt", O_RDONLY);
- FD_SET(0, &wr_set);
- FD_SET(1, &wr_set);
- FD_SET(2, &wr_set);
+ SetFDs(fds, 2);
- // Expect normal files to select as read, write, and error
- int cnt = select(4, &rd_set, &rd_set, &rd_set, NULL);
- EXPECT_EQ(3 * 3, cnt);
- EXPECT_NE(0, FD_ISSET(0, &rd_set));
- EXPECT_NE(0, FD_ISSET(1, &rd_set));
- EXPECT_NE(0, FD_ISSET(2, &rd_set));
+ EXPECT_EQ(2, kp->poll(pollfds, 2, 0));
+ EXPECT_EQ(POLLIN | POLLOUT, pollfds[0].revents);
+ EXPECT_EQ(POLLIN | POLLOUT, pollfds[1].revents);
+ CloseFDs(fds, 2);
- for (int index = 0 ; index < SOCKET_CNT; index++) {
- fds[index] = socket(0, 0, 0);
- EXPECT_NE(-1, fds[index]);
- }
+ // The write FD should select for write-only, read FD should not select
+ EXPECT_EQ(0, kp->pipe(fds));
+ SetFDs(fds, 2);
- // Highest numbered fd
- const int fdnum = fds[SOCKET_CNT - 1] + 1;
-
- // Expect only the normal files to select
- SetFDs(&rd_set, fds);
- cnt = select(fds[SOCKET_CNT-1] + 1, &rd_set, NULL, NULL, NULL);
- EXPECT_EQ(3, cnt);
- EXPECT_NE(0, FD_ISSET(0, &rd_set));
- EXPECT_NE(0, FD_ISSET(1, &rd_set));
- EXPECT_NE(0, FD_ISSET(2, &rd_set));
- for (int index = 0 ; index < SOCKET_CNT; index++) {
- EXPECT_EQ(0, FD_ISSET(fds[index], &rd_set));
- }
+ EXPECT_EQ(2, kp->poll(pollfds, 2, 0));
+ EXPECT_EQ(POLLOUT, pollfds[0].revents);
+ EXPECT_EQ(POLLOUT, pollfds[1].revents);
binji 2013/09/12 01:47:57 doesn't match comment (probably from fds[index] bu
noelallen1 2013/09/12 23:19:03 Done.
+
+ CloseFDs(fds, 2);
+}
+
+TEST_F(SelectPollTest, SelectMemPipe) {
+ int fds[2];
- // Poke one of the pollable nodes to be READ ready
- ioctl(fds[0], POLLIN, NULL);
+ // Both FDs for regular files should be read/write but not exception.
+ fds[0] = kp->open("/test.txt", O_CREAT | O_WRONLY);
+ fds[1] = kp->open("/test.txt", O_RDONLY);
+ SetFDs(fds, 2);
- // Expect normal files to be read/write and one pollable node to be read.
- SetFDs(&rd_set, fds);
- SetFDs(&wr_set, fds);
- cnt = select(fdnum, &rd_set, &wr_set, NULL, NULL);
- EXPECT_EQ(7, cnt);
+ EXPECT_EQ(4, kp->select(fds[1] + 1, &rd_set, &wr_set, &ex_set, &tv));
EXPECT_NE(0, FD_ISSET(fds[0], &rd_set));
- EXPECT_EQ(0, FD_ISSET(fds[0], &wr_set));
+ EXPECT_NE(0, FD_ISSET(fds[1], &rd_set));
+ EXPECT_NE(0, FD_ISSET(fds[0], &wr_set));
+ EXPECT_NE(0, FD_ISSET(fds[1], &wr_set));
+ EXPECT_EQ(0, FD_ISSET(fds[0], &ex_set));
+ EXPECT_EQ(0, FD_ISSET(fds[1], &ex_set));
+
+ CloseFDs(fds, 2);
+
+ // The write FD should select for write-only, read FD should not select
+ EXPECT_EQ(0, kp->pipe(fds));
+ SetFDs(fds, 2);
+
+ EXPECT_EQ(2, kp->select(fds[1] + 1, &rd_set, &wr_set, &ex_set, &tv));
+ EXPECT_EQ(0, FD_ISSET(fds[0], &rd_set));
+ EXPECT_EQ(0, FD_ISSET(fds[1], &rd_set));
+// EXPECT_EQ(0, FD_ISSET(fds[0], &wr_set));
binji 2013/09/12 01:47:57 why?
noelallen1 2013/09/12 23:19:03 Done.
+ EXPECT_NE(0, FD_ISSET(fds[1], &wr_set));
+ EXPECT_EQ(0, FD_ISSET(fds[0], &ex_set));
+ EXPECT_EQ(0, FD_ISSET(fds[1], &ex_set));
}

Powered by Google App Engine
This is Rietveld 408576698