blob: a2f4cd6ca4bdcbc075e0bd9d20bd79092396663c [file] [log] [blame]
// Copyright 2024 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 <sys/mount.h>
#include <sys/syscall.h>
#include <cerrno>
#include <csignal>
#include <ctime>
#include <gtest/gtest.h>
#include <linux/capability.h>
#include "src/starnix/tests/syscalls/cpp/capabilities_helper.h"
#include "src/starnix/tests/syscalls/cpp/test_helper.h"
TEST(Timers, NoWakeAlarmCap) {
test_helper::UnsetCapability(CAP_WAKE_ALARM);
timer_t timer_id;
struct sigevent sev = {};
sev.sigev_notify = SIGEV_NONE;
EXPECT_EQ(-1, timer_create(CLOCK_BOOTTIME_ALARM, &sev, &timer_id));
EXPECT_EQ(errno, EPERM);
EXPECT_EQ(-1, timer_create(CLOCK_REALTIME_ALARM, &sev, &timer_id));
EXPECT_EQ(errno, EPERM);
}
TEST(Timers, RealtimeAlarm) {
if (!test_helper::HasCapability(CAP_WAKE_ALARM)) {
GTEST_SKIP()
<< "The CAP_WAKE_ALARM capability is required to create a CLOCK_REALTIME_ALARM timer.";
}
timespec begin = {};
ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &begin));
timer_t timer_id;
struct sigevent sev = {};
sev.sigev_notify = SIGEV_NONE;
SAFE_SYSCALL(timer_create(CLOCK_REALTIME_ALARM, &sev, &timer_id));
// Test timer 1 second in the future.
struct itimerspec its = {};
its.it_value = begin;
its.it_value.tv_sec += 1;
SAFE_SYSCALL(timer_settime(timer_id, TIMER_ABSTIME, &its, nullptr));
struct timespec sleep_t = {
.tv_sec = 1,
.tv_nsec = 5000,
};
nanosleep(&sleep_t, nullptr);
// The timer should count down to 0 and stop since the interval is zero. No overruns should be
// counted.
EXPECT_EQ(0, timer_gettime(timer_id, &its));
EXPECT_EQ(0, its.it_value.tv_sec);
EXPECT_EQ(0, its.it_value.tv_nsec);
EXPECT_EQ(0, timer_getoverrun(timer_id));
SAFE_SYSCALL(timer_delete(timer_id));
}