1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <general_test/timer_stress_test.h>
18 
19 #include <cinttypes>
20 #include <cstddef>
21 
22 #include <shared/send_message.h>
23 
24 #include <chre.h>
25 
26 using nanoapp_testing::sendFatalFailureToHost;
27 using nanoapp_testing::sendInternalFailureToHost;
28 using nanoapp_testing::sendSuccessToHost;
29 
30 /*
31  * We stress the system by setting more and more timers until the system
32  * runs out.  We then cancel one (CT) and set a new timer post-cancel (NT).
33  * We make sure all the timers we set fire.
34  *
35  * Our stages are:
36  * Stage 0: Successfully cancel CT.
37  * Stage 1: All of our "exhaustion" timers fire.
38  * Stage 2: The new timer, NT, fires.
39  *
40  * After all of our stages have succeeded, we send success to the host.  Note
41  * there is no system requirement that Stage 2 happens after Stage 1, so
42  * we use markSuccess() to track this.
43  */
44 
45 // Allow 1000ms to create the large number of timers specified below. This
46 // equates to approximately 1ms per timer which should give ample time for
47 // timer creation to complete.
48 constexpr uint64_t kDuration = UINT64_C(1000000000);
49 
50 // If the system keeps claiming it can set more timers, we don't let it
51 // continue forever.  Instead, we'll cut it off at this limit.  And then
52 // we'll call its bluff, and make sure that all of these timers legitimately
53 // fire.  While it won't be an actual exhaustion test (we never took the
54 // system down to no more timers available), it will still give us confidence
55 // that this CHRE can properly handle any semi-reasonable timer load properly.
56 // 1030 is an arbitrary number, slightly over 2^10.  The hope is this
57 // balances between catching incorrect behavior and the test taking too long.
58 constexpr int32_t kMaxTimersToSet = INT32_C(1030);
59 
60 namespace general_test {
61 
62 namespace {
63 
64 const uint32_t kCookies[] = {0, 1, 2};
65 
66 } // anonymous namespace
67 
startStages()68 void TimerStressTest::startStages() {
69   uint32_t cancelId = chreTimerSet(kDuration, &kCookies[0], true);
70   if (cancelId == CHRE_TIMER_INVALID) {
71     sendFatalFailureToHost("No timers available");
72   }
73 
74   mStage1CallbacksLeft = 0;
75   // We anticipate most CHREs will not reach kMaxTimersToSet.
76   while (mStage1CallbacksLeft < kMaxTimersToSet) {
77     if (chreTimerSet(kDuration, &kCookies[1], true) == CHRE_TIMER_INVALID) {
78       break;
79     }
80     mStage1CallbacksLeft++;
81   }
82   if (mStage1CallbacksLeft == 0) {
83     sendFatalFailureToHost("Insufficient timers available");
84   }
85   if (!chreTimerCancel(cancelId)) {
86     sendFatalFailureToHost("Unable to cancel timer");
87   }
88   markSuccess(0);
89   if (chreTimerSet(kDuration, &kCookies[2], true) == CHRE_TIMER_INVALID) {
90     sendFatalFailureToHost("Unable to set new timer after successful "
91                            "cancel.");
92   }
93 }
94 
TimerStressTest()95 TimerStressTest::TimerStressTest()
96   : Test(CHRE_API_VERSION_1_0),
97     mInMethod(false),
98     mFinishedBitmask(0),
99     mStage1CallbacksLeft(0) {
100 }
101 
setUp(uint32_t messageSize,const void *)102 void TimerStressTest::setUp(uint32_t messageSize, const void * /* message */) {
103   mInMethod = true;
104 
105   if (messageSize != 0) {
106     sendFatalFailureToHost(
107         "TimerStress message expects 0 additional bytes, got ",
108         &messageSize);
109   }
110 
111   startStages();
112 
113   mInMethod = false;
114 }
115 
handleStageEvent(uint32_t index)116 void TimerStressTest::handleStageEvent(uint32_t index) {
117   switch (index) {
118     case 0:
119       sendFatalFailureToHost("Canceled timer fired:", &index);
120       break;
121 
122     case 1:
123       --mStage1CallbacksLeft;
124       if (mStage1CallbacksLeft <= 0) {
125         markSuccess(index);
126       }
127       break;
128 
129     case 2:
130       markSuccess(index);
131       break;
132 
133     default:
134       sendFatalFailureToHost("Unexpected event stage:", &index);
135   }
136 }
137 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)138 void TimerStressTest::handleEvent(uint32_t senderInstanceId,
139                                   uint16_t eventType, const void* eventData) {
140   if (mInMethod) {
141     sendFatalFailureToHost("handleEvent invoked while another nanoapp "
142                            "method is running");
143   }
144   mInMethod = true;
145   if (senderInstanceId != CHRE_INSTANCE_ID) {
146     sendFatalFailureToHost("handleEvent got event from unexpected sender:",
147                            &senderInstanceId);
148   }
149   if (eventType != CHRE_EVENT_TIMER) {
150     unexpectedEvent(eventType);
151   }
152 
153   const uint32_t *data = static_cast<const uint32_t *>(eventData);
154   handleStageEvent(*data);
155 
156   mInMethod = false;
157 }
158 
markSuccess(uint32_t stage)159 void TimerStressTest::markSuccess(uint32_t stage) {
160   chreLog(CHRE_LOG_DEBUG, "Stage %" PRIu32 " succeeded", stage);
161   uint32_t finishedBit = (1 << stage);
162   if ((kAllFinished & finishedBit) == 0) {
163     sendFatalFailureToHost("markSuccess bad stage:", &stage);
164   }
165   if ((mFinishedBitmask & finishedBit) != 0) {
166     sendFatalFailureToHost("timer over-triggered:", &stage);
167   }
168   mFinishedBitmask |= finishedBit;
169   if (mFinishedBitmask == kAllFinished) {
170     sendSuccessToHost();
171   }
172 }
173 
174 
175 }  // namespace general_test
176