• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 <gtest/gtest.h>
18 #include <string>
19 
20 #include "chre/platform/atomic.h"
21 #include "chre/platform/condition_variable.h"
22 #include "chre/platform/mutex.h"
23 #include "chre/platform/shared/log_buffer.h"
24 
25 namespace chre {
26 
27 // TODO(b/146164384): Test that the onLogsReady callback is called
28 //                    asynchronously
29 
30 class TestLogBufferCallback : public LogBufferCallbackInterface {
31  public:
onLogsReady()32   void onLogsReady() {
33     // Do nothing
34   }
35 };
36 
37 static constexpr size_t kDefaultBufferSize = 1024;
38 
39 // Helpers
copyStringWithOffset(char * destination,const char * source,size_t sourceOffset)40 void copyStringWithOffset(char *destination, const char *source,
41                           size_t sourceOffset) {
42   size_t strlength = strlen(source + sourceOffset);
43   // +1 to copy nullbyte on the end
44   memcpy(destination, source + sourceOffset, strlength + 1);
45 }
46 
TEST(LogBuffer,HandleOneLogAndCopy)47 TEST(LogBuffer, HandleOneLogAndCopy) {
48   char buffer[kDefaultBufferSize];
49   constexpr size_t kOutBufferSize = 20;
50   char outBuffer[kOutBufferSize];
51   const char *testLogStr = "test";
52   char testedBuffer[kOutBufferSize];
53   TestLogBufferCallback callback;
54 
55   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
56   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStr);
57   size_t numLogsDropped;
58   size_t bytesCopied =
59       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
60 
61   EXPECT_EQ(bytesCopied, strlen(testLogStr) + LogBuffer::kLogDataOffset + 1);
62   copyStringWithOffset(testedBuffer, outBuffer, LogBuffer::kLogDataOffset);
63   EXPECT_TRUE(strcmp(testedBuffer, testLogStr) == 0);
64 }
65 
TEST(LogBuffer,HandleTwoLogsAndCopy)66 TEST(LogBuffer, HandleTwoLogsAndCopy) {
67   char buffer[kDefaultBufferSize];
68   constexpr size_t kOutBufferSize = 30;
69   char outBuffer[kOutBufferSize];
70   const char *testLogStr = "test";
71   const char *testLogStr2 = "test2";
72   char testedBuffer[kOutBufferSize];
73   TestLogBufferCallback callback;
74 
75   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
76   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStr);
77   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStr2);
78   size_t numLogsDropped;
79   size_t bytesCopied =
80       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
81 
82   EXPECT_EQ(bytesCopied, strlen(testLogStr) + strlen(testLogStr2) +
83                              2 * LogBuffer::kLogDataOffset + 2);
84   copyStringWithOffset(testedBuffer, outBuffer, LogBuffer::kLogDataOffset);
85   EXPECT_TRUE(strcmp(testedBuffer, testLogStr) == 0);
86   copyStringWithOffset(testedBuffer, outBuffer,
87                        2 * LogBuffer::kLogDataOffset + strlen(testLogStr) + 1);
88   EXPECT_TRUE(strcmp(testedBuffer, testLogStr2) == 0);
89 }
90 
TEST(LogBuffer,FailOnMoreCopyThanHandle)91 TEST(LogBuffer, FailOnMoreCopyThanHandle) {
92   char buffer[kDefaultBufferSize];
93   constexpr size_t kOutBufferSize = 20;
94   char outBuffer[kOutBufferSize];
95   const char *testLogStr = "test";
96   TestLogBufferCallback callback;
97 
98   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
99   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStr);
100   size_t numLogsDropped;
101   logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
102   size_t bytesCopied =
103       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
104 
105   EXPECT_EQ(bytesCopied, 0);
106 }
107 
TEST(LogBuffer,FailOnHandleLargerLogThanBufferSize)108 TEST(LogBuffer, FailOnHandleLargerLogThanBufferSize) {
109   char buffer[kDefaultBufferSize];
110   constexpr size_t kOutBufferSize = 20;
111   char outBuffer[kOutBufferSize];
112   // Note the size of this log is too big to fit in the buffer that we are
113   // using for the LogBuffer object
114   std::string testLogStrStr(1025, 'a');
115   TestLogBufferCallback callback;
116 
117   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
118   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStrStr.c_str());
119   size_t numLogsDropped;
120   size_t bytesCopied =
121       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
122 
123   // Should not be able to read this log out because there should be no log in
124   // the first place
125   EXPECT_EQ(bytesCopied, 0);
126 }
127 
TEST(LogBuffer,LogOverwritten)128 TEST(LogBuffer, LogOverwritten) {
129   char buffer[kDefaultBufferSize];
130   constexpr size_t kOutBufferSize = 200;
131   char outBuffer[kOutBufferSize];
132   char testedBuffer[kOutBufferSize];
133   TestLogBufferCallback callback;
134   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
135 
136   // This for loop adds 1060 bytes of data through the buffer which is > than
137   // 1024
138   for (size_t i = 0; i < 10; i++) {
139     std::string testLogStrStr(100, 'a' + i);
140     const char *testLogStr = testLogStrStr.c_str();
141     logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStr);
142   }
143   size_t numLogsDropped;
144   size_t bytesCopied =
145       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
146   memcpy(testedBuffer, outBuffer + LogBuffer::kLogDataOffset, 101);
147 
148   // Should have read out the second from front test log string which is 'a' + 1
149   // = 'b'
150   EXPECT_TRUE(strcmp(testedBuffer, std::string(100, 'b').c_str()) == 0);
151   EXPECT_EQ(bytesCopied, LogBuffer::kLogDataOffset + 100 + 1);
152   // Should have dropped the first log
153   EXPECT_EQ(numLogsDropped, 1);
154 }
155 
TEST(LogBuffer,CopyIntoEmptyBuffer)156 TEST(LogBuffer, CopyIntoEmptyBuffer) {
157   char buffer[kDefaultBufferSize];
158   constexpr size_t kOutBufferSize = 0;
159   char outBuffer[kOutBufferSize];
160   TestLogBufferCallback callback;
161   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
162 
163   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, "test");
164   size_t numLogsDropped;
165   size_t bytesCopied =
166       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
167 
168   EXPECT_EQ(bytesCopied, 0);
169 }
170 
TEST(LogBuffer,NoCopyInfoBufferAfterHandleEmptyLog)171 TEST(LogBuffer, NoCopyInfoBufferAfterHandleEmptyLog) {
172   char buffer[kDefaultBufferSize];
173   constexpr size_t kOutBufferSize = 200;
174   char outBuffer[kOutBufferSize];
175   TestLogBufferCallback callback;
176   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
177 
178   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, "");
179   size_t numLogsDropped;
180   size_t bytesCopied =
181       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
182 
183   EXPECT_EQ(bytesCopied, 0);
184 }
185 
TEST(LogBuffer,HandleLogOfNullBytes)186 TEST(LogBuffer, HandleLogOfNullBytes) {
187   char buffer[kDefaultBufferSize];
188   constexpr size_t kOutBufferSize = 200;
189   char outBuffer[kOutBufferSize];
190   TestLogBufferCallback callback;
191   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
192 
193   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, "\0\0\0");
194   size_t numLogsDropped;
195   size_t bytesCopied =
196       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
197 
198   EXPECT_EQ(bytesCopied, 0);
199 }
200 
TEST(LogBuffer,TruncateLongLog)201 TEST(LogBuffer, TruncateLongLog) {
202   char buffer[kDefaultBufferSize];
203   constexpr size_t kOutBufferSize = 500;
204   char outBuffer[kOutBufferSize];
205   TestLogBufferCallback callback;
206   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
207   std::string testStr(256, 'a');
208 
209   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testStr.c_str());
210   size_t numLogsDropped;
211   size_t bytesCopied =
212       logBuffer.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
213 
214   // Should truncate the logs down to the kLogMaxSize value of 255 by the time
215   // it is copied out.
216   EXPECT_EQ(bytesCopied, 255);
217 }
218 
TEST(LogBuffer,WouldCauseOverflowTest)219 TEST(LogBuffer, WouldCauseOverflowTest) {
220   char buffer[kDefaultBufferSize];
221   TestLogBufferCallback callback;
222   LogBuffer logBuffer(&callback, buffer, kDefaultBufferSize);
223 
224   // With an empty buffer inerting one character should not overflow
225   // ASSERT because if this fails the next ASSERT statement is undefined most
226   // likely.
227   ASSERT_FALSE(logBuffer.logWouldCauseOverflow(1));
228 
229   // This for loop adds 1000 bytes of data. There is 24 bytes of space left in
230   // the buffer after this loop.
231   for (size_t i = 0; i < 10; i++) {
232     std::string testLogStrStr(94, 'a');
233     const char *testLogStr = testLogStrStr.c_str();
234     logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStr);
235   }
236 
237   std::string testLogStrStr(11, 'a');
238   const char *testLogStr = testLogStrStr.c_str();
239   // After this log entry there is room enough for a log of character size 1.
240   logBuffer.handleLog(LogBufferLogLevel::INFO, 0, testLogStr);
241 
242   // There should be just enough space for this log
243   ASSERT_FALSE(logBuffer.logWouldCauseOverflow(1));
244 
245   // Inserting any more than a one char log should cause overflow
246   ASSERT_TRUE(logBuffer.logWouldCauseOverflow(2));
247 }
248 
TEST(LogBuffer,TransferTest)249 TEST(LogBuffer, TransferTest) {
250   char buffer[kDefaultBufferSize];
251   const size_t kOutBufferSize = 10;
252   char outBuffer[kOutBufferSize];
253   size_t numLogsDropped;
254   TestLogBufferCallback callback;
255   LogBuffer logBufferFrom(&callback, buffer, kDefaultBufferSize);
256   LogBuffer logBufferTo(&callback, buffer, kDefaultBufferSize);
257 
258   const char *str1 = "str1";
259   const char *str2 = "str2";
260   const char *str3 = "str3";
261 
262   logBufferFrom.handleLog(LogBufferLogLevel::INFO, 0, str1);
263   logBufferFrom.handleLog(LogBufferLogLevel::INFO, 0, str2);
264   logBufferFrom.handleLog(LogBufferLogLevel::INFO, 0, str3);
265 
266   logBufferFrom.transferTo(logBufferTo);
267 
268   // The logs should have the text of each of the logs pushed onto the From
269   // buffer in FIFO ordering.
270   logBufferTo.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
271   ASSERT_TRUE(strcmp(outBuffer + LogBuffer::kLogDataOffset, str1) == 0);
272   logBufferTo.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
273   ASSERT_TRUE(strcmp(outBuffer + LogBuffer::kLogDataOffset, str2) == 0);
274   logBufferTo.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
275   ASSERT_TRUE(strcmp(outBuffer + LogBuffer::kLogDataOffset, str3) == 0);
276 
277   size_t bytesCopied =
278       logBufferTo.copyLogs(outBuffer, kOutBufferSize, &numLogsDropped);
279   // There should have been no logs left in the To buffer for that last copyLogs
280   ASSERT_EQ(bytesCopied, 0);
281 }
282 
283 // TODO(srok): Add multithreaded tests
284 
285 }  // namespace chre
286