• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <chrono>
2 #include <errno.h>
3 #include <gtest/gtest.h>
4 #include <pthread.h>
5 #include <string.h>
6 #include <thread>
7 #include <time.h>
8 
9 using namespace testing::ext;
10 
11 class TimerTest : public testing::Test {
SetUp()12     void SetUp() override {}
TearDown()13     void TearDown() override {}
14 };
15 #define SLEEPTIME 100
16 class SignalProcessor {
17 public:
SignalProcessor(int signalNum,void (* handler)(int),int saFlags=0)18     SignalProcessor(int signalNum, void (*handler)(int), int saFlags = 0)
19         : signalNumber_(signalNum), oldAction_(new struct sigaction)
20     {
21         action_ = { .sa_flags = saFlags, .sa_handler = handler };
22         sigaction(signalNumber_, &action_, oldAction_);
23     }
24 
SignalProcessor(int signalNum,void (* action)(int,siginfo_t *,void *),int saFlags=SA_SIGINFO)25     SignalProcessor(int signalNum, void (*action)(int, siginfo_t*, void*), int saFlags = SA_SIGINFO)
26         : signalNumber_(signalNum), oldAction_(new struct sigaction)
27     {
28         action_ = { .sa_flags = saFlags, .sa_sigaction = action };
29         sigaction(signalNumber_, &action_, oldAction_);
30     }
31 
~SignalProcessor()32     ~SignalProcessor()
33     {
34         sigaction(signalNumber_, oldAction_, nullptr);
35         delete oldAction_;
36     }
37 
38 private:
39     const int signalNumber_;
40     struct sigaction action_;
41     struct sigaction* oldAction_;
42 };
43 
44 class Scaler {
45 private:
46     std::atomic<int> value_;
47     timer_t timerId_;
48     struct sigevent se_;
49     bool timerValid_;
50 
CreateTimer()51     void CreateTimer()
52     {
53         if (!timerValid_) {
54             if (timer_create(CLOCK_REALTIME, &se_, &timerId_) == 0) {
55                 timerValid_ = true;
56             }
57         }
58     }
59 
60 public:
Scaler(void (* fn)(sigval))61     explicit Scaler(void (*fn)(sigval)) : value_(0), timerValid_(false)
62     {
63         memset(&se_, 0, sizeof(se_));
64         se_.sigev_notify = SIGEV_THREAD;
65         se_.sigev_notify_function = fn;
66         se_.sigev_value.sival_ptr = this;
67         CreateTimer();
68     }
69 
~Scaler()70     ~Scaler()
71     {
72         if (timerValid_) {
73             if (timerValid_) {
74                 if (timer_delete(timerId_) == 0) {
75                     timerValid_ = false;
76                 }
77             }
78         }
79     }
80 
Value() const81     int Value() const
82     {
83         return value_.load();
84     }
85 
GetTimerValid()86     bool GetTimerValid()
87     {
88         return timerValid_;
89     }
90 
GetTimerid()91     timer_t GetTimerid()
92     {
93         return timerId_;
94     }
95 
Change()96     void Change()
97     {
98         timerValid_ = false;
99     }
100 
SetTimer(time_t valueS,time_t valueNs,time_t intervalS,time_t intervalNs)101     void SetTimer(time_t valueS, time_t valueNs, time_t intervalS, time_t intervalNs)
102     {
103         itimerspec newValue;
104         newValue.it_value.tv_sec = valueS;
105         newValue.it_value.tv_nsec = valueNs;
106         newValue.it_interval.tv_sec = intervalS;
107         newValue.it_interval.tv_nsec = intervalNs;
108         timer_settime(timerId_, 0, &newValue, nullptr);
109     }
110 
ValUpdate()111     bool ValUpdate()
112     {
113         int currentValue = value_;
114         time_t start = time(nullptr);
115         while (currentValue == value_ && (time(nullptr) - start) < 5) {
116             std::this_thread::sleep_for(std::chrono::milliseconds(SLEEPTIME));
117         }
118         return currentValue != value_;
119     }
120 
ScalerFunc(sigval value_)121     static void ScalerFunc(sigval value_)
122     {
123         Scaler* cd = reinterpret_cast<Scaler*>(value_.sival_ptr);
124         ++cd->value_;
125     }
126 
ScaNotifyFunc(sigval value_)127     static void ScaNotifyFunc(sigval value_)
128     {
129         Scaler* cd = reinterpret_cast<Scaler*>(value_.sival_ptr);
130         ++cd->value_;
131         cd->SetTimer(0, 0, 1, 0);
132     }
133 };
134 
NotifyFunction(sigval)135 static void NotifyFunction(sigval) {}
136 static int g_count = 0;
Handler(int sig)137 void Handler(int sig)
138 {
139     g_count++;
140     return;
141 }
142 
143 /**
144  * @tc.name: timer_create_001
145  * @tc.desc: Verify that the "timer_create" function correctly creates a timer with the specified attributes and
146  *           that the "timer_delete" function successfully deletes the created timer.
147  * @tc.type: FUNC
148  **/
149 HWTEST_F(TimerTest, timer_create_001, TestSize.Level1)
150 {
151     struct sigevent sev;
152     timer_t timerid;
153 
154     sev.sigev_notify = SIGEV_SIGNAL;
155     sev.sigev_signo = SIGUSR1;
156     sev.sigev_value.sival_ptr = &timerid;
157     signal(SIGUSR1, Handler);
158     int result = timer_create(CLOCK_REALTIME, &sev, &timerid);
159     EXPECT_EQ(result, 0);
160     EXPECT_EQ(0, timer_delete(timerid));
161 }
162 
163 /**
164  * @tc.name: timer_create_002
165  * @tc.desc: Verify that the "timer_create" function properly handles invalid input arguments and returns the expected
166  *           error code in the event of such errors.
167  * @tc.type: FUNC
168  **/
169 HWTEST_F(TimerTest, timer_create_002, TestSize.Level1)
170 {
171     clockid_t invalid = 13;
172     timer_t timer;
173     EXPECT_EQ(timer_create(invalid, nullptr, &timer), -1);
174     EXPECT_EQ(EINVAL, errno);
175 
176     sigevent sev;
177     memset(&sev, 0, sizeof(sev));
178     sev.sigev_notify = SIGEV_THREAD;
179     sev.sigev_notify_function = NotifyFunction;
180     EXPECT_EQ(-1, timer_create(invalid, &sev, &timer));
181     EXPECT_EQ(EINVAL, errno);
182 }
183 
184 /**
185  * @tc.name: timer_delete_001
186  * @tc.desc: Check if the timer is properly deleted and if the scaler's value remains unchanged after the
187  *           timer is deleted.
188  * @tc.type: FUNC
189  **/
190 HWTEST_F(TimerTest, timer_delete_001, TestSize.Level1)
191 {
192     Scaler scaler(Scaler::ScalerFunc);
193     EXPECT_EQ(0, scaler.Value());
194 
195     scaler.SetTimer(0, 2, 0, 2);
196 
197     EXPECT_TRUE(scaler.ValUpdate());
198     EXPECT_TRUE(scaler.ValUpdate());
199     bool timerValid = scaler.GetTimerValid();
200     timer_t timerid = scaler.GetTimerid();
201     if (timerValid) {
202         if (timer_delete(timerid) == 0) {
203             scaler.Change();
204         }
205     }
206     std::chrono::nanoseconds duration1(500000);
207     std::this_thread::sleep_for(duration1);
208     int value = scaler.Value();
209     std::chrono::nanoseconds duration2(500000);
210     std::this_thread::sleep_for(duration2);
211     EXPECT_EQ(value, scaler.Value());
212 }
213 
214 /**
215  * @tc.name: timer_settime_001
216  * @tc.desc: Verify that the "SetTimer" function of the "Scaler" object correctly sets the expiration time for a timer
217  *           associated with the object, allowing for proper management and triggering of timers in the system.
218  * @tc.type: FUNC
219  **/
220 HWTEST_F(TimerTest, timer_settime_001, TestSize.Level1)
221 {
222     Scaler scaler(Scaler::ScaNotifyFunc);
223     EXPECT_EQ(0, scaler.Value());
224     scaler.SetTimer(0, 500000000, 1, 0);
225     sleep(1);
226     EXPECT_EQ(1, scaler.Value());
227 }
228 
229 /**
230  * @tc.name: timer_settime_002
231  * @tc.desc: Verify that the "SetTimer" function of the "Scaler" object correctly sets a timer with a reload interval
232  *           and that the timer can be successfully deleted.
233  * @tc.type: FUNC
234  **/
235 HWTEST_F(TimerTest, timer_settime_002, TestSize.Level1)
236 {
237     Scaler scaler(Scaler::ScalerFunc);
238     EXPECT_EQ(0, scaler.Value());
239 
240     scaler.SetTimer(0, 1, 0, 10);
241     // Increase the probability of the timer reaching the set time
242     EXPECT_TRUE(scaler.ValUpdate());
243     EXPECT_TRUE(scaler.ValUpdate());
244     bool timerValid = scaler.GetTimerValid();
245     timer_t timerid = scaler.GetTimerid();
246     if (timerValid) {
247         if (timer_delete(timerid) == 0) {
248             scaler.Change();
249         }
250     }
251     std::chrono::nanoseconds duration(500000);
252     std::this_thread::sleep_for(duration);
253 }