1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "logd/LogEventQueue.h"
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <stdio.h>
20
21 #include <thread>
22
23 #include "socket/StatsSocketListener.h"
24 #include "stats_event.h"
25 #include "tests/statsd_test_util.h"
26
27 namespace android {
28 namespace os {
29 namespace statsd {
30
31 using namespace android;
32 using namespace testing;
33
34 using std::unique_ptr;
35
36 namespace {
37
makeStatsEvent(uint64_t timestampNs)38 AStatsEvent* makeStatsEvent(uint64_t timestampNs) {
39 AStatsEvent* statsEvent = AStatsEvent_obtain();
40 AStatsEvent_setAtomId(statsEvent, 10);
41 AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
42 AStatsEvent_build(statsEvent);
43 return statsEvent;
44 }
45
makeLogEvent(uint64_t timestampNs)46 std::unique_ptr<LogEvent> makeLogEvent(uint64_t timestampNs) {
47 AStatsEvent* statsEvent = makeStatsEvent(timestampNs);
48 std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
49 parseStatsEventToLogEvent(statsEvent, logEvent.get());
50 EXPECT_EQ(logEvent->GetElapsedTimestampNs(), timestampNs);
51 return logEvent;
52 }
53
54 } // anonymous namespace
55
56 #ifdef __ANDROID__
TEST(LogEventQueue_test,TestGoodConsumer)57 TEST(LogEventQueue_test, TestGoodConsumer) {
58 LogEventQueue queue(50);
59 int64_t eventTimeNs = 100;
60 std::thread writer([&queue, eventTimeNs] {
61 LogEventQueue::Result result;
62 for (int i = 0; i < 100; i++) {
63 result = queue.push(makeLogEvent(eventTimeNs + i * 1000));
64 EXPECT_TRUE(result.success);
65 std::this_thread::sleep_for(std::chrono::milliseconds(1));
66 }
67 });
68
69 std::thread reader([&queue, eventTimeNs] {
70 for (int i = 0; i < 100; i++) {
71 auto event = queue.waitPop();
72 EXPECT_TRUE(event != nullptr);
73 // All events are in right order.
74 EXPECT_EQ(eventTimeNs + i * 1000, event->GetElapsedTimestampNs());
75 }
76 });
77
78 reader.join();
79 writer.join();
80 }
81
TEST(LogEventQueue_test,TestSlowConsumer)82 TEST(LogEventQueue_test, TestSlowConsumer) {
83 LogEventQueue queue(50);
84 int64_t eventTimeNs = 100;
85 std::thread writer([&queue, eventTimeNs] {
86 int failure_count = 0;
87 LogEventQueue::Result result;
88 for (int i = 0; i < 100; i++) {
89 result = queue.push(makeLogEvent(eventTimeNs + i * 1000));
90 if (!result.success) {
91 failure_count++;
92 }
93 std::this_thread::sleep_for(std::chrono::milliseconds(1));
94 }
95
96 // There is some remote chance that reader thread not get chance to run before writer thread
97 // ends. That's why the following comparison is not "==".
98 // There will be at least 45 events lost due to overflow.
99 EXPECT_TRUE(failure_count >= 45);
100 // The oldest event must be at least the 6th event.
101 EXPECT_TRUE(result.oldestTimestampNs <= (100 + 5 * 1000));
102 });
103
104 std::thread reader([&queue, eventTimeNs] {
105 // The consumer quickly processed 5 events, then it got stuck (not reading anymore).
106 for (int i = 0; i < 5; i++) {
107 auto event = queue.waitPop();
108 EXPECT_TRUE(event != nullptr);
109 // All events are in right order.
110 EXPECT_EQ(eventTimeNs + i * 1000, event->GetElapsedTimestampNs());
111 }
112 });
113
114 reader.join();
115 writer.join();
116 }
117
TEST(LogEventQueue_test,TestQueueMaxSize)118 TEST(LogEventQueue_test, TestQueueMaxSize) {
119 StatsdStats::getInstance().reset();
120
121 LogEventQueue queue(50);
122 LogEventFilter filter;
123 filter.setFilteringEnabled(false);
124
125 int64_t eventTimeNs = 100;
126 int64_t oldestEventNs = 0;
127 int32_t newSize = 0;
128 for (int i = 0; i < 30; i++, eventTimeNs++) {
129 auto statsEvent = makeStatsEvent(eventTimeNs);
130 size_t bufferSize;
131 const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize);
132 StatsSocketListener::processStatsEventBuffer(buffer, bufferSize, 0, 0, queue, filter);
133 AStatsEvent_release(statsEvent);
134 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, i + 1);
135 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos, eventTimeNs);
136 }
137
138 const int32_t lastMaxSizeObserved = StatsdStats::getInstance().mEventQueueMaxSizeObserved;
139 const int64_t lastMaxSizeElapsedNanos =
140 StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos;
141
142 // consumer reads the entire queue
143 int64_t nextEventTs = 100;
144 for (int i = 0; i < 30; i++, nextEventTs++) {
145 auto event = queue.waitPop();
146 EXPECT_TRUE(event != nullptr);
147 // All events are in right order.
148 EXPECT_EQ(nextEventTs, event->GetElapsedTimestampNs());
149 }
150
151 // the expectation after queue drained entirely the max count & ts do not update for
152 // smaller values
153 {
154 auto statsEvent = makeStatsEvent(eventTimeNs);
155 size_t bufferSize;
156 const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize);
157 StatsSocketListener::processStatsEventBuffer(buffer, bufferSize, 0, 0, queue, filter);
158 AStatsEvent_release(statsEvent);
159 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, lastMaxSizeObserved);
160 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos,
161 lastMaxSizeElapsedNanos);
162 eventTimeNs++;
163 }
164
165 for (int i = 0; i < 1; i++, nextEventTs++) {
166 auto event = queue.waitPop();
167 EXPECT_TRUE(event != nullptr);
168 // All events are in right order.
169 EXPECT_EQ(nextEventTs, event->GetElapsedTimestampNs());
170 }
171
172 // the expectation after queue drained entirely the max count & ts do update for
173 // bigger values
174 // fill up to the the previous max values observed - stats are not changed
175 for (int i = 0; i < lastMaxSizeObserved; i++, eventTimeNs++) {
176 auto statsEvent = makeStatsEvent(eventTimeNs);
177 size_t bufferSize;
178 const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize);
179 StatsSocketListener::processStatsEventBuffer(buffer, bufferSize, 0, 0, queue, filter);
180 AStatsEvent_release(statsEvent);
181 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, lastMaxSizeObserved);
182 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos,
183 lastMaxSizeElapsedNanos);
184 }
185
186 // add extra elements to update the stats
187 for (int i = 0; i < 10; i++, eventTimeNs++) {
188 auto statsEvent = makeStatsEvent(eventTimeNs);
189 size_t bufferSize;
190 const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize);
191 StatsSocketListener::processStatsEventBuffer(buffer, bufferSize, 0, 0, queue, filter);
192 AStatsEvent_release(statsEvent);
193 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved,
194 lastMaxSizeObserved + i + 1);
195 EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos, eventTimeNs);
196 }
197 }
198
199 #else
200 GTEST_LOG_(INFO) << "This test does nothing.\n";
201 #endif
202
203 } // namespace statsd
204 } // namespace os
205 } // namespace android
206