summaryrefslogtreecommitdiff
path: root/libc/test/src/sched/sched_rr_get_interval_test.cpp
blob: d5eecb5bee5b5fc50a9dd3cb07ab6652761fe2f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//===-- Unittests for sched_rr_get_interval -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/sched/sched_get_priority_min.h"
#include "src/sched/sched_getscheduler.h"
#include "src/sched/sched_rr_get_interval.h"
#include "src/sched/sched_setscheduler.h"
#include "src/unistd/getuid.h"
#include "test/UnitTest/ErrnoCheckingTest.h"
#include "test/UnitTest/Test.h"

#include "hdr/sched_macros.h"
#include "hdr/types/struct_timespec.h"

using LlvmLibcSchedRRGetIntervalTest =
    LIBC_NAMESPACE::testing::ErrnoCheckingTest;

TEST_F(LlvmLibcSchedRRGetIntervalTest, SmokeTest) {
  auto SetSched = [&](int policy) {
    int min_priority = LIBC_NAMESPACE::sched_get_priority_min(policy);
    ASSERT_GE(min_priority, 0);
    ASSERT_ERRNO_SUCCESS();
    struct sched_param param;
    param.sched_priority = min_priority;
    ASSERT_EQ(LIBC_NAMESPACE::sched_setscheduler(0, policy, &param), 0);
    ASSERT_ERRNO_SUCCESS();
  };

  auto TimespecToNs = [](struct timespec t) {
    return static_cast<uint64_t>(t.tv_sec * 1000UL * 1000UL * 1000UL +
                                 t.tv_nsec);
  };

  struct timespec ts;

  // We can only set SCHED_RR with CAP_SYS_ADMIN
  if (LIBC_NAMESPACE::getuid() == 0)
    SetSched(SCHED_RR);

  int cur_policy = LIBC_NAMESPACE::sched_getscheduler(0);
  ASSERT_GE(cur_policy, 0);
  ASSERT_ERRNO_SUCCESS();

  // We can actually run meaningful tests.
  if (cur_policy == SCHED_RR) {
    // Success
    ASSERT_EQ(LIBC_NAMESPACE::sched_rr_get_interval(0, &ts), 0);
    ASSERT_ERRNO_SUCCESS();

    // Check that numbers make sense (liberal bound of 10ns - 30sec)
    constexpr uint64_t tenNs = 10UL;
    ASSERT_GT(TimespecToNs(ts), tenNs);
    constexpr uint64_t thirstyS = 30UL * 1000UL * 1000UL * 1000UL;
    ASSERT_LT(TimespecToNs(ts), thirstyS);

    // Null timespec
    ASSERT_EQ(LIBC_NAMESPACE::sched_rr_get_interval(0, nullptr), -1);
    ASSERT_ERRNO_EQ(EFAULT);

    // Negative pid
    ASSERT_EQ(LIBC_NAMESPACE::sched_rr_get_interval(-1, &ts), -1);
    ASSERT_ERRNO_EQ(EINVAL);
  }

  // Negative tests don't have SCHED_RR set
  SetSched(SCHED_OTHER);
  ASSERT_EQ(LIBC_NAMESPACE::sched_rr_get_interval(0, &ts), 0);
  ASSERT_ERRNO_SUCCESS();

  // TODO: Missing unkown pid -> ESRCH. This is read only so safe to try a few
  //       unlikely values.
}