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