| Index: base/debug/trace_event_test_utils.h
|
| diff --git a/base/debug/trace_event_test_utils.h b/base/debug/trace_event_test_utils.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b97ad131c009952d153ac6c3de7f37ccb6ae6fb2
|
| --- /dev/null
|
| +++ b/base/debug/trace_event_test_utils.h
|
| @@ -0,0 +1,228 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_
|
| +#define BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_
|
| +#pragma once
|
| +
|
| +#include "base/debug/trace_event.h"
|
| +
|
| +namespace base {
|
| +namespace debug {
|
| +
|
| +namespace trace {
|
| +
|
| +class QueryNode;
|
| +
|
| +// Pass these values to Query to compare with the corresponding member of a
|
| +// TraceEvent.
|
| +enum TraceEventMember {
|
| + EVENT_INVALID=0,
|
| + EVENT_PID,
|
| + EVENT_TID,
|
| + // Return the timestamp of the event in microseconds since epoch.
|
| + EVENT_TIME,
|
| + // Return the duration of an event in seconds.
|
| + // Only works for events with associated BEGIN/END: Query(OTHER_EXISTS).
|
| + EVENT_DURATION,
|
| + EVENT_PHASE,
|
| + EVENT_CATEGORY,
|
| + EVENT_NAME,
|
| + EVENT_HAS_ARG,
|
| + EVENT_ARG,
|
| + // Return true if associated event exists (BEGIN for END or END for BEGIN).
|
| + EVENT_HAS_OTHER,
|
| + // Use these to access the associated BEGIN/END event's members:
|
| + OTHER_PID,
|
| + OTHER_TID,
|
| + OTHER_TIME,
|
| + OTHER_PHASE,
|
| + OTHER_HAS_ARG,
|
| + OTHER_ARG
|
| +};
|
| +
|
| +// Use Query with TraceAnalyzer to search for specific events.
|
| +// Queries can be combined using boolean and comparison operators.
|
| +// For example:
|
| +// Query q = (Query(EVENT_NAME) == "my_event" &&
|
| +// Query(OTHER_EXISTS) &&
|
| +// Query(EVENT_DURATION) > 1000000.0/60.0);
|
| +class Query {
|
| + public:
|
| + // Compare with the given member.
|
| + Query(TraceEventMember member);
|
| + // Compare with the given member argument value.
|
| + Query(TraceEventMember member, const std::string& arg_name);
|
| + // Compare with the given string.
|
| + Query(const std::string& str);
|
| + Query(const char* str) { *this = Query(std::string(str)); }
|
| + // Compare with the given number.
|
| + Query(double num);
|
| + Query(float num) { *this = Query(static_cast<double>(num)); }
|
| + Query(int num) { *this = Query(static_cast<double>(num)); }
|
| + Query(uint32 num) { *this = Query(static_cast<double>(num)); }
|
| + Query(bool boolean) { *this = Query(static_cast<double>(boolean ? 1 : 0)); }
|
| + Query(TraceEventPhase phase) { *this = Query(static_cast<double>(phase)); }
|
| + ~Query();
|
| +
|
| + // Compare with the given string pattern. Only works with == and != operators.
|
| + static Query Pattern(const std::string& pattern);
|
| +
|
| + // Common queries:
|
| +
|
| + // Find BEGIN events that have a corresponding END event.
|
| + static Query MatchBeginWithEnd() {
|
| + return (Query(EVENT_PHASE) == TRACE_EVENT_PHASE_BEGIN) &&
|
| + Query(EVENT_HAS_OTHER);
|
| + }
|
| +
|
| + // Find END events that have a corresponding BEGIN event.
|
| + static Query MatchEndWithBegin() {
|
| + return (Query(EVENT_PHASE) == TRACE_EVENT_PHASE_END) &&
|
| + Query(EVENT_HAS_OTHER);
|
| + }
|
| +
|
| + // Find BEGIN events of given |name| which also have associated END events.
|
| + static Query MatchBeginName(const std::string& name) {
|
| + return (Query(EVENT_NAME) == name) && MatchBeginWithEnd();
|
| + }
|
| +
|
| + // Match given Process ID and Thread ID.
|
| + static Query MatchPidTid(base::debug::TestTraceEvent::PidTid pid_tid) {
|
| + return (Query(EVENT_PID) == pid_tid.pid) &&
|
| + (Query(EVENT_TID) == pid_tid.tid);
|
| + }
|
| +
|
| + // Match BEGIN/END event pair that spans multiple threads.
|
| + static Query MatchCrossPidTid() {
|
| + return (Query(EVENT_PID) != Query(OTHER_PID)) ||
|
| + (Query(EVENT_TID) != Query(OTHER_TID));
|
| + }
|
| +
|
| + Query operator==(const Query& rhs) const;
|
| + Query operator!=(const Query& rhs) const;
|
| + Query operator< (const Query& rhs) const;
|
| + Query operator<=(const Query& rhs) const;
|
| + Query operator> (const Query& rhs) const;
|
| + Query operator>=(const Query& rhs) const;
|
| + Query operator&&(const Query& rhs) const;
|
| + Query operator||(const Query& rhs) const;
|
| + Query operator! () const;
|
| +
|
| + // Return true if the given event matches this query tree.
|
| + bool Evaluate(const TestTraceEvent& event) const;
|
| +
|
| + private:
|
| + enum Operator {
|
| + OP_NONE=0,
|
| + OP_EQ,
|
| + OP_NE,
|
| + OP_LT,
|
| + OP_LE,
|
| + OP_GT,
|
| + OP_GE,
|
| + OP_AND,
|
| + OP_OR,
|
| + OP_NOT
|
| + };
|
| +
|
| + enum QueryType {
|
| + QUERY_Operator,
|
| + QUERY_EventMember,
|
| + QUERY_Number,
|
| + QUERY_String
|
| + };
|
| +
|
| + Query(const Query& left, const Query& right, Operator binary_op);
|
| + Query(const Query& left, Operator unary_op);
|
| +
|
| + bool CompareAsDouble(const TestTraceEvent& event, bool* result) const;
|
| + bool CompareAsString(const TestTraceEvent& event, bool* result) const;
|
| + bool GetAsDouble(const TestTraceEvent& event, double* num) const;
|
| + bool GetAsString(const TestTraceEvent& event, std::string* str) const;
|
| + TraceValue GetMemberValue(const TestTraceEvent& event) const;
|
| + bool is_value() const { return type_ != QUERY_Operator; }
|
| + bool is_unary_operator() const {
|
| + return type_ == QUERY_Operator && operator_ == OP_NOT;
|
| + }
|
| +
|
| + const Query& left() const;
|
| + const Query& right() const;
|
| +
|
| + QueryType type_;
|
| + Operator operator_;
|
| + scoped_refptr<QueryNode> left_;
|
| + scoped_refptr<QueryNode> right_;
|
| + TraceEventMember member_;
|
| + double number_;
|
| + std::string string_;
|
| + bool is_pattern_;
|
| +};
|
| +
|
| +// QueryNode allows Query to store a ref-counted query tree.
|
| +class QueryNode : public RefCounted<QueryNode> {
|
| + public:
|
| + QueryNode(const Query& query);
|
| + const Query& query() const { return query_; }
|
| +
|
| + private:
|
| + friend class RefCounted<QueryNode>;
|
| + ~QueryNode();
|
| +
|
| + Query query_;
|
| +};
|
| +
|
| +} // namespace trace
|
| +
|
| +// TraceAnalyzer is designed to make tracing-based tests easier to write.
|
| +// It will grow to provide trace querying capabilities as new use cases are
|
| +// encountered.
|
| +class TraceAnalyzer {
|
| + public:
|
| + typedef std::vector<base::debug::TestTraceEvent> EventVector;
|
| + typedef std::vector<base::debug::TestTraceEvent*> EventPtrVector;
|
| + typedef std::vector<const base::debug::TestTraceEvent*> ConstEventPtrVector;
|
| + typedef std::map<base::debug::TestTraceEvent::PidTid,
|
| + EventPtrVector> EventPtrTree;
|
| +
|
| + TraceAnalyzer();
|
| + TraceAnalyzer(const std::string& json_events);
|
| + TraceAnalyzer(const EventVector& events);
|
| + ~TraceAnalyzer();
|
| +
|
| + // Replace all events with |json_events|.
|
| + void SetEvents(const std::string& json_events);
|
| + // Replace all events with |events|.
|
| + void SetEvents(const EventVector& events);
|
| +
|
| + const EventVector& events() { return raw_events_; }
|
| +
|
| + const std::string& GetThreadName(const base::debug::TestTraceEvent::PidTid&
|
| + pid_tid);
|
| +
|
| + // Find all events that match query:
|
| + size_t FindEvents(const trace::Query& query,
|
| + ConstEventPtrVector* output) const;
|
| +
|
| + // Helper method: find first event that matches query
|
| + const base::debug::TestTraceEvent* FindEvent(
|
| + const trace::Query& query) const;
|
| +
|
| + private:
|
| + // After collecting all events, this will collapse BEGIN/END pairs and
|
| + // create a tree for stacked BEGIN/END pairs, separated by thread id. For
|
| + // BEGIN/END pairs that span multiple pids or tids, the collapsed event will
|
| + // be placed in the map under default key PidTid() (pid=0, tid=0).
|
| + void AssociateAllEvents();
|
| + void AssociateEvents(EventPtrVector& events_input,
|
| + EventPtrVector& orphans_output);
|
| +
|
| + std::map<base::debug::TestTraceEvent::PidTid, std::string> thread_names_;
|
| + EventVector raw_events_;
|
| +};
|
| +
|
| +} // namespace debug
|
| +} // namespace base
|
| +
|
| +#endif // BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_
|
|
|