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