1 /*
2  * Copyright (C) 2013-2014 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 <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include <benchmark/benchmark.h>
22 
23 static const char begin[] = "--------- beginning of ";
24 
BM_logcat_sorted_order(benchmark::State & state)25 static void BM_logcat_sorted_order(benchmark::State& state) {
26     FILE* fp;
27 
28     if (!state.KeepRunning()) return;
29 
30     fp = popen(
31         "logcat -v time -b radio -b events -b system -b main -d 2>/dev/null",
32         "r");
33     if (!fp) return;
34 
35     class timestamp {
36        private:
37         int month;
38         int day;
39         int hour;
40         int minute;
41         int second;
42         int millisecond;
43         bool ok;
44 
45        public:
46         void init(const char* buffer) {
47             ok = false;
48             if (buffer != NULL) {
49                 ok = sscanf(buffer, "%d-%d %d:%d:%d.%d ", &month, &day, &hour,
50                             &minute, &second, &millisecond) == 6;
51             }
52         }
53 
54         explicit timestamp(const char* buffer) {
55             init(buffer);
56         }
57 
58         bool operator<(timestamp& T) {
59             return !ok || !T.ok || (month < T.month) ||
60                    ((month == T.month) &&
61                     ((day < T.day) ||
62                      ((day == T.day) &&
63                       ((hour < T.hour) ||
64                        ((hour == T.hour) &&
65                         ((minute < T.minute) ||
66                          ((minute == T.minute) &&
67                           ((second < T.second) ||
68                            ((second == T.second) &&
69                             (millisecond < T.millisecond))))))))));
70         }
71 
72         bool valid(void) {
73             return ok;
74         }
75     } last(NULL);
76 
77     char* last_buffer = NULL;
78     char buffer[5120];
79 
80     int count = 0;
81     int next_lt_last = 0;
82 
83     while (fgets(buffer, sizeof(buffer), fp)) {
84         if (!strncmp(begin, buffer, sizeof(begin) - 1)) {
85             continue;
86         }
87         if (!last.valid()) {
88             free(last_buffer);
89             last_buffer = strdup(buffer);
90             last.init(buffer);
91         }
92         timestamp next(buffer);
93         if (next < last) {
94             if (last_buffer) {
95                 fprintf(stderr, "<%s", last_buffer);
96             }
97             fprintf(stderr, ">%s", buffer);
98             ++next_lt_last;
99         }
100         if (next.valid()) {
101             free(last_buffer);
102             last_buffer = strdup(buffer);
103             last.init(buffer);
104         }
105         ++count;
106     }
107     free(last_buffer);
108 
109     pclose(fp);
110 
111     static const int max_ok = 2;
112 
113     // Allow few fails, happens with readers active
114     fprintf(stderr, "%s: %d/%d out of order entries\n",
115             (next_lt_last) ? ((next_lt_last <= max_ok) ? "WARNING" : "ERROR")
116                            : "INFO",
117             next_lt_last, count);
118 
119     if (next_lt_last > max_ok) {
120         fprintf(stderr, "EXPECT_GE(max_ok=%d, next_lt_last=%d)\n", max_ok,
121                 next_lt_last);
122     }
123 
124     // sample statistically too small
125     if (count < 100) {
126         fprintf(stderr, "EXPECT_LT(100, count=%d)\n", count);
127     }
128 
129     state.KeepRunning();
130 }
131 BENCHMARK(BM_logcat_sorted_order);
132 
133 BENCHMARK_MAIN();
134