1 #include <errno.h>
2 #include <sched.h>
3 
4 #include <condition_variable>
5 #include <mutex>
6 #include <thread>
7 
8 #include <dvr/performance_client_api.h>
9 #include <gtest/gtest.h>
10 
TEST(DISABLED_PerformanceTest,SetCpuPartition)11 TEST(DISABLED_PerformanceTest, SetCpuPartition) {
12   int error;
13 
14   // Test setting the the partition for the current task.
15   error = dvrSetCpuPartition(0, "/application/background");
16   EXPECT_EQ(0, error);
17 
18   error = dvrSetCpuPartition(0, "/application/performance");
19   EXPECT_EQ(0, error);
20 
21   // Test setting the partition for one of our tasks.
22   bool done = false;
23   pid_t task_id = 0;
24   std::mutex mutex;
25   std::condition_variable done_condition, id_condition;
26 
27   std::thread thread([&] {
28     std::unique_lock<std::mutex> lock(mutex);
29 
30     task_id = gettid();
31     id_condition.notify_one();
32 
33     done_condition.wait(lock, [&done] { return done; });
34   });
35 
36   {
37     std::unique_lock<std::mutex> lock(mutex);
38     id_condition.wait(lock, [&task_id] { return task_id != 0; });
39   }
40   EXPECT_NE(0, task_id);
41 
42   error = dvrSetCpuPartition(task_id, "/application");
43   EXPECT_EQ(0, error);
44 
45   {
46     std::lock_guard<std::mutex> lock(mutex);
47     done = true;
48     done_condition.notify_one();
49   }
50   thread.join();
51 
52   // Test setting the partition for a task that isn't valid using
53   // the task id of the thread that we just joined. Technically the
54   // id could wrap around by the time we get here, but this is
55   // extremely unlikely.
56   error = dvrSetCpuPartition(task_id, "/application");
57   EXPECT_EQ(-EINVAL, error);
58 
59   // Test setting the partition for a task that doesn't belong to us.
60   error = dvrSetCpuPartition(1, "/application");
61   EXPECT_EQ(-EINVAL, error);
62 
63   // Test setting the partition to one that doesn't exist.
64   error = dvrSetCpuPartition(0, "/foobar");
65   EXPECT_EQ(-ENOENT, error);
66 }
67 
TEST(PerformanceTest,SetSchedulerClass)68 TEST(PerformanceTest, SetSchedulerClass) {
69   int error;
70 
71   // TODO(eieio): Test all supported scheduler classes and priority levels.
72 
73   error = dvrSetSchedulerClass(0, "background");
74   EXPECT_EQ(0, error);
75   EXPECT_EQ(SCHED_BATCH, sched_getscheduler(0));
76 
77   error = dvrSetSchedulerClass(0, "audio:low");
78   EXPECT_EQ(0, error);
79   EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0));
80 
81   error = dvrSetSchedulerClass(0, "normal");
82   EXPECT_EQ(0, error);
83   EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0));
84 
85   error = dvrSetSchedulerClass(0, "foobar");
86   EXPECT_EQ(-EINVAL, error);
87 }
88 
TEST(PerformanceTest,SchedulerClassResetOnFork)89 TEST(PerformanceTest, SchedulerClassResetOnFork) {
90   int error;
91 
92   error = dvrSetSchedulerClass(0, "graphics:high");
93   EXPECT_EQ(0, error);
94   EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0));
95 
96   int scheduler = -1;
97   std::thread thread([&]() { scheduler = sched_getscheduler(0); });
98   thread.join();
99 
100   EXPECT_EQ(SCHED_NORMAL, scheduler);
101 
102   // Return to SCHED_NORMAL.
103   error = dvrSetSchedulerClass(0, "normal");
104   EXPECT_EQ(0, error);
105   EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0));
106 }
107 
TEST(PerformanceTest,GetCpuPartition)108 TEST(PerformanceTest, GetCpuPartition) {
109   int error;
110   char partition[PATH_MAX + 1];
111 
112   error = dvrSetCpuPartition(0, "/");
113   ASSERT_EQ(0, error);
114 
115   error = dvrGetCpuPartition(0, partition, sizeof(partition));
116   EXPECT_EQ(0, error);
117   EXPECT_EQ("/", std::string(partition));
118 
119   error = dvrSetCpuPartition(0, "/application");
120   EXPECT_EQ(0, error);
121 
122   error = dvrGetCpuPartition(0, partition, sizeof(partition));
123   EXPECT_EQ(0, error);
124   EXPECT_EQ("/application", std::string(partition));
125 
126   // Test passing a buffer that is too short.
127   error = dvrGetCpuPartition(0, partition, 5);
128   EXPECT_EQ(-ENOBUFS, error);
129 
130   // Test getting the partition for a task that doesn't belong to us.
131   error = dvrGetCpuPartition(1, partition, sizeof(partition));
132   EXPECT_EQ(-EINVAL, error);
133 
134   // Test passing a nullptr value for partition buffer.
135   error = dvrGetCpuPartition(0, nullptr, sizeof(partition));
136   EXPECT_EQ(-EINVAL, error);
137 }
138