diff options
Diffstat (limited to 'test/syscalls/linux/base_poll_test.h')
-rw-r--r-- | test/syscalls/linux/base_poll_test.h | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/test/syscalls/linux/base_poll_test.h b/test/syscalls/linux/base_poll_test.h new file mode 100644 index 000000000..9b9b81933 --- /dev/null +++ b/test/syscalls/linux/base_poll_test.h @@ -0,0 +1,101 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GVISOR_TEST_SYSCALLS_BASE_POLL_TEST_H_ +#define GVISOR_TEST_SYSCALLS_BASE_POLL_TEST_H_ + +#include <signal.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <syscall.h> +#include <time.h> +#include <unistd.h> + +#include <memory> + +#include "gtest/gtest.h" +#include "absl/synchronization/mutex.h" +#include "absl/time/time.h" +#include "test/util/logging.h" +#include "test/util/signal_util.h" +#include "test/util/thread_util.h" + +namespace gvisor { +namespace testing { + +// TimerThread is a cancelable timer. +class TimerThread { + public: + TimerThread(absl::Time deadline, pid_t tgid, pid_t tid) + : thread_([=] { + mu_.Lock(); + mu_.AwaitWithDeadline(absl::Condition(&cancel_), deadline); + if (!cancel_) { + TEST_PCHECK(tgkill(tgid, tid, SIGALRM) == 0); + } + mu_.Unlock(); + }) {} + + ~TimerThread() { Cancel(); } + + void Cancel() { + absl::MutexLock ml(&mu_); + cancel_ = true; + } + + private: + mutable absl::Mutex mu_; + bool cancel_ GUARDED_BY(mu_) = false; + + // Must be last to ensure that the destructor for the thread is run before + // any other member of the object is destroyed. + ScopedThread thread_; +}; + +// Base test fixture for poll, select, ppoll, and pselect tests. +// +// This fixture makes use of SIGALRM. The handler is saved in SetUp() and +// restored in TearDown(). +class BasePollTest : public ::testing::Test { + protected: + BasePollTest(); + ~BasePollTest() override; + + // Sets a timer that will send a signal to the calling thread after + // `duration`. + void SetTimer(absl::Duration duration); + + // Returns true if the timer has fired. + bool TimerFired() const; + + // Stops the pending timer (if any) and clear the "fired" state. + void ClearTimer(); + + private: + // Thread that implements the timer. If the timer is stopped, timer_ is null. + // + // We have to use a thread for this purpose because tests using this fixture + // expect to be interrupted by the timer signal, but itimers/alarm(2) send + // thread-group-directed signals, which may be handled by any thread in the + // test process. + std::unique_ptr<TimerThread> timer_; + + // The original SIGALRM handler, to restore in destructor. + struct sigaction original_alarm_sa_; +}; + +} // namespace testing +} // namespace gvisor + +#endif // GVISOR_TEST_SYSCALLS_BASE_POLL_TEST_H_ |