OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_ |
| 6 #define BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_ |
| 7 #pragma once |
| 8 |
| 9 #include "base/debug/trace_event.h" |
| 10 |
| 11 namespace base { |
| 12 namespace debug { |
| 13 |
| 14 namespace trace { |
| 15 |
| 16 class QueryNode; |
| 17 |
| 18 // Pass these values to Query to compare with the corresponding member of a |
| 19 // TraceEvent. |
| 20 enum TraceEventMember { |
| 21 EVENT_INVALID=0, |
| 22 EVENT_PID, |
| 23 EVENT_TID, |
| 24 // Return the timestamp of the event in microseconds since epoch. |
| 25 EVENT_TIME, |
| 26 // Return the duration of an event in seconds. |
| 27 // Only works for events with associated BEGIN/END: Query(OTHER_EXISTS). |
| 28 EVENT_DURATION, |
| 29 EVENT_PHASE, |
| 30 EVENT_CATEGORY, |
| 31 EVENT_NAME, |
| 32 EVENT_HAS_ARG, |
| 33 EVENT_ARG, |
| 34 // Return true if associated event exists (BEGIN for END or END for BEGIN). |
| 35 EVENT_HAS_OTHER, |
| 36 // Use these to access the associated BEGIN/END event's members: |
| 37 OTHER_PID, |
| 38 OTHER_TID, |
| 39 OTHER_TIME, |
| 40 OTHER_PHASE, |
| 41 OTHER_HAS_ARG, |
| 42 OTHER_ARG |
| 43 }; |
| 44 |
| 45 // Use Query with TraceAnalyzer to search for specific events. |
| 46 // Queries can be combined using boolean and comparison operators. |
| 47 // For example: |
| 48 // Query q = (Query(EVENT_NAME) == "my_event" && |
| 49 // Query(OTHER_EXISTS) && |
| 50 // Query(EVENT_DURATION) > 1000000.0/60.0); |
| 51 class Query { |
| 52 public: |
| 53 // Compare with the given member. |
| 54 Query(TraceEventMember member); |
| 55 // Compare with the given member argument value. |
| 56 Query(TraceEventMember member, const std::string& arg_name); |
| 57 // Compare with the given string. |
| 58 Query(const std::string& str); |
| 59 Query(const char* str) { *this = Query(std::string(str)); } |
| 60 // Compare with the given number. |
| 61 Query(double num); |
| 62 Query(float num) { *this = Query(static_cast<double>(num)); } |
| 63 Query(int num) { *this = Query(static_cast<double>(num)); } |
| 64 Query(uint32 num) { *this = Query(static_cast<double>(num)); } |
| 65 Query(bool boolean) { *this = Query(static_cast<double>(boolean ? 1 : 0)); } |
| 66 Query(TraceEventPhase phase) { *this = Query(static_cast<double>(phase)); } |
| 67 ~Query(); |
| 68 |
| 69 // Compare with the given string pattern. Only works with == and != operators. |
| 70 static Query Pattern(const std::string& pattern); |
| 71 |
| 72 // Common queries: |
| 73 |
| 74 // Find BEGIN events that have a corresponding END event. |
| 75 static Query MatchBeginWithEnd() { |
| 76 return (Query(EVENT_PHASE) == TRACE_EVENT_PHASE_BEGIN) && |
| 77 Query(EVENT_HAS_OTHER); |
| 78 } |
| 79 |
| 80 // Find END events that have a corresponding BEGIN event. |
| 81 static Query MatchEndWithBegin() { |
| 82 return (Query(EVENT_PHASE) == TRACE_EVENT_PHASE_END) && |
| 83 Query(EVENT_HAS_OTHER); |
| 84 } |
| 85 |
| 86 // Find BEGIN events of given |name| which also have associated END events. |
| 87 static Query MatchBeginName(const std::string& name) { |
| 88 return (Query(EVENT_NAME) == name) && MatchBeginWithEnd(); |
| 89 } |
| 90 |
| 91 // Match given Process ID and Thread ID. |
| 92 static Query MatchPidTid(base::debug::TestTraceEvent::PidTid pid_tid) { |
| 93 return (Query(EVENT_PID) == pid_tid.pid) && |
| 94 (Query(EVENT_TID) == pid_tid.tid); |
| 95 } |
| 96 |
| 97 // Match BEGIN/END event pair that spans multiple threads. |
| 98 static Query MatchCrossPidTid() { |
| 99 return (Query(EVENT_PID) != Query(OTHER_PID)) || |
| 100 (Query(EVENT_TID) != Query(OTHER_TID)); |
| 101 } |
| 102 |
| 103 Query operator==(const Query& rhs) const; |
| 104 Query operator!=(const Query& rhs) const; |
| 105 Query operator< (const Query& rhs) const; |
| 106 Query operator<=(const Query& rhs) const; |
| 107 Query operator> (const Query& rhs) const; |
| 108 Query operator>=(const Query& rhs) const; |
| 109 Query operator&&(const Query& rhs) const; |
| 110 Query operator||(const Query& rhs) const; |
| 111 Query operator! () const; |
| 112 |
| 113 // Return true if the given event matches this query tree. |
| 114 bool Evaluate(const TestTraceEvent& event) const; |
| 115 |
| 116 private: |
| 117 enum Operator { |
| 118 OP_NONE=0, |
| 119 OP_EQ, |
| 120 OP_NE, |
| 121 OP_LT, |
| 122 OP_LE, |
| 123 OP_GT, |
| 124 OP_GE, |
| 125 OP_AND, |
| 126 OP_OR, |
| 127 OP_NOT |
| 128 }; |
| 129 |
| 130 enum QueryType { |
| 131 QUERY_Operator, |
| 132 QUERY_EventMember, |
| 133 QUERY_Number, |
| 134 QUERY_String |
| 135 }; |
| 136 |
| 137 Query(const Query& left, const Query& right, Operator binary_op); |
| 138 Query(const Query& left, Operator unary_op); |
| 139 |
| 140 bool CompareAsDouble(const TestTraceEvent& event, bool* result) const; |
| 141 bool CompareAsString(const TestTraceEvent& event, bool* result) const; |
| 142 bool GetAsDouble(const TestTraceEvent& event, double* num) const; |
| 143 bool GetAsString(const TestTraceEvent& event, std::string* str) const; |
| 144 TraceValue GetMemberValue(const TestTraceEvent& event) const; |
| 145 bool is_value() const { return type_ != QUERY_Operator; } |
| 146 bool is_unary_operator() const { |
| 147 return type_ == QUERY_Operator && operator_ == OP_NOT; |
| 148 } |
| 149 |
| 150 const Query& left() const; |
| 151 const Query& right() const; |
| 152 |
| 153 QueryType type_; |
| 154 Operator operator_; |
| 155 scoped_refptr<QueryNode> left_; |
| 156 scoped_refptr<QueryNode> right_; |
| 157 TraceEventMember member_; |
| 158 double number_; |
| 159 std::string string_; |
| 160 bool is_pattern_; |
| 161 }; |
| 162 |
| 163 // QueryNode allows Query to store a ref-counted query tree. |
| 164 class QueryNode : public RefCounted<QueryNode> { |
| 165 public: |
| 166 QueryNode(const Query& query); |
| 167 const Query& query() const { return query_; } |
| 168 |
| 169 private: |
| 170 friend class RefCounted<QueryNode>; |
| 171 ~QueryNode(); |
| 172 |
| 173 Query query_; |
| 174 }; |
| 175 |
| 176 } // namespace trace |
| 177 |
| 178 // TraceAnalyzer is designed to make tracing-based tests easier to write. |
| 179 // It will grow to provide trace querying capabilities as new use cases are |
| 180 // encountered. |
| 181 class TraceAnalyzer { |
| 182 public: |
| 183 typedef std::vector<base::debug::TestTraceEvent> EventVector; |
| 184 typedef std::vector<base::debug::TestTraceEvent*> EventPtrVector; |
| 185 typedef std::vector<const base::debug::TestTraceEvent*> ConstEventPtrVector; |
| 186 typedef std::map<base::debug::TestTraceEvent::PidTid, |
| 187 EventPtrVector> EventPtrTree; |
| 188 |
| 189 TraceAnalyzer(); |
| 190 TraceAnalyzer(const std::string& json_events); |
| 191 TraceAnalyzer(const EventVector& events); |
| 192 ~TraceAnalyzer(); |
| 193 |
| 194 // Replace all events with |json_events|. |
| 195 void SetEvents(const std::string& json_events); |
| 196 // Replace all events with |events|. |
| 197 void SetEvents(const EventVector& events); |
| 198 |
| 199 const EventVector& events() { return raw_events_; } |
| 200 |
| 201 const std::string& GetThreadName(const base::debug::TestTraceEvent::PidTid& |
| 202 pid_tid); |
| 203 |
| 204 // Find all events that match query: |
| 205 size_t FindEvents(const trace::Query& query, |
| 206 ConstEventPtrVector* output) const; |
| 207 |
| 208 // Helper method: find first event that matches query |
| 209 const base::debug::TestTraceEvent* FindEvent( |
| 210 const trace::Query& query) const; |
| 211 |
| 212 private: |
| 213 // After collecting all events, this will collapse BEGIN/END pairs and |
| 214 // create a tree for stacked BEGIN/END pairs, separated by thread id. For |
| 215 // BEGIN/END pairs that span multiple pids or tids, the collapsed event will |
| 216 // be placed in the map under default key PidTid() (pid=0, tid=0). |
| 217 void AssociateAllEvents(); |
| 218 void AssociateEvents(EventPtrVector& events_input, |
| 219 EventPtrVector& orphans_output); |
| 220 |
| 221 std::map<base::debug::TestTraceEvent::PidTid, std::string> thread_names_; |
| 222 EventVector raw_events_; |
| 223 }; |
| 224 |
| 225 } // namespace debug |
| 226 } // namespace base |
| 227 |
| 228 #endif // BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_ |
OLD | NEW |