blob: 9b059064b6213c2b9813d1bf6debcf20b661730b [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/sys/fuzzing/common/async-eventpair.h"
#include <lib/zx/eventpair.h>
#include <lib/zx/time.h>
#include <zircon/errors.h>
#include <zircon/types.h>
#include <gtest/gtest.h>
#include "src/sys/fuzzing/common/testing/async-test.h"
namespace fuzzing {
// Test fixture.
class AsyncEventPairTest : public AsyncTest {};
// Unit tests.
TEST_F(AsyncEventPairTest, Create) {
AsyncEventPair eventpair(executor());
auto ep1 = eventpair.Create();
EXPECT_EQ(ep1.wait_one(ZX_EVENTPAIR_PEER_CLOSED, zx::time::infinite_past(), nullptr),
ZX_ERR_TIMED_OUT);
// Creating again closes the previous eventpair.
auto ep2 = eventpair.Create();
EXPECT_EQ(ep1.wait_one(ZX_EVENTPAIR_PEER_CLOSED, zx::time::infinite_past(), nullptr), ZX_OK);
}
TEST_F(AsyncEventPairTest, Pair) {
AsyncEventPair eventpair(executor());
zx::eventpair ep1, ep2;
EXPECT_EQ(zx::eventpair::create(0, &ep1, &ep2), ZX_OK);
eventpair.Pair(std::move(ep1));
EXPECT_EQ(ep2.wait_one(ZX_EVENTPAIR_PEER_CLOSED, zx::time::infinite_past(), nullptr),
ZX_ERR_TIMED_OUT);
// Pairing again closes the previous eventpair.
zx::eventpair ep3, ep4;
EXPECT_EQ(zx::eventpair::create(0, &ep3, &ep4), ZX_OK);
eventpair.Pair(std::move(ep3));
EXPECT_EQ(ep2.wait_one(ZX_EVENTPAIR_PEER_CLOSED, zx::time::infinite_past(), nullptr), ZX_OK);
}
TEST_F(AsyncEventPairTest, IsConnected) {
AsyncEventPair eventpair1(executor());
AsyncEventPair eventpair2(executor());
EXPECT_FALSE(eventpair1.IsConnected());
EXPECT_FALSE(eventpair2.IsConnected());
auto eventpair = eventpair2.Create();
EXPECT_FALSE(eventpair1.IsConnected());
EXPECT_TRUE(eventpair2.IsConnected());
eventpair1.Pair(std::move(eventpair));
EXPECT_TRUE(eventpair1.IsConnected());
EXPECT_TRUE(eventpair2.IsConnected());
eventpair2.Reset();
EXPECT_FALSE(eventpair1.IsConnected());
EXPECT_FALSE(eventpair2.IsConnected());
}
TEST_F(AsyncEventPairTest, SignalSelf) {
AsyncEventPair eventpair1(executor());
AsyncEventPair eventpair2(executor());
// Returns error if not connected.
EXPECT_EQ(eventpair1.SignalSelf(0, ZX_USER_SIGNAL_1), ZX_ERR_PEER_CLOSED);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_1), 0U);
eventpair1.Pair(eventpair2.Create());
EXPECT_EQ(eventpair1.SignalSelf(0, ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2), ZX_OK);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_1), ZX_USER_SIGNAL_1);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_ALL), ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2);
EXPECT_EQ(eventpair2.GetSignals(ZX_USER_SIGNAL_ALL), 0U);
EXPECT_EQ(eventpair1.SignalSelf(ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1, ZX_USER_SIGNAL_3), ZX_OK);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_1), 0U);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_ALL), ZX_USER_SIGNAL_2 | ZX_USER_SIGNAL_3);
EXPECT_EQ(eventpair2.GetSignals(ZX_USER_SIGNAL_ALL), 0U);
// Can only raise user signals.
EXPECT_EQ(eventpair1.SignalSelf(0, ZX_USER_SIGNAL_0 | ZX_EVENTPAIR_PEER_CLOSED), ZX_OK);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_0 | ZX_EVENTPAIR_PEER_CLOSED), ZX_USER_SIGNAL_0);
}
TEST_F(AsyncEventPairTest, SignalPeer) {
AsyncEventPair eventpair1(executor());
AsyncEventPair eventpair2(executor());
// Returns error if not connected.
EXPECT_EQ(eventpair1.SignalPeer(0, ZX_USER_SIGNAL_1), ZX_ERR_PEER_CLOSED);
EXPECT_EQ(eventpair2.GetSignals(ZX_USER_SIGNAL_1), 0U);
eventpair1.Pair(eventpair2.Create());
EXPECT_EQ(eventpair2.SignalPeer(0, ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2), ZX_OK);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_1), ZX_USER_SIGNAL_1);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_ALL), ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2);
EXPECT_EQ(eventpair2.GetSignals(ZX_USER_SIGNAL_ALL), 0U);
EXPECT_EQ(eventpair2.SignalPeer(ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1, ZX_USER_SIGNAL_3), ZX_OK);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_1), 0U);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_ALL), ZX_USER_SIGNAL_2 | ZX_USER_SIGNAL_3);
EXPECT_EQ(eventpair2.GetSignals(ZX_USER_SIGNAL_ALL), 0U);
// Can only raise user signals.
EXPECT_EQ(eventpair2.SignalPeer(0, ZX_USER_SIGNAL_0 | ZX_EVENTPAIR_PEER_CLOSED), ZX_OK);
EXPECT_EQ(eventpair1.GetSignals(ZX_USER_SIGNAL_0 | ZX_EVENTPAIR_PEER_CLOSED), ZX_USER_SIGNAL_0);
}
TEST_F(AsyncEventPairTest, WaitFor) {
AsyncEventPair eventpair1(executor());
AsyncEventPair eventpair2(executor());
// Returns error if not connected.
auto signals01 = ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1;
FUZZING_EXPECT_ERROR(eventpair1.WaitFor(signals01), ZX_ERR_PEER_CLOSED);
RunUntilIdle();
eventpair1.Pair(eventpair2.Create());
FUZZING_EXPECT_OK(eventpair1.WaitFor(signals01), signals01);
FUZZING_EXPECT_OK(executor()->MakeDelayedPromise(zx::msec(1)).and_then([&] {
EXPECT_EQ(eventpair2.SignalPeer(0, signals01), ZX_OK);
return fpromise::ok();
}));
RunUntilIdle();
// Should be able to return immediately, and get back only requested signals.
auto signals1 = ZX_USER_SIGNAL_1;
FUZZING_EXPECT_OK(eventpair1.WaitFor(signals1), signals1);
RunUntilIdle();
// Can clear and be signaled again.
EXPECT_EQ(eventpair1.SignalSelf(signals1, 0), ZX_OK);
auto signals12 = ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2;
FUZZING_EXPECT_OK(eventpair1.WaitFor(signals12), signals12);
FUZZING_EXPECT_OK(executor()->MakeDelayedPromise(zx::msec(1)).and_then([&] {
EXPECT_EQ(eventpair2.SignalPeer(0, signals12), ZX_OK);
return fpromise::ok();
}));
RunUntilIdle();
// Wait should be interrupted by a local |Reset|.
EXPECT_EQ(eventpair1.SignalSelf(signals1, 0), ZX_OK);
FUZZING_EXPECT_ERROR(eventpair1.WaitFor(signals1));
FUZZING_EXPECT_OK(executor()->MakeDelayedPromise(zx::msec(1)).and_then([&] {
eventpair1.Reset();
return fpromise::ok();
}));
RunUntilIdle();
// Waiting after local |Reset| immediately returns error.
FUZZING_EXPECT_ERROR(eventpair1.WaitFor(signals1));
RunUntilIdle();
// Wait should be interrupted by a remote |Reset|.
eventpair1.Pair(eventpair2.Create());
EXPECT_EQ(eventpair1.SignalSelf(signals1, 0), ZX_OK);
FUZZING_EXPECT_ERROR(eventpair1.WaitFor(signals1));
FUZZING_EXPECT_OK(executor()->MakeDelayedPromise(zx::msec(1)).and_then([&] {
eventpair2.Reset();
return fpromise::ok();
}));
RunUntilIdle();
// Waiting after remote |Reset| immediately returns error.
FUZZING_EXPECT_ERROR(eventpair1.WaitFor(signals1));
RunUntilIdle();
// Dropping the remote end returns an error.
{
auto eventpair = eventpair1.Create();
FUZZING_EXPECT_ERROR(eventpair1.WaitFor(signals1));
}
RunUntilIdle();
}
} // namespace fuzzing