summaryrefslogtreecommitdiffstats
path: root/src/testlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib')
-rw-r--r--src/testlib/3rdparty/linux_perf_event_p.h615
-rw-r--r--src/testlib/doc/src/qttestlib-manual.qdoc8
-rw-r--r--src/testlib/qabstracttestlogger.cpp4
-rw-r--r--src/testlib/qbenchmark.cpp5
-rw-r--r--src/testlib/qbenchmark.h4
-rw-r--r--src/testlib/qbenchmark_p.h12
-rw-r--r--src/testlib/qbenchmarkmetric.cpp124
-rw-r--r--src/testlib/qbenchmarkmetric.h27
-rw-r--r--src/testlib/qbenchmarkmetric_p.h4
-rw-r--r--src/testlib/qbenchmarkperfevents.cpp607
-rw-r--r--src/testlib/qbenchmarkperfevents_p.h88
-rw-r--r--src/testlib/qplaintestlogger.cpp2
-rw-r--r--src/testlib/qsignalspy.h21
-rw-r--r--src/testlib/qsignalspy.qdoc2
-rw-r--r--src/testlib/qtest.h87
-rw-r--r--src/testlib/qtest_global.h4
-rw-r--r--src/testlib/qtest_gui.h4
-rw-r--r--src/testlib/qtest_widgets.h2
-rw-r--r--src/testlib/qtestaccessible.h6
-rw-r--r--src/testlib/qtestassert.h4
-rw-r--r--src/testlib/qtestcase.cpp92
-rw-r--r--src/testlib/qtestcase.h4
-rw-r--r--src/testlib/qtestcoreelement_p.h4
-rw-r--r--src/testlib/qtestcorelist_p.h4
-rw-r--r--src/testlib/qtestdata.h4
-rw-r--r--src/testlib/qtestelement_p.h4
-rw-r--r--src/testlib/qtestelementattribute_p.h4
-rw-r--r--src/testlib/qtestevent.h4
-rw-r--r--src/testlib/qtestevent.qdoc2
-rw-r--r--src/testlib/qtesteventloop.h4
-rw-r--r--src/testlib/qtestkeyboard.h4
-rw-r--r--src/testlib/qtestmouse.h5
-rw-r--r--src/testlib/qtestspontaneevent.h6
-rw-r--r--src/testlib/qtestsystem.h8
-rw-r--r--src/testlib/qtesttouch.h5
-rw-r--r--src/testlib/qtestxunitstreamer_p.h4
-rw-r--r--src/testlib/qxmltestlogger.cpp3
-rw-r--r--src/testlib/qxunittestlogger.cpp4
-rw-r--r--src/testlib/testlib.pro8
39 files changed, 1656 insertions, 147 deletions
diff --git a/src/testlib/3rdparty/linux_perf_event_p.h b/src/testlib/3rdparty/linux_perf_event_p.h
new file mode 100644
index 0000000000..4f63c05d27
--- /dev/null
+++ b/src/testlib/3rdparty/linux_perf_event_p.h
@@ -0,0 +1,615 @@
+/*
+ * Performance events:
+ *
+ * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright (C) 2008-2011, Red Hat, Inc., Ingo Molnar
+ * Copyright (C) 2008-2011, Red Hat, Inc., Peter Zijlstra
+ *
+ * Data type definitions, declarations, prototypes.
+ *
+ * Started by: Thomas Gleixner and Ingo Molnar
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+#ifndef _UAPI_LINUX_PERF_EVENT_H
+#define _UAPI_LINUX_PERF_EVENT_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/byteorder.h>
+
+/*
+ * User-space ABI bits:
+ */
+
+/*
+ * attr.type
+ */
+enum perf_type_id {
+ PERF_TYPE_HARDWARE = 0,
+ PERF_TYPE_SOFTWARE = 1,
+ PERF_TYPE_TRACEPOINT = 2,
+ PERF_TYPE_HW_CACHE = 3,
+ PERF_TYPE_RAW = 4,
+ PERF_TYPE_BREAKPOINT = 5,
+
+ PERF_TYPE_MAX, /* non-ABI */
+};
+
+/*
+ * Generalized performance event event_id types, used by the
+ * attr.event_id parameter of the sys_perf_event_open()
+ * syscall:
+ */
+enum perf_hw_id {
+ /*
+ * Common hardware events, generalized by the kernel:
+ */
+ PERF_COUNT_HW_CPU_CYCLES = 0,
+ PERF_COUNT_HW_INSTRUCTIONS = 1,
+ PERF_COUNT_HW_CACHE_REFERENCES = 2,
+ PERF_COUNT_HW_CACHE_MISSES = 3,
+ PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
+ PERF_COUNT_HW_BRANCH_MISSES = 5,
+ PERF_COUNT_HW_BUS_CYCLES = 6,
+ PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
+ PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
+ PERF_COUNT_HW_REF_CPU_CYCLES = 9,
+
+ PERF_COUNT_HW_MAX, /* non-ABI */
+};
+
+/*
+ * Generalized hardware cache events:
+ *
+ * { L1-D, L1-I, LLC, ITLB, DTLB, BPU, NODE } x
+ * { read, write, prefetch } x
+ * { accesses, misses }
+ */
+enum perf_hw_cache_id {
+ PERF_COUNT_HW_CACHE_L1D = 0,
+ PERF_COUNT_HW_CACHE_L1I = 1,
+ PERF_COUNT_HW_CACHE_LL = 2,
+ PERF_COUNT_HW_CACHE_DTLB = 3,
+ PERF_COUNT_HW_CACHE_ITLB = 4,
+ PERF_COUNT_HW_CACHE_BPU = 5,
+ PERF_COUNT_HW_CACHE_NODE = 6,
+
+ PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
+};
+
+enum perf_hw_cache_op_id {
+ PERF_COUNT_HW_CACHE_OP_READ = 0,
+ PERF_COUNT_HW_CACHE_OP_WRITE = 1,
+ PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
+
+ PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
+};
+
+enum perf_hw_cache_op_result_id {
+ PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
+ PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
+
+ PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
+};
+
+/*
+ * Special "software" events provided by the kernel, even if the hardware
+ * does not support performance events. These events measure various
+ * physical and sw events of the kernel (and allow the profiling of them as
+ * well):
+ */
+enum perf_sw_ids {
+ PERF_COUNT_SW_CPU_CLOCK = 0,
+ PERF_COUNT_SW_TASK_CLOCK = 1,
+ PERF_COUNT_SW_PAGE_FAULTS = 2,
+ PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
+ PERF_COUNT_SW_CPU_MIGRATIONS = 4,
+ PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
+ PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
+ PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
+ PERF_COUNT_SW_EMULATION_FAULTS = 8,
+
+ PERF_COUNT_SW_MAX, /* non-ABI */
+};
+
+/*
+ * Bits that can be set in attr.sample_type to request information
+ * in the overflow packets.
+ */
+enum perf_event_sample_format {
+ PERF_SAMPLE_IP = 1U << 0,
+ PERF_SAMPLE_TID = 1U << 1,
+ PERF_SAMPLE_TIME = 1U << 2,
+ PERF_SAMPLE_ADDR = 1U << 3,
+ PERF_SAMPLE_READ = 1U << 4,
+ PERF_SAMPLE_CALLCHAIN = 1U << 5,
+ PERF_SAMPLE_ID = 1U << 6,
+ PERF_SAMPLE_CPU = 1U << 7,
+ PERF_SAMPLE_PERIOD = 1U << 8,
+ PERF_SAMPLE_STREAM_ID = 1U << 9,
+ PERF_SAMPLE_RAW = 1U << 10,
+ PERF_SAMPLE_BRANCH_STACK = 1U << 11,
+ PERF_SAMPLE_REGS_USER = 1U << 12,
+ PERF_SAMPLE_STACK_USER = 1U << 13,
+
+ PERF_SAMPLE_MAX = 1U << 14, /* non-ABI */
+};
+
+/*
+ * values to program into branch_sample_type when PERF_SAMPLE_BRANCH is set
+ *
+ * If the user does not pass priv level information via branch_sample_type,
+ * the kernel uses the event's priv level. Branch and event priv levels do
+ * not have to match. Branch priv level is checked for permissions.
+ *
+ * The branch types can be combined, however BRANCH_ANY covers all types
+ * of branches and therefore it supersedes all the other types.
+ */
+enum perf_branch_sample_type {
+ PERF_SAMPLE_BRANCH_USER = 1U << 0, /* user branches */
+ PERF_SAMPLE_BRANCH_KERNEL = 1U << 1, /* kernel branches */
+ PERF_SAMPLE_BRANCH_HV = 1U << 2, /* hypervisor branches */
+
+ PERF_SAMPLE_BRANCH_ANY = 1U << 3, /* any branch types */
+ PERF_SAMPLE_BRANCH_ANY_CALL = 1U << 4, /* any call branch */
+ PERF_SAMPLE_BRANCH_ANY_RETURN = 1U << 5, /* any return branch */
+ PERF_SAMPLE_BRANCH_IND_CALL = 1U << 6, /* indirect calls */
+
+ PERF_SAMPLE_BRANCH_MAX = 1U << 7, /* non-ABI */
+};
+
+#define PERF_SAMPLE_BRANCH_PLM_ALL \
+ (PERF_SAMPLE_BRANCH_USER|\
+ PERF_SAMPLE_BRANCH_KERNEL|\
+ PERF_SAMPLE_BRANCH_HV)
+
+/*
+ * Values to determine ABI of the registers dump.
+ */
+enum perf_sample_regs_abi {
+ PERF_SAMPLE_REGS_ABI_NONE = 0,
+ PERF_SAMPLE_REGS_ABI_32 = 1,
+ PERF_SAMPLE_REGS_ABI_64 = 2,
+};
+
+/*
+ * The format of the data returned by read() on a perf event fd,
+ * as specified by attr.read_format:
+ *
+ * struct read_format {
+ * { u64 value;
+ * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
+ * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
+ * { u64 id; } && PERF_FORMAT_ID
+ * } && !PERF_FORMAT_GROUP
+ *
+ * { u64 nr;
+ * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
+ * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
+ * { u64 value;
+ * { u64 id; } && PERF_FORMAT_ID
+ * } cntr[nr];
+ * } && PERF_FORMAT_GROUP
+ * };
+ */
+enum perf_event_read_format {
+ PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0,
+ PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
+ PERF_FORMAT_ID = 1U << 2,
+ PERF_FORMAT_GROUP = 1U << 3,
+
+ PERF_FORMAT_MAX = 1U << 4, /* non-ABI */
+};
+
+#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
+#define PERF_ATTR_SIZE_VER1 72 /* add: config2 */
+#define PERF_ATTR_SIZE_VER2 80 /* add: branch_sample_type */
+#define PERF_ATTR_SIZE_VER3 96 /* add: sample_regs_user */
+ /* add: sample_stack_user */
+
+/*
+ * Hardware event_id to monitor via a performance monitoring event:
+ */
+struct perf_event_attr {
+
+ /*
+ * Major type: hardware/software/tracepoint/etc.
+ */
+ __u32 type;
+
+ /*
+ * Size of the attr structure, for fwd/bwd compat.
+ */
+ __u32 size;
+
+ /*
+ * Type specific configuration information.
+ */
+ __u64 config;
+
+ union {
+ __u64 sample_period;
+ __u64 sample_freq;
+ };
+
+ __u64 sample_type;
+ __u64 read_format;
+
+ __u64 disabled : 1, /* off by default */
+ inherit : 1, /* children inherit it */
+ pinned : 1, /* must always be on PMU */
+ exclusive : 1, /* only group on PMU */
+ exclude_user : 1, /* don't count user */
+ exclude_kernel : 1, /* ditto kernel */
+ exclude_hv : 1, /* ditto hypervisor */
+ exclude_idle : 1, /* don't count when idle */
+ mmap : 1, /* include mmap data */
+ comm : 1, /* include comm data */
+ freq : 1, /* use freq, not period */
+ inherit_stat : 1, /* per task counts */
+ enable_on_exec : 1, /* next exec enables */
+ task : 1, /* trace fork/exit */
+ watermark : 1, /* wakeup_watermark */
+ /*
+ * precise_ip:
+ *
+ * 0 - SAMPLE_IP can have arbitrary skid
+ * 1 - SAMPLE_IP must have constant skid
+ * 2 - SAMPLE_IP requested to have 0 skid
+ * 3 - SAMPLE_IP must have 0 skid
+ *
+ * See also PERF_RECORD_MISC_EXACT_IP
+ */
+ precise_ip : 2, /* skid constraint */
+ mmap_data : 1, /* non-exec mmap data */
+ sample_id_all : 1, /* sample_type all events */
+
+ exclude_host : 1, /* don't count in host */
+ exclude_guest : 1, /* don't count in guest */
+
+ exclude_callchain_kernel : 1, /* exclude kernel callchains */
+ exclude_callchain_user : 1, /* exclude user callchains */
+
+ __reserved_1 : 41;
+
+ union {
+ __u32 wakeup_events; /* wakeup every n events */
+ __u32 wakeup_watermark; /* bytes before wakeup */
+ };
+
+ __u32 bp_type;
+ union {
+ __u64 bp_addr;
+ __u64 config1; /* extension of config */
+ };
+ union {
+ __u64 bp_len;
+ __u64 config2; /* extension of config1 */
+ };
+ __u64 branch_sample_type; /* enum perf_branch_sample_type */
+
+ /*
+ * Defines set of user regs to dump on samples.
+ * See asm/perf_regs.h for details.
+ */
+ __u64 sample_regs_user;
+
+ /*
+ * Defines size of the user stack to dump on samples.
+ */
+ __u32 sample_stack_user;
+
+ /* Align to u64. */
+ __u32 __reserved_2;
+};
+
+#define perf_flags(attr) (*(&(attr)->read_format + 1))
+
+/*
+ * Ioctls that can be done on a perf event fd:
+ */
+#define PERF_EVENT_IOC_ENABLE _IO ('$', 0)
+#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
+#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
+#define PERF_EVENT_IOC_RESET _IO ('$', 3)
+#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64)
+#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
+#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
+
+enum perf_event_ioc_flags {
+ PERF_IOC_FLAG_GROUP = 1U << 0,
+};
+
+/*
+ * Structure of the page that can be mapped via mmap
+ */
+struct perf_event_mmap_page {
+ __u32 version; /* version number of this structure */
+ __u32 compat_version; /* lowest version this is compat with */
+
+ /*
+ * Bits needed to read the hw events in user-space.
+ *
+ * u32 seq, time_mult, time_shift, idx, width;
+ * u64 count, enabled, running;
+ * u64 cyc, time_offset;
+ * s64 pmc = 0;
+ *
+ * do {
+ * seq = pc->lock;
+ * barrier()
+ *
+ * enabled = pc->time_enabled;
+ * running = pc->time_running;
+ *
+ * if (pc->cap_usr_time && enabled != running) {
+ * cyc = rdtsc();
+ * time_offset = pc->time_offset;
+ * time_mult = pc->time_mult;
+ * time_shift = pc->time_shift;
+ * }
+ *
+ * idx = pc->index;
+ * count = pc->offset;
+ * if (pc->cap_usr_rdpmc && idx) {
+ * width = pc->pmc_width;
+ * pmc = rdpmc(idx - 1);
+ * }
+ *
+ * barrier();
+ * } while (pc->lock != seq);
+ *
+ * NOTE: for obvious reason this only works on self-monitoring
+ * processes.
+ */
+ __u32 lock; /* seqlock for synchronization */
+ __u32 index; /* hardware event identifier */
+ __s64 offset; /* add to hardware event value */
+ __u64 time_enabled; /* time event active */
+ __u64 time_running; /* time event on cpu */
+ union {
+ __u64 capabilities;
+ __u64 cap_usr_time : 1,
+ cap_usr_rdpmc : 1,
+ cap_____res : 62;
+ };
+
+ /*
+ * If cap_usr_rdpmc this field provides the bit-width of the value
+ * read using the rdpmc() or equivalent instruction. This can be used
+ * to sign extend the result like:
+ *
+ * pmc <<= 64 - width;
+ * pmc >>= 64 - width; // signed shift right
+ * count += pmc;
+ */
+ __u16 pmc_width;
+
+ /*
+ * If cap_usr_time the below fields can be used to compute the time
+ * delta since time_enabled (in ns) using rdtsc or similar.
+ *
+ * u64 quot, rem;
+ * u64 delta;
+ *
+ * quot = (cyc >> time_shift);
+ * rem = cyc & ((1 << time_shift) - 1);
+ * delta = time_offset + quot * time_mult +
+ * ((rem * time_mult) >> time_shift);
+ *
+ * Where time_offset,time_mult,time_shift and cyc are read in the
+ * seqcount loop described above. This delta can then be added to
+ * enabled and possible running (if idx), improving the scaling:
+ *
+ * enabled += delta;
+ * if (idx)
+ * running += delta;
+ *
+ * quot = count / running;
+ * rem = count % running;
+ * count = quot * enabled + (rem * enabled) / running;
+ */
+ __u16 time_shift;
+ __u32 time_mult;
+ __u64 time_offset;
+
+ /*
+ * Hole for extension of the self monitor capabilities
+ */
+
+ __u64 __reserved[120]; /* align to 1k */
+
+ /*
+ * Control data for the mmap() data buffer.
+ *
+ * User-space reading the @data_head value should issue an rmb(), on
+ * SMP capable platforms, after reading this value -- see
+ * perf_event_wakeup().
+ *
+ * When the mapping is PROT_WRITE the @data_tail value should be
+ * written by userspace to reflect the last read data. In this case
+ * the kernel will not over-write unread data.
+ */
+ __u64 data_head; /* head in the data section */
+ __u64 data_tail; /* user-space written tail */
+};
+
+#define PERF_RECORD_MISC_CPUMODE_MASK (7 << 0)
+#define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0)
+#define PERF_RECORD_MISC_KERNEL (1 << 0)
+#define PERF_RECORD_MISC_USER (2 << 0)
+#define PERF_RECORD_MISC_HYPERVISOR (3 << 0)
+#define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0)
+#define PERF_RECORD_MISC_GUEST_USER (5 << 0)
+
+/*
+ * Indicates that the content of PERF_SAMPLE_IP points to
+ * the actual instruction that triggered the event. See also
+ * perf_event_attr::precise_ip.
+ */
+#define PERF_RECORD_MISC_EXACT_IP (1 << 14)
+/*
+ * Reserve the last bit to indicate some extended misc field
+ */
+#define PERF_RECORD_MISC_EXT_RESERVED (1 << 15)
+
+struct perf_event_header {
+ __u32 type;
+ __u16 misc;
+ __u16 size;
+};
+
+enum perf_event_type {
+
+ /*
+ * If perf_event_attr.sample_id_all is set then all event types will
+ * have the sample_type selected fields related to where/when
+ * (identity) an event took place (TID, TIME, ID, CPU, STREAM_ID)
+ * described in PERF_RECORD_SAMPLE below, it will be stashed just after
+ * the perf_event_header and the fields already present for the existing
+ * fields, i.e. at the end of the payload. That way a newer perf.data
+ * file will be supported by older perf tools, with these new optional
+ * fields being ignored.
+ *
+ * The MMAP events record the PROT_EXEC mappings so that we can
+ * correlate userspace IPs to code. They have the following structure:
+ *
+ * struct {
+ * struct perf_event_header header;
+ *
+ * u32 pid, tid;
+ * u64 addr;
+ * u64 len;
+ * u64 pgoff;
+ * char filename[];
+ * };
+ */
+ PERF_RECORD_MMAP = 1,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u64 id;
+ * u64 lost;
+ * };
+ */
+ PERF_RECORD_LOST = 2,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ *
+ * u32 pid, tid;
+ * char comm[];
+ * };
+ */
+ PERF_RECORD_COMM = 3,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u32 pid, ppid;
+ * u32 tid, ptid;
+ * u64 time;
+ * };
+ */
+ PERF_RECORD_EXIT = 4,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u64 time;
+ * u64 id;
+ * u64 stream_id;
+ * };
+ */
+ PERF_RECORD_THROTTLE = 5,
+ PERF_RECORD_UNTHROTTLE = 6,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u32 pid, ppid;
+ * u32 tid, ptid;
+ * u64 time;
+ * };
+ */
+ PERF_RECORD_FORK = 7,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u32 pid, tid;
+ *
+ * struct read_format values;
+ * };
+ */
+ PERF_RECORD_READ = 8,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ *
+ * { u64 ip; } && PERF_SAMPLE_IP
+ * { u32 pid, tid; } && PERF_SAMPLE_TID
+ * { u64 time; } && PERF_SAMPLE_TIME
+ * { u64 addr; } && PERF_SAMPLE_ADDR
+ * { u64 id; } && PERF_SAMPLE_ID
+ * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
+ * { u32 cpu, res; } && PERF_SAMPLE_CPU
+ * { u64 period; } && PERF_SAMPLE_PERIOD
+ *
+ * { struct read_format values; } && PERF_SAMPLE_READ
+ *
+ * { u64 nr,
+ * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
+ *
+ * #
+ * # The RAW record below is opaque data wrt the ABI
+ * #
+ * # That is, the ABI doesn't make any promises wrt to
+ * # the stability of its content, it may vary depending
+ * # on event, hardware, kernel version and phase of
+ * # the moon.
+ * #
+ * # In other words, PERF_SAMPLE_RAW contents are not an ABI.
+ * #
+ *
+ * { u32 size;
+ * char data[size];}&& PERF_SAMPLE_RAW
+ *
+ * { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
+ *
+ * { u64 abi; # enum perf_sample_regs_abi
+ * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER
+ *
+ * { u64 size;
+ * char data[size];
+ * u64 dyn_size; } && PERF_SAMPLE_STACK_USER
+ * };
+ */
+ PERF_RECORD_SAMPLE = 9,
+
+ PERF_RECORD_MAX, /* non-ABI */
+};
+
+#define PERF_MAX_STACK_DEPTH 127
+
+enum perf_callchain_context {
+ PERF_CONTEXT_HV = (__u64)-32,
+ PERF_CONTEXT_KERNEL = (__u64)-128,
+ PERF_CONTEXT_USER = (__u64)-512,
+
+ PERF_CONTEXT_GUEST = (__u64)-2048,
+ PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176,
+ PERF_CONTEXT_GUEST_USER = (__u64)-2560,
+
+ PERF_CONTEXT_MAX = (__u64)-4095,
+};
+
+#define PERF_FLAG_FD_NO_GROUP (1U << 0)
+#define PERF_FLAG_FD_OUTPUT (1U << 1)
+#define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */
+
+#endif /* _UAPI_LINUX_PERF_EVENT_H */
diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc
index 70bc6112c0..c44bb49ae3 100644
--- a/src/testlib/doc/src/qttestlib-manual.qdoc
+++ b/src/testlib/doc/src/qttestlib-manual.qdoc
@@ -247,6 +247,12 @@
2000.
\li \c -nocrashhandler \br
Disables the crash handler on Unix platforms.
+ \li \c -platform \e name \br
+ This command line argument applies to all Qt applications, but might be
+ especially useful in the context of auto-testing. By using the "offscreen"
+ platform plugin (-platform offscreen) it's possible to have tests that use
+ QWidget or QWindow run without showing anything on the screen. Currently
+ the offscreen platform plugin is only fully supported on X11.
\endlist
\section3 Benchmarking Options
@@ -262,6 +268,8 @@
Counts events received during benchmarks.
\li \c -minimumvalue \e n \br
Sets the minimum acceptable measurement value.
+ \li \c -minimumtotal \e n \br
+ Sets the minimum acceptable total for repeated executions of a test function.
\li \c -iterations \e n \br
Sets the number of accumulation iterations.
\li \c -median \e n \br
diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp
index da7e793341..d039c3c342 100644
--- a/src/testlib/qabstracttestlogger.cpp
+++ b/src/testlib/qabstracttestlogger.cpp
@@ -82,9 +82,9 @@ QAbstractTestLogger::~QAbstractTestLogger()
void QAbstractTestLogger::filterUnprintable(char *str) const
{
- char *idx = str;
+ unsigned char *idx = reinterpret_cast<unsigned char *>(str);
while (*idx) {
- if (((*idx < 0x20 && *idx != '\n' && *idx != '\t') || *idx > 0x7e))
+ if (((*idx < 0x20 && *idx != '\n' && *idx != '\t') || *idx == 0x7f))
*idx = '?';
++idx;
}
diff --git a/src/testlib/qbenchmark.cpp b/src/testlib/qbenchmark.cpp
index 796d817ae2..3ef29e19ce 100644
--- a/src/testlib/qbenchmark.cpp
+++ b/src/testlib/qbenchmark.cpp
@@ -59,6 +59,7 @@ QBenchmarkGlobalData::QBenchmarkGlobalData()
, medianIterationCount(-1)
, createChart(false)
, verboseOutput(false)
+ , minimumTotal(-1)
, mode_(WallTime)
{
setMode(mode_);
@@ -87,6 +88,10 @@ QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer()
} else if (mode_ == CallgrindChildProcess || mode_ == CallgrindParentProcess) {
measurer = new QBenchmarkCallgrindMeasurer;
#endif
+#ifdef QTESTLIB_USE_PERF_EVENTS
+ } else if (mode_ == PerfCounter) {
+ measurer = new QBenchmarkPerfEventsMeasurer;
+#endif
#ifdef HAVE_TICK_COUNTER
} else if (mode_ == TickCounter) {
measurer = new QBenchmarkTickMeasurer;
diff --git a/src/testlib/qbenchmark.h b/src/testlib/qbenchmark.h
index f166955249..ea5023c095 100644
--- a/src/testlib/qbenchmark.h
+++ b/src/testlib/qbenchmark.h
@@ -45,8 +45,6 @@
#include <QtTest/qtest_global.h>
#include <QtTest/qbenchmarkmetric.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -94,6 +92,4 @@ namespace QTest
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QBENCHMARK_H
diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h
index 6b5d996966..351287b103 100644
--- a/src/testlib/qbenchmark_p.h
+++ b/src/testlib/qbenchmark_p.h
@@ -63,12 +63,21 @@
#undef QTESTLIB_USE_VALGRIND
#endif
+#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE) && !defined(Q_OS_ANDROID)
+#define QTESTLIB_USE_PERF_EVENTS
+#else
+#undef QTESTLIB_USE_PERF_EVENTS
+#endif
+
#include <QtTest/private/qbenchmarkmeasurement_p.h>
#include <QtCore/QMap>
#include <QtTest/qtest_global.h>
#ifdef QTESTLIB_USE_VALGRIND
#include <QtTest/private/qbenchmarkvalgrind_p.h>
#endif
+#ifdef QTESTLIB_USE_PERF_EVENTS
+#include <QtTest/private/qbenchmarkperfevents_p.h>
+#endif
#include <QtTest/private/qbenchmarkevent_p.h>
#include <QtTest/private/qbenchmarkmetric_p.h>
@@ -137,7 +146,7 @@ public:
QBenchmarkGlobalData();
~QBenchmarkGlobalData();
- enum Mode { WallTime, CallgrindParentProcess, CallgrindChildProcess, TickCounter, EventCounter };
+ enum Mode { WallTime, CallgrindParentProcess, CallgrindChildProcess, PerfCounter, TickCounter, EventCounter };
void setMode(Mode mode);
Mode mode() const { return mode_; }
QBenchmarkMeasurerBase *createMeasurer();
@@ -151,6 +160,7 @@ public:
bool createChart;
bool verboseOutput;
QString callgrindOutFileBase;
+ int minimumTotal;
private:
Mode mode_;
};
diff --git a/src/testlib/qbenchmarkmetric.cpp b/src/testlib/qbenchmarkmetric.cpp
index ca802e3688..727b9fb912 100644
--- a/src/testlib/qbenchmarkmetric.cpp
+++ b/src/testlib/qbenchmarkmetric.cpp
@@ -51,19 +51,39 @@
\value BitsPerSecond Bits per second
\value BytesPerSecond Bytes per second
\value WalltimeMilliseconds Clock time in milliseconds
- \value CPUTicks CPU time
- \value InstructionReads Instruction reads
- \value Events Event count
\value WalltimeNanoseconds Clock time in nanoseconds
\value BytesAllocated Memory usage in bytes
+ \value Events Event count
+ \value CPUTicks CPU time
+ \value CPUMigrations Process migrations between CPUs
+ \value CPUCycles CPU cycles
+ \value BusCycles Bus cycles
+ \value StalledCycles Cycles stalled
+ \value InstructionReads Instruction reads
+ \value Instructions Instructions executed
+ \value BranchInstructions Branch-type instructions
+ \value BranchMisses Branch instructions that were mispredicted
+ \value CacheReferences Cache accesses of any type
+ \value CacheMisses Cache misses of any type
+ \value CacheReads Cache reads / loads
+ \value CacheReadMisses Cache read / load misses
+ \value CacheWrites Cache writes / stores
+ \value CacheWriteMisses Cache write / store misses
+ \value CachePrefetches Cache prefetches
+ \value CachePrefetchMisses Cache prefetch misses
+ \value ContextSwitches Context switches
+ \value PageFaults Page faults of any type
+ \value MinorPageFaults Minor page faults
+ \value MajorPageFaults Major page faults
+ \value AlignmentFaults Faults caused due to misalignment
+ \value EmulationFaults Faults that needed software emulation
+
+ \sa QTest::benchmarkMetricName(), QTest::benchmarkMetricUnit()
Note that \c WalltimeNanoseconds and \c BytesAllocated are
only provided for use via \l setBenchmarkResult(), and results
in those metrics are not able to be provided automatically
by the QTest framework.
-
- \sa QTest::benchmarkMetricName(), QTest::benchmarkMetricUnit()
-
*/
/*!
@@ -82,16 +102,58 @@ const char * QTest::benchmarkMetricName(QBenchmarkMetric metric)
return "BytesPerSecond";
case WalltimeMilliseconds:
return "WalltimeMilliseconds";
+ case Events:
+ return "Events";
case CPUTicks:
return "CPUTicks";
+ case CPUMigrations:
+ return "CPUMigrations";
+ case CPUCycles:
+ return "CPUCycles";
+ case BusCycles:
+ return "BusCycles";
+ case StalledCycles:
+ return "StalledCycles";
case InstructionReads:
return "InstructionReads";
- case Events:
- return "Events";
+ case Instructions:
+ return "Instructions";
case WalltimeNanoseconds:
return "WalltimeNanoseconds";
case BytesAllocated:
return "BytesAllocated";
+ case BranchInstructions:
+ return "BranchInstructions";
+ case BranchMisses:
+ return "BranchMisses";
+ case CacheReferences:
+ return "CacheReferences";
+ case CacheReads:
+ return "CacheReads";
+ case CacheWrites:
+ return "CacheWrites";
+ case CachePrefetches:
+ return "CachePrefetches";
+ case CacheMisses:
+ return "CacheMisses";
+ case CacheReadMisses:
+ return "CacheReadMisses";
+ case CacheWriteMisses:
+ return "CacheWriteMisses";
+ case CachePrefetchMisses:
+ return "CachePrefetchMisses";
+ case ContextSwitches:
+ return "ContextSwitches";
+ case PageFaults:
+ return "PageFaults";
+ case MinorPageFaults:
+ return "MinorPageFaults";
+ case MajorPageFaults:
+ return "MajorPageFaults";
+ case AlignmentFaults:
+ return "AlignmentFaults";
+ case EmulationFaults:
+ return "EmulationFaults";
default:
return "";
}
@@ -113,16 +175,58 @@ const char * QTest::benchmarkMetricUnit(QBenchmarkMetric metric)
return "bytes/s";
case WalltimeMilliseconds:
return "msecs";
+ case Events:
+ return "events";
case CPUTicks:
return "CPU ticks";
+ case CPUMigrations:
+ return "CPU migrations";
+ case CPUCycles:
+ return "CPU cycles";
+ case BusCycles:
+ return "bus cycles";
+ case StalledCycles:
+ return "stalled cycles";
case InstructionReads:
return "instruction reads";
- case Events:
- return "events";
+ case Instructions:
+ return "instructions";
case WalltimeNanoseconds:
return "nsecs";
case BytesAllocated:
return "bytes";
+ case BranchInstructions:
+ return "branch instructions";
+ case BranchMisses:
+ return "branch misses";
+ case CacheReferences:
+ return "cache references";
+ case CacheReads:
+ return "cache loads";
+ case CacheWrites:
+ return "cache stores";
+ case CachePrefetches:
+ return "cache prefetches";
+ case CacheMisses:
+ return "cache misses";
+ case CacheReadMisses:
+ return "cache load misses";
+ case CacheWriteMisses:
+ return "cache store misses";
+ case CachePrefetchMisses:
+ return "cache prefetch misses";
+ case ContextSwitches:
+ return "context switches";
+ case PageFaults:
+ return "page faults";
+ case MinorPageFaults:
+ return "minor page faults";
+ case MajorPageFaults:
+ return "major page faults";
+ case AlignmentFaults:
+ return "alignment faults";
+ case EmulationFaults:
+ return "emulation faults";
default:
return "";
}
diff --git a/src/testlib/qbenchmarkmetric.h b/src/testlib/qbenchmarkmetric.h
index 9a59156e66..448df3f691 100644
--- a/src/testlib/qbenchmarkmetric.h
+++ b/src/testlib/qbenchmarkmetric.h
@@ -44,8 +44,6 @@
#include <QtTest/qtest_global.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -60,13 +58,32 @@ enum QBenchmarkMetric {
InstructionReads,
Events,
WalltimeNanoseconds,
- BytesAllocated
+ BytesAllocated,
+ CPUMigrations,
+ CPUCycles,
+ BusCycles,
+ StalledCycles,
+ Instructions,
+ BranchInstructions,
+ BranchMisses,
+ CacheReferences,
+ CacheReads,
+ CacheWrites,
+ CachePrefetches,
+ CacheMisses,
+ CacheReadMisses,
+ CacheWriteMisses,
+ CachePrefetchMisses,
+ ContextSwitches,
+ PageFaults,
+ MinorPageFaults,
+ MajorPageFaults,
+ AlignmentFaults,
+ EmulationFaults
};
}
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QBENCHMARK_H
diff --git a/src/testlib/qbenchmarkmetric_p.h b/src/testlib/qbenchmarkmetric_p.h
index ad819e8757..0af2ed2d1a 100644
--- a/src/testlib/qbenchmarkmetric_p.h
+++ b/src/testlib/qbenchmarkmetric_p.h
@@ -56,8 +56,6 @@
#include <QtTest/qtest_global.h>
#include <QtTest/qbenchmarkmetric.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -68,6 +66,4 @@ namespace QTest {
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QBENCHMARK_H
diff --git a/src/testlib/qbenchmarkperfevents.cpp b/src/testlib/qbenchmarkperfevents.cpp
new file mode 100644
index 0000000000..e3034d1f94
--- /dev/null
+++ b/src/testlib/qbenchmarkperfevents.cpp
@@ -0,0 +1,607 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Intel Corporation.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbenchmarkperfevents_p.h"
+#include "qbenchmarkmetric.h"
+#include "qbenchmark_p.h"
+
+#ifdef QTESTLIB_USE_PERF_EVENTS
+
+// include the qcore_unix_p.h without core-private
+// we only use inline functions anyway
+#include "../corelib/kernel/qcore_unix_p.h"
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <sys/syscall.h>
+#include <sys/ioctl.h>
+
+#include "3rdparty/linux_perf_event_p.h"
+
+// for PERF_TYPE_HW_CACHE, the config is a bitmask
+// lowest 8 bits: cache type
+// bits 8 to 15: cache operation
+// bits 16 to 23: cache result
+#define CACHE_L1D_READ (PERF_COUNT_HW_CACHE_L1D | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_L1D_WRITE (PERF_COUNT_HW_CACHE_L1D | PERF_COUNT_HW_CACHE_OP_WRITE << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_L1D_PREFETCH (PERF_COUNT_HW_CACHE_L1D | PERF_COUNT_HW_CACHE_OP_PREFETCH << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_L1I_READ (PERF_COUNT_HW_CACHE_L1I | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_L1I_PREFETCH (PERF_COUNT_HW_CACHE_L1I | PERF_COUNT_HW_CACHE_OP_PREFETCH << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_LLC_READ (PERF_COUNT_HW_CACHE_LL | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_LLC_WRITE (PERF_COUNT_HW_CACHE_LL | PERF_COUNT_HW_CACHE_OP_WRITE << 8| PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_LLC_PREFETCH (PERF_COUNT_HW_CACHE_LL | PERF_COUNT_HW_CACHE_OP_PREFETCH << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_L1D_READ_MISS (PERF_COUNT_HW_CACHE_L1D | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_L1D_WRITE_MISS (PERF_COUNT_HW_CACHE_L1D | PERF_COUNT_HW_CACHE_OP_WRITE << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_L1D_PREFETCH_MISS (PERF_COUNT_HW_CACHE_L1D | PERF_COUNT_HW_CACHE_OP_PREFETCH << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_L1I_READ_MISS (PERF_COUNT_HW_CACHE_L1I | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_L1I_PREFETCH_MISS (PERF_COUNT_HW_CACHE_L1I | PERF_COUNT_HW_CACHE_OP_PREFETCH << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_LLC_READ_MISS (PERF_COUNT_HW_CACHE_LL | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_LLC_WRITE_MISS (PERF_COUNT_HW_CACHE_LL | PERF_COUNT_HW_CACHE_OP_WRITE << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_LLC_PREFETCH_MISS (PERF_COUNT_HW_CACHE_LL | PERF_COUNT_HW_CACHE_OP_PREFETCH << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+#define CACHE_BRANCH_READ (PERF_COUNT_HW_CACHE_BPU | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
+#define CACHE_BRANCH_READ_MISS (PERF_COUNT_HW_CACHE_BPU | PERF_COUNT_HW_CACHE_OP_READ << 8 | PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
+
+QT_BEGIN_NAMESPACE
+
+static perf_event_attr attr;
+
+static void initPerf()
+{
+ static bool done;
+ if (!done) {
+ memset(&attr, 0, sizeof attr);
+ attr.size = sizeof attr;
+ attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
+ attr.disabled = true; // we'll enable later
+ attr.inherit = true; // let children processes inherit the monitoring
+ attr.pinned = true; // keep it running in the hardware
+ attr.inherit_stat = true; // aggregate all the info from child processes
+ attr.task = true; // trace fork/exits
+
+ // set a default performance counter: CPU cycles
+ attr.type = PERF_TYPE_HARDWARE;
+ attr.config = PERF_COUNT_HW_CPU_CYCLES; // default
+
+ done = true;
+ }
+}
+
+/*!
+ \class QBenchmarkPerfEvents
+ \brief The Linux perf events benchmark backend
+
+ This benchmark backend uses the Linux Performance Counters interface,
+ introduced with the Linux kernel v2.6.31. The interface is done by one
+ system call (perf_event_open) which takes an attribute structure and
+ returns a file descriptor.
+
+ More information:
+ \li design docs: tools/perf/design.txt <http://lxr.linux.no/linux/tools/perf/design.txt>
+ \li sample tool: tools/perf/builtin-stat.c <http://lxr.linux.no/linux/tools/perf/builtin-stat.c>
+ (note: as of v3.3.1, the documentation is out-of-date with the kernel
+ interface, so reading the source code of existing tools is necessary)
+
+ This benchlib backend monitors the current process as well as child process
+ launched. We do not try to benchmark in kernel or hypervisor mode, as that
+ usually requires elevated privileges.
+ */
+
+static int perf_event_open(perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags)
+{
+ return syscall(SYS_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+bool QBenchmarkPerfEventsMeasurer::isAvailable()
+{
+ // this generates an EFAULT because attr == NULL if perf_event_open is available
+ // if the kernel is too old, it generates ENOSYS
+ return perf_event_open(0, 0, 0, 0, 0) == -1 && errno != ENOSYS;
+}
+
+/* Event list structure
+ The following table provides the list of supported events
+
+ Event type Event counter Unit Name and aliases
+ HARDWARE CPU_CYCLES CPUCycles cycles cpu-cycles
+ HARDWARE INSTRUCTIONS Instructions instructions
+ HARDWARE CACHE_REFERENCES CacheReferences cache-references
+ HARDWARE CACHE_MISSES CacheMisses cache-misses
+ HARDWARE BRANCH_INSTRUCTIONS BranchInstructions branch-instructions branches
+ HARDWARE BRANCH_MISSES BranchMisses branch-misses
+ HARDWARE BUS_CYCLES BusCycles bus-cycles
+ HARDWARE STALLED_CYCLES_FRONTEND StalledCycles stalled-cycles-frontend idle-cycles-frontend
+ HARDWARE STALLED_CYCLES_BACKEND StalledCycles stalled-cycles-backend idle-cycles-backend
+ SOFTWARE CPU_CLOCK WalltimeMilliseconds cpu-clock
+ SOFTWARE TASK_CLOCK WalltimeMilliseconds task-clock
+ SOFTWARE PAGE_FAULTS PageFaults page-faults faults
+ SOFTWARE PAGE_FAULTS_MAJ MajorPageFaults major-faults
+ SOFTWARE PAGE_FAULTS_MIN MinorPageFaults minor-faults
+ SOFTWARE CONTEXT_SWITCHES ContextSwitches context-switches cs
+ SOFTWARE CPU_MIGRATIONS CPUMigrations cpu-migrations migrations
+ SOFTWARE ALIGNMENT_FAULTS AlignmentFaults alignment-faults
+ SOFTWARE EMULATION_FAULTS EmulationFaults emulation-faults
+ HW_CACHE L1D_READ CacheReads l1d-cache-reads l1d-cache-loads l1d-reads l1d-loads
+ HW_CACHE L1D_WRITE CacheWrites l1d-cache-writes l1d-cache-stores l1d-writes l1d-stores
+ HW_CACHE L1D_PREFETCH CachePrefetches l1d-cache-prefetches l1d-prefetches
+ HW_CACHE L1I_READ CacheReads l1i-cache-reads l1i-cache-loads l1i-reads l1i-loads
+ HW_CACHE L1I_PREFETCH CachePrefetches l1i-cache-prefetches l1i-prefetches
+ HW_CACHE LLC_READ CacheReads llc-cache-reads llc-cache-loads llc-loads llc-reads
+ HW_CACHE LLC_WRITE CacheWrites llc-cache-writes llc-cache-stores llc-writes llc-stores
+ HW_CACHE LLC_PREFETCH CachePrefetches llc-cache-prefetches llc-prefetches
+ HW_CACHE L1D_READ_MISS CacheReads l1d-cache-read-misses l1d-cache-load-misses l1d-read-misses l1d-load-misses
+ HW_CACHE L1D_WRITE_MISS CacheWrites l1d-cache-write-misses l1d-cache-store-misses l1d-write-misses l1d-store-misses
+ HW_CACHE L1D_PREFETCH_MISS CachePrefetches l1d-cache-prefetch-misses l1d-prefetch-misses
+ HW_CACHE L1I_READ_MISS CacheReads l1i-cache-read-misses l1i-cache-load-misses l1i-read-misses l1i-load-misses
+ HW_CACHE L1I_PREFETCH_MISS CachePrefetches l1i-cache-prefetch-misses l1i-prefetch-misses
+ HW_CACHE LLC_READ_MISS CacheReads llc-cache-read-misses llc-cache-load-misses llc-read-misses llc-load-misses
+ HW_CACHE LLC_WRITE_MISS CacheWrites llc-cache-write-misses llc-cache-store-misses llc-write-misses llc-store-misses
+ HW_CACHE LLC_PREFETCH_MISS CachePrefetches llc-cache-prefetch-misses llc-prefetch-misses
+ HW_CACHE BRANCH_READ BranchInstructions branch-reads branch-loads branch-predicts
+ HW_CACHE BRANCH_READ_MISS BranchMisses branch-mispredicts branch-read-misses branch-load-misses
+
+ Use the following Perl script to re-generate the list
+=== cut perl ===
+#!/usr/bin/env perl
+# Load all entries into %map
+while (<STDIN>) {
+ m/^\s*(.*)\s*$/;
+ @_ = split /\s+/, $1;
+ $type = shift @_;
+ $id = ($type eq "HARDWARE" ? "PERF_COUNT_HW_" :
+ $type eq "SOFTWARE" ? "PERF_COUNT_SW_" :
+ $type eq "HW_CACHE" ? "CACHE_" : "") . shift @_;
+ $unit = shift @_;
+
+ for $string (@_) {
+ die "$string was already seen!" if defined($map{$string});
+ $map{$string} = [-1, $type, $id, $unit];
+ push @strings, $string;
+ }
+}
+
+# sort the map and print the string list
+@strings = sort @strings;
+print "static const char eventlist_strings[] = \n";
+$counter = 0;
+for $entry (@strings) {
+ print " \"$entry\\0\"\n";
+ $map{$entry}[0] = $counter;
+ $counter += 1 + length $entry;
+}
+
+# print the table
+print " \"\\0\";\n\nstatic const Events eventlist[] = {\n";
+for $entry (sort @strings) {
+ printf " { %3d, PERF_TYPE_%s, %s, QTest::%s },\n",
+ $map{$entry}[0],
+ $map{$entry}[1],
+ $map{$entry}[2],
+ $map{$entry}[3];
+}
+print " { 0, PERF_TYPE_MAX, 0, QTest::Events }\n};\n";
+=== cut perl ===
+*/
+
+struct Events {
+ unsigned offset;
+ quint32 type;
+ quint64 event_id;
+ QTest::QBenchmarkMetric metric;
+};
+
+/* -- BEGIN GENERATED CODE -- */
+static const char eventlist_strings[] =
+ "alignment-faults\0"
+ "branch-instructions\0"
+ "branch-load-misses\0"
+ "branch-loads\0"
+ "branch-mispredicts\0"
+ "branch-misses\0"
+ "branch-predicts\0"
+ "branch-read-misses\0"
+ "branch-reads\0"
+ "branches\0"
+ "bus-cycles\0"
+ "cache-misses\0"
+ "cache-references\0"
+ "context-switches\0"
+ "cpu-clock\0"
+ "cpu-cycles\0"
+ "cpu-migrations\0"
+ "cs\0"
+ "cycles\0"
+ "emulation-faults\0"
+ "faults\0"
+ "idle-cycles-backend\0"
+ "idle-cycles-frontend\0"
+ "instructions\0"
+ "l1d-cache-load-misses\0"
+ "l1d-cache-loads\0"
+ "l1d-cache-prefetch-misses\0"
+ "l1d-cache-prefetches\0"
+ "l1d-cache-read-misses\0"
+ "l1d-cache-reads\0"
+ "l1d-cache-store-misses\0"
+ "l1d-cache-stores\0"
+ "l1d-cache-write-misses\0"
+ "l1d-cache-writes\0"
+ "l1d-load-misses\0"
+ "l1d-loads\0"
+ "l1d-prefetch-misses\0"
+ "l1d-prefetches\0"
+ "l1d-read-misses\0"
+ "l1d-reads\0"
+ "l1d-store-misses\0"
+ "l1d-stores\0"
+ "l1d-write-misses\0"
+ "l1d-writes\0"
+ "l1i-cache-load-misses\0"
+ "l1i-cache-loads\0"
+ "l1i-cache-prefetch-misses\0"
+ "l1i-cache-prefetches\0"
+ "l1i-cache-read-misses\0"
+ "l1i-cache-reads\0"
+ "l1i-load-misses\0"
+ "l1i-loads\0"
+ "l1i-prefetch-misses\0"
+ "l1i-prefetches\0"
+ "l1i-read-misses\0"
+ "l1i-reads\0"
+ "llc-cache-load-misses\0"
+ "llc-cache-loads\0"
+ "llc-cache-prefetch-misses\0"
+ "llc-cache-prefetches\0"
+ "llc-cache-read-misses\0"
+ "llc-cache-reads\0"
+ "llc-cache-store-misses\0"
+ "llc-cache-stores\0"
+ "llc-cache-write-misses\0"
+ "llc-cache-writes\0"
+ "llc-load-misses\0"
+ "llc-loads\0"
+ "llc-prefetch-misses\0"
+ "llc-prefetches\0"
+ "llc-read-misses\0"
+ "llc-reads\0"
+ "llc-store-misses\0"
+ "llc-stores\0"
+ "llc-write-misses\0"
+ "llc-writes\0"
+ "major-faults\0"
+ "migrations\0"
+ "minor-faults\0"
+ "page-faults\0"
+ "stalled-cycles-backend\0"
+ "stalled-cycles-frontend\0"
+ "task-clock\0"
+ "\0";
+
+static const Events eventlist[] = {
+ { 0, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS, QTest::AlignmentFaults },
+ { 17, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS, QTest::BranchInstructions },
+ { 37, PERF_TYPE_HW_CACHE, CACHE_BRANCH_READ_MISS, QTest::BranchMisses },
+ { 56, PERF_TYPE_HW_CACHE, CACHE_BRANCH_READ, QTest::BranchInstructions },
+ { 69, PERF_TYPE_HW_CACHE, CACHE_BRANCH_READ_MISS, QTest::BranchMisses },
+ { 88, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES, QTest::BranchMisses },
+ { 102, PERF_TYPE_HW_CACHE, CACHE_BRANCH_READ, QTest::BranchInstructions },
+ { 118, PERF_TYPE_HW_CACHE, CACHE_BRANCH_READ_MISS, QTest::BranchMisses },
+ { 137, PERF_TYPE_HW_CACHE, CACHE_BRANCH_READ, QTest::BranchInstructions },
+ { 150, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS, QTest::BranchInstructions },
+ { 159, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES, QTest::BusCycles },
+ { 170, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES, QTest::CacheMisses },
+ { 183, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES, QTest::CacheReferences },
+ { 200, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES, QTest::ContextSwitches },
+ { 217, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, QTest::WalltimeMilliseconds },
+ { 227, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES, QTest::CPUCycles },
+ { 238, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS, QTest::CPUMigrations },
+ { 253, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES, QTest::ContextSwitches },
+ { 256, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES, QTest::CPUCycles },
+ { 263, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS, QTest::EmulationFaults },
+ { 280, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS, QTest::PageFaults },
+ { 287, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND, QTest::StalledCycles },
+ { 307, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, QTest::StalledCycles },
+ { 328, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, QTest::Instructions },
+ { 341, PERF_TYPE_HW_CACHE, CACHE_L1D_READ_MISS, QTest::CacheReads },
+ { 363, PERF_TYPE_HW_CACHE, CACHE_L1D_READ, QTest::CacheReads },
+ { 379, PERF_TYPE_HW_CACHE, CACHE_L1D_PREFETCH_MISS, QTest::CachePrefetches },
+ { 405, PERF_TYPE_HW_CACHE, CACHE_L1D_PREFETCH, QTest::CachePrefetches },
+ { 426, PERF_TYPE_HW_CACHE, CACHE_L1D_READ_MISS, QTest::CacheReads },
+ { 448, PERF_TYPE_HW_CACHE, CACHE_L1D_READ, QTest::CacheReads },
+ { 464, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE_MISS, QTest::CacheWrites },
+ { 487, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE, QTest::CacheWrites },
+ { 504, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE_MISS, QTest::CacheWrites },
+ { 527, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE, QTest::CacheWrites },
+ { 544, PERF_TYPE_HW_CACHE, CACHE_L1D_READ_MISS, QTest::CacheReads },
+ { 560, PERF_TYPE_HW_CACHE, CACHE_L1D_READ, QTest::CacheReads },
+ { 570, PERF_TYPE_HW_CACHE, CACHE_L1D_PREFETCH_MISS, QTest::CachePrefetches },
+ { 590, PERF_TYPE_HW_CACHE, CACHE_L1D_PREFETCH, QTest::CachePrefetches },
+ { 605, PERF_TYPE_HW_CACHE, CACHE_L1D_READ_MISS, QTest::CacheReads },
+ { 621, PERF_TYPE_HW_CACHE, CACHE_L1D_READ, QTest::CacheReads },
+ { 631, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE_MISS, QTest::CacheWrites },
+ { 648, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE, QTest::CacheWrites },
+ { 659, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE_MISS, QTest::CacheWrites },
+ { 676, PERF_TYPE_HW_CACHE, CACHE_L1D_WRITE, QTest::CacheWrites },
+ { 687, PERF_TYPE_HW_CACHE, CACHE_L1I_READ_MISS, QTest::CacheReads },
+ { 709, PERF_TYPE_HW_CACHE, CACHE_L1I_READ, QTest::CacheReads },
+ { 725, PERF_TYPE_HW_CACHE, CACHE_L1I_PREFETCH_MISS, QTest::CachePrefetches },
+ { 751, PERF_TYPE_HW_CACHE, CACHE_L1I_PREFETCH, QTest::CachePrefetches },
+ { 772, PERF_TYPE_HW_CACHE, CACHE_L1I_READ_MISS, QTest::CacheReads },
+ { 794, PERF_TYPE_HW_CACHE, CACHE_L1I_READ, QTest::CacheReads },
+ { 810, PERF_TYPE_HW_CACHE, CACHE_L1I_READ_MISS, QTest::CacheReads },
+ { 826, PERF_TYPE_HW_CACHE, CACHE_L1I_READ, QTest::CacheReads },
+ { 836, PERF_TYPE_HW_CACHE, CACHE_L1I_PREFETCH_MISS, QTest::CachePrefetches },
+ { 856, PERF_TYPE_HW_CACHE, CACHE_L1I_PREFETCH, QTest::CachePrefetches },
+ { 871, PERF_TYPE_HW_CACHE, CACHE_L1I_READ_MISS, QTest::CacheReads },
+ { 887, PERF_TYPE_HW_CACHE, CACHE_L1I_READ, QTest::CacheReads },
+ { 897, PERF_TYPE_HW_CACHE, CACHE_LLC_READ_MISS, QTest::CacheReads },
+ { 919, PERF_TYPE_HW_CACHE, CACHE_LLC_READ, QTest::CacheReads },
+ { 935, PERF_TYPE_HW_CACHE, CACHE_LLC_PREFETCH_MISS, QTest::CachePrefetches },
+ { 961, PERF_TYPE_HW_CACHE, CACHE_LLC_PREFETCH, QTest::CachePrefetches },
+ { 982, PERF_TYPE_HW_CACHE, CACHE_LLC_READ_MISS, QTest::CacheReads },
+ { 1004, PERF_TYPE_HW_CACHE, CACHE_LLC_READ, QTest::CacheReads },
+ { 1020, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE_MISS, QTest::CacheWrites },
+ { 1043, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE, QTest::CacheWrites },
+ { 1060, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE_MISS, QTest::CacheWrites },
+ { 1083, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE, QTest::CacheWrites },
+ { 1100, PERF_TYPE_HW_CACHE, CACHE_LLC_READ_MISS, QTest::CacheReads },
+ { 1116, PERF_TYPE_HW_CACHE, CACHE_LLC_READ, QTest::CacheReads },
+ { 1126, PERF_TYPE_HW_CACHE, CACHE_LLC_PREFETCH_MISS, QTest::CachePrefetches },
+ { 1146, PERF_TYPE_HW_CACHE, CACHE_LLC_PREFETCH, QTest::CachePrefetches },
+ { 1161, PERF_TYPE_HW_CACHE, CACHE_LLC_READ_MISS, QTest::CacheReads },
+ { 1177, PERF_TYPE_HW_CACHE, CACHE_LLC_READ, QTest::CacheReads },
+ { 1187, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE_MISS, QTest::CacheWrites },
+ { 1204, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE, QTest::CacheWrites },
+ { 1215, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE_MISS, QTest::CacheWrites },
+ { 1232, PERF_TYPE_HW_CACHE, CACHE_LLC_WRITE, QTest::CacheWrites },
+ { 1243, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ, QTest::MajorPageFaults },
+ { 1256, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS, QTest::CPUMigrations },
+ { 1267, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN, QTest::MinorPageFaults },
+ { 1280, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS, QTest::PageFaults },
+ { 1292, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND, QTest::StalledCycles },
+ { 1315, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, QTest::StalledCycles },
+ { 1339, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK, QTest::WalltimeMilliseconds },
+ { 0, PERF_TYPE_MAX, 0, QTest::Events }
+};
+/* -- END GENERATED CODE -- */
+
+QTest::QBenchmarkMetric QBenchmarkPerfEventsMeasurer::metricForEvent(quint32 type, quint64 event_id)
+{
+ const Events *ptr = eventlist;
+ for ( ; ptr->type != PERF_TYPE_MAX; ++ptr) {
+ if (ptr->type == type && ptr->event_id == event_id)
+ return ptr->metric;
+ }
+ return QTest::Events;
+}
+
+void QBenchmarkPerfEventsMeasurer::setCounter(const char *name)
+{
+ initPerf();
+ const char *colon = strchr(name, ':');
+ int n = colon ? colon - name : strlen(name);
+ const Events *ptr = eventlist;
+ for ( ; ptr->type != PERF_TYPE_MAX; ++ptr) {
+ int c = strncmp(name, eventlist_strings + ptr->offset, n);
+ if (c == 0)
+ break;
+ if (c < 0) {
+ fprintf(stderr, "ERROR: Performance counter type '%s' is unknown\n", name);
+ exit(1);
+ }
+ }
+
+ attr.type = ptr->type;
+ attr.config = ptr->event_id;
+
+ // now parse the attributes
+ if (!colon)
+ return;
+ while (*++colon) {
+ switch (*colon) {
+ case 'u':
+ attr.exclude_user = true;
+ break;
+ case 'k':
+ attr.exclude_kernel = true;
+ break;
+ case 'h':
+ attr.exclude_hv = true;
+ break;
+ case 'G':
+ attr.exclude_guest = true;
+ break;
+ case 'H':
+ attr.exclude_host = true;
+ break;
+ default:
+ fprintf(stderr, "ERROR: Unknown attribute '%c'\n", *colon);
+ exit(1);
+ }
+ }
+}
+
+void QBenchmarkPerfEventsMeasurer::listCounters()
+{
+ if (!isAvailable()) {
+ printf("Performance counters are not available on this system\n");
+ return;
+ }
+
+ printf("The following performance counters are available:\n");
+ const Events *ptr = eventlist;
+ for ( ; ptr->type != PERF_TYPE_MAX; ++ptr) {
+ printf(" %-30s [%s]\n", eventlist_strings + ptr->offset,
+ ptr->type == PERF_TYPE_HARDWARE ? "hardware" :
+ ptr->type == PERF_TYPE_SOFTWARE ? "software" :
+ ptr->type == PERF_TYPE_HW_CACHE ? "cache" : "other");
+ }
+
+ printf("\nAttributes can be specified by adding a colon and the following:\n"
+ " u - exclude measuring in the userspace\n"
+ " k - exclude measuring in kernel mode\n"
+ " h - exclude measuring in the hypervisor\n"
+ " G - exclude measuring when running virtualized (guest VM)\n"
+ " H - exclude measuring when running non-virtualized (host system)\n"
+ "Attributes can be combined, for example: -perfcounter branch-mispredicts:kh\n");
+}
+
+QBenchmarkPerfEventsMeasurer::QBenchmarkPerfEventsMeasurer()
+ : fd(-1)
+{
+}
+
+QBenchmarkPerfEventsMeasurer::~QBenchmarkPerfEventsMeasurer()
+{
+ qt_safe_close(fd);
+}
+
+void QBenchmarkPerfEventsMeasurer::init()
+{
+}
+
+void QBenchmarkPerfEventsMeasurer::start()
+{
+
+ initPerf();
+ // pid == 0 -> attach to the current process
+ // cpu == -1 -> monitor on all CPUs
+ // group_fd == -1 -> this is the group leader
+ // flags == 0 -> reserved, must be zero
+ fd = perf_event_open(&attr, 0, -1, -1, 0);
+ if (fd == -1) {
+ perror("QBenchmarkPerfEventsMeasurer::start: perf_event_open");
+ exit(1);
+ } else {
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+ }
+
+ // enable the counter
+ ::ioctl(fd, PERF_EVENT_IOC_RESET);
+ ::ioctl(fd, PERF_EVENT_IOC_ENABLE);
+}
+
+qint64 QBenchmarkPerfEventsMeasurer::checkpoint()
+{
+ ::ioctl(fd, PERF_EVENT_IOC_DISABLE);
+ qint64 value = readValue();
+ ::ioctl(fd, PERF_EVENT_IOC_ENABLE);
+ return value;
+}
+
+qint64 QBenchmarkPerfEventsMeasurer::stop()
+{
+ // disable the counter
+ ::ioctl(fd, PERF_EVENT_IOC_DISABLE);
+ return readValue();
+}
+
+bool QBenchmarkPerfEventsMeasurer::isMeasurementAccepted(qint64)
+{
+ return true;
+}
+
+int QBenchmarkPerfEventsMeasurer::adjustIterationCount(int)
+{
+ return 1;
+}
+
+int QBenchmarkPerfEventsMeasurer::adjustMedianCount(int)
+{
+ return 1;
+}
+
+QTest::QBenchmarkMetric QBenchmarkPerfEventsMeasurer::metricType()
+{
+ return metricForEvent(attr.type, attr.config);
+}
+
+static quint64 rawReadValue(int fd)
+{
+ /* from the kernel docs:
+ * struct read_format {
+ * { u64 value;
+ * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
+ * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
+ * { u64 id; } && PERF_FORMAT_ID
+ * } && !PERF_FORMAT_GROUP
+ */
+
+ struct read_format {
+ quint64 value;
+ quint64 time_enabled;
+ quint64 time_running;
+ } results;
+
+ size_t nread = 0;
+ while (nread < sizeof results) {
+ char *ptr = reinterpret_cast<char *>(&results);
+ qint64 r = qt_safe_read(fd, ptr + nread, sizeof results - nread);
+ if (r == -1) {
+ perror("QBenchmarkPerfEventsMeasurer::readValue: reading the results");
+ exit(1);
+ }
+ nread += quint64(r);
+ }
+
+ if (results.time_running == results.time_enabled)
+ return results.value;
+
+ // scale the results, though this shouldn't happen!
+ return results.value * (double(results.time_running) / double(results.time_enabled));
+}
+
+qint64 QBenchmarkPerfEventsMeasurer::readValue()
+{
+ quint64 raw = rawReadValue(fd);
+ if (metricType() == QTest::WalltimeMilliseconds) {
+ // perf returns nanoseconds
+ return raw / 1000000;
+ }
+ return raw;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/testlib/qbenchmarkperfevents_p.h b/src/testlib/qbenchmarkperfevents_p.h
new file mode 100644
index 0000000000..f73d140300
--- /dev/null
+++ b/src/testlib/qbenchmarkperfevents_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Intel Corporation.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBENCHMARKPERFEVENTS_P_H
+#define QBENCHMARKPERFEVENTS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtTest/private/qbenchmarkmeasurement_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBenchmarkPerfEventsMeasurer : public QBenchmarkMeasurerBase
+{
+public:
+ QBenchmarkPerfEventsMeasurer();
+ ~QBenchmarkPerfEventsMeasurer();
+ virtual void init();
+ virtual void start();
+ virtual qint64 checkpoint();
+ virtual qint64 stop();
+ virtual bool isMeasurementAccepted(qint64 measurement);
+ virtual int adjustIterationCount(int suggestion);
+ virtual int adjustMedianCount(int suggestion);
+ virtual bool repeatCount() { return 1; }
+ virtual bool needsWarmupIteration() { return true; }
+ virtual QTest::QBenchmarkMetric metricType();
+
+ static bool isAvailable();
+ static QTest::QBenchmarkMetric metricForEvent(quint32 type, quint64 event_id);
+ static void setCounter(const char *name);
+ static void listCounters();
+private:
+ int fd;
+
+ qint64 readValue();
+};
+
+QT_END_NAMESPACE
+
+#endif // QBENCHMARKPERFEVENTS_P_H
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index 93f0dd34ff..9fe82de19e 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -196,7 +196,7 @@ namespace QTest {
void QPlainTestLogger::outputMessage(const char *str)
{
#if defined(Q_OS_WINCE)
- QString strUtf16 = QString::fromLatin1(str);
+ QString strUtf16 = QString::fromLocal8Bit(str);
const int maxOutputLength = 255;
do {
QString tmp = strUtf16.left(maxOutputLength);
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index 0323fa111f..72a5df1ed9 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -50,8 +50,6 @@
#include <QtCore/qvector.h>
#include <QtTest/qtesteventloop.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -97,7 +95,7 @@ public:
return;
}
sig = ba;
- initArgs(mo->method(sigIndex));
+ initArgs(mo->method(sigIndex), obj);
}
inline bool isValid() const { return !sig.isEmpty(); }
@@ -131,10 +129,23 @@ public:
private:
void initArgs(const QMetaMethod &member)
{
+ initArgs(member, 0);
+ }
+
+ void initArgs(const QMetaMethod &member, const QObject *obj)
+ {
const QList<QByteArray> params = member.parameterTypes();
args.reserve(params.size());
for (int i = 0; i < params.count(); ++i) {
- const int tp = QMetaType::type(params.at(i).constData());
+ int tp = QMetaType::type(params.at(i).constData());
+ if (tp == QMetaType::UnknownType && obj) {
+ void *argv[] = { &tp, &i };
+ QMetaObject::metacall(const_cast<QObject*>(obj),
+ QMetaObject::RegisterMethodArgumentMetaType,
+ member.methodIndex(), argv);
+ if (tp == -1)
+ tp = QMetaType::UnknownType;
+ }
if (tp == QMetaType::UnknownType) {
Q_ASSERT(tp != QMetaType::Void); // void parameter => metaobject is corrupt
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
@@ -172,6 +183,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qsignalspy.qdoc b/src/testlib/qsignalspy.qdoc
index e9f2cac531..77dcd99741 100644
--- a/src/testlib/qsignalspy.qdoc
+++ b/src/testlib/qsignalspy.qdoc
@@ -25,7 +25,7 @@
**
****************************************************************************/
-/*!
+/*!
\class QSignalSpy
\inmodule QtTest
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 6d130af27c..ac1d6cc9ef 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -60,8 +60,6 @@
#include <QtCore/qrect.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -70,12 +68,12 @@ namespace QTest
template<> inline char *toString(const QLatin1String &str)
{
- return qstrdup(str.latin1());
+ return qstrdup(qPrintable(QString(str)));
}
template<> inline char *toString(const QString &str)
{
- return qstrdup(str.toLatin1().constData());
+ return qstrdup(qPrintable(str));
}
template<> inline char *toString(const QByteArray &ba)
@@ -87,29 +85,29 @@ template<> inline char *toString(const QByteArray &ba)
template<> inline char *toString(const QTime &time)
{
return time.isValid()
- ? qstrdup(time.toString(QLatin1String("hh:mm:ss.zzz")).toLatin1().constData())
+ ? qstrdup(qPrintable(time.toString(QLatin1String("hh:mm:ss.zzz"))))
: qstrdup("Invalid QTime");
}
template<> inline char *toString(const QDate &date)
{
return date.isValid()
- ? qstrdup(date.toString(QLatin1String("yyyy/MM/dd")).toLatin1().constData())
+ ? qstrdup(qPrintable(date.toString(QLatin1String("yyyy/MM/dd"))))
: qstrdup("Invalid QDate");
}
template<> inline char *toString(const QDateTime &dateTime)
{
return dateTime.isValid()
- ? qstrdup((dateTime.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")) +
- (dateTime.timeSpec() == Qt::LocalTime ? QLatin1String("[local time]") : QLatin1String("[UTC]"))).toLatin1().constData())
+ ? qstrdup(qPrintable(dateTime.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")) +
+ (dateTime.timeSpec() == Qt::LocalTime ? QLatin1String("[local time]") : QLatin1String("[UTC]"))))
: qstrdup("Invalid QDateTime");
}
#endif // QT_NO_DATESTRING
template<> inline char *toString(const QChar &c)
{
- return qstrdup(QString::fromLatin1("QChar: '%1' (0x%2)").arg(c).arg(QString::number(static_cast<int>(c.unicode()), 16)).toLatin1().constData());
+ return qstrdup(qPrintable(QString::fromLatin1("QChar: '%1' (0x%2)").arg(c).arg(QString::number(static_cast<int>(c.unicode()), 16))));
}
template<> inline char *toString(const QPoint &p)
@@ -145,7 +143,7 @@ template<> inline char *toString(const QRectF &s)
template<> inline char *toString(const QUrl &uri)
{
if (!uri.isValid())
- return qstrdup(QByteArray("Invalid URL: " + uri.errorString().toLatin1()).constData());
+ return qstrdup(qPrintable(QStringLiteral("Invalid URL: ") + uri.errorString()));
return qstrdup(uri.toEncoded().constData());
}
@@ -161,7 +159,7 @@ template<> inline char *toString(const QVariant &v)
if (!v.isNull()) {
vstring.append(',');
if (v.canConvert(QVariant::String)) {
- vstring.append(qvariant_cast<QString>(v).toLatin1());
+ vstring.append(qvariant_cast<QString>(v).toLocal8Bit());
}
else {
vstring.append("<value not representable as string>");
@@ -186,9 +184,9 @@ inline bool qCompare(QLatin1String const &t1, QString const &t2, const char *act
return qCompare(QString(t1), t2, actual, expected, file, line);
}
-template<>
-inline bool qCompare(QStringList const &t1, QStringList const &t2,
- const char *actual, const char *expected, const char *file, int line)
+template <typename T>
+inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual, const char *expected,
+ const char *file, int line)
{
char msg[1024];
msg[0] = '\0';
@@ -196,23 +194,30 @@ inline bool qCompare(QStringList const &t1, QStringList const &t2,
const int actualSize = t1.count();
const int expectedSize = t2.count();
if (actualSize != expectedSize) {
- qsnprintf(msg, sizeof(msg), "Compared QStringLists have different sizes.\n"
+ qsnprintf(msg, sizeof(msg), "Compared lists have different sizes.\n"
" Actual (%s) size: '%d'\n"
" Expected (%s) size: '%d'", actual, actualSize, expected, expectedSize);
isOk = false;
}
for (int i = 0; isOk && i < actualSize; ++i) {
- if (t1.at(i) != t2.at(i)) {
- qsnprintf(msg, sizeof(msg), "Compared QStringLists differ at index %d.\n"
+ if (!(t1.at(i) == t2.at(i))) {
+ qsnprintf(msg, sizeof(msg), "Compared lists differ at index %d.\n"
" Actual (%s): '%s'\n"
- " Expected (%s): '%s'", i, actual, t1.at(i).toLatin1().constData(),
- expected, t2.at(i).toLatin1().constData());
+ " Expected (%s): '%s'", i, actual, toString(t1.at(i)),
+ expected, toString(t2.at(i)));
isOk = false;
}
}
return compare_helper(isOk, msg, 0, 0, actual, expected, file, line);
}
+template <>
+inline bool qCompare(QStringList const &t1, QStringList const &t2, const char *actual, const char *expected,
+ const char *file, int line)
+{
+ return qCompare<QString>(t1, t2, actual, expected, file, line);
+}
+
template <typename T>
inline bool qCompare(QFlags<T> const &t1, T const &t2, const char *actual, const char *expected,
const char *file, int line)
@@ -227,6 +232,48 @@ inline bool qCompare(QFlags<T> const &t1, int const &t2, const char *actual, con
return qCompare(int(t1), t2, actual, expected, file, line);
}
+template<>
+inline bool qCompare(qint64 const &t1, qint32 const &t2, const char *actual,
+ const char *expected, const char *file, int line)
+{
+ return qCompare(t1, static_cast<qint64>(t2), actual, expected, file, line);
+}
+
+template<>
+inline bool qCompare(qint64 const &t1, quint32 const &t2, const char *actual,
+ const char *expected, const char *file, int line)
+{
+ return qCompare(t1, static_cast<qint64>(t2), actual, expected, file, line);
+}
+
+template<>
+inline bool qCompare(quint64 const &t1, quint32 const &t2, const char *actual,
+ const char *expected, const char *file, int line)
+{
+ return qCompare(t1, static_cast<quint64>(t2), actual, expected, file, line);
+}
+
+template<>
+inline bool qCompare(qint32 const &t1, qint64 const &t2, const char *actual,
+ const char *expected, const char *file, int line)
+{
+ return qCompare(static_cast<qint64>(t1), t2, actual, expected, file, line);
+}
+
+template<>
+inline bool qCompare(quint32 const &t1, qint64 const &t2, const char *actual,
+ const char *expected, const char *file, int line)
+{
+ return qCompare(static_cast<qint64>(t1), t2, actual, expected, file, line);
+}
+
+template<>
+inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual,
+ const char *expected, const char *file, int line)
+{
+ return qCompare(static_cast<quint64>(t1), t2, actual, expected, file, line);
+}
+
}
QT_END_NAMESPACE
@@ -294,6 +341,4 @@ int main(int argc, char *argv[]) \
return QTest::qExec(&tc, argc, argv); \
}
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtest_global.h b/src/testlib/qtest_global.h
index 9e59713663..ac5a0b23f5 100644
--- a/src/testlib/qtest_global.h
+++ b/src/testlib/qtest_global.h
@@ -44,8 +44,6 @@
#include <QtCore/qglobal.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -76,6 +74,4 @@ namespace QTest
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h
index 1962344f12..a9ac7777c3 100644
--- a/src/testlib/qtest_gui.h
+++ b/src/testlib/qtest_gui.h
@@ -69,8 +69,6 @@
#pragma qt_no_master_include
#endif
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -149,6 +147,4 @@ inline bool qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, c
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtest_widgets.h b/src/testlib/qtest_widgets.h
index 265b3a4703..1161b84edc 100644
--- a/src/testlib/qtest_widgets.h
+++ b/src/testlib/qtest_widgets.h
@@ -57,11 +57,9 @@
#pragma qt_no_master_include
#endif
-QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-QT_END_HEADER
#endif
diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h
index d2f57a0ced..f27651c3ad 100644
--- a/src/testlib/qtestaccessible.h
+++ b/src/testlib/qtestaccessible.h
@@ -47,6 +47,8 @@
#pragma qt_no_master_include
#endif
+#include <QtCore/qglobal.h>
+
#ifndef QT_NO_ACCESSIBILITY
#define QVERIFY_EVENT(event) \
@@ -59,8 +61,6 @@
#include <QtTest/qtest_global.h>
#include <QtTest/qtestsystem.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -266,7 +266,5 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QT_NO_ACCESSIBILITY
#endif // QTESTACCESSIBLE_H
diff --git a/src/testlib/qtestassert.h b/src/testlib/qtestassert.h
index 7e88fa9d4d..c6942534c5 100644
--- a/src/testlib/qtestassert.h
+++ b/src/testlib/qtestassert.h
@@ -44,8 +44,6 @@
#include <QtCore/qglobal.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -55,6 +53,4 @@ QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 987c5d88b2..27fcc64ceb 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -64,6 +64,8 @@
#include <QtTest/private/qbenchmark_p.h>
#include <QtTest/private/cycle_p.h>
+#include <numeric>
+
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -82,7 +84,7 @@
#include <time.h>
#endif
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
#include <IOKit/pwr_mgt/IOPMLib.h>
#endif
@@ -1341,11 +1343,17 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
#ifdef QTESTLIB_USE_VALGRIND
" -callgrind : Use callgrind to time benchmarks\n"
#endif
+#ifdef QTESTLIB_USE_PERF_EVENTS
+ " -perf : Use Linux perf events to time benchmarks\n"
+ " -perfcounter name : Use the counter named 'name'\n"
+ " -perfcounterlist : Lists the counters available\n"
+#endif
#ifdef HAVE_TICK_COUNTER
" -tickcounter : Use CPU tick counters to time benchmarks\n"
#endif
" -eventcounter : Counts events received during benchmarks\n"
" -minimumvalue n : Sets the minimum acceptable measurement value\n"
+ " -minimumtotal n : Sets the minimum acceptable total for repeated executions of a test function\n"
" -iterations n : Sets the number of accumulation iterations.\n"
" -median n : Sets the number of median iterations.\n"
" -vb : Print out verbose benchmarking information.\n";
@@ -1481,6 +1489,25 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
QBenchmarkGlobalData::current->callgrindOutFileBase =
QBenchmarkValgrindUtils::outFileBase();
#endif
+#ifdef QTESTLIB_USE_PERF_EVENTS
+ } else if (strcmp(argv[i], "-perf") == 0) {
+ if (QBenchmarkPerfEventsMeasurer::isAvailable()) {
+ // perf available
+ QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::PerfCounter);
+ } else {
+ fprintf(stderr, "WARNING: Linux perf events not available. Using the walltime measurer.\n");
+ }
+ } else if (strcmp(argv[i], "-perfcounter") == 0) {
+ if (i + 1 >= argc) {
+ fprintf(stderr, "-perfcounter needs an extra parameter with the name of the counter\n");
+ exit(1);
+ } else {
+ QBenchmarkPerfEventsMeasurer::setCounter(argv[++i]);
+ }
+ } else if (strcmp(argv[i], "-perfcounterlist") == 0) {
+ QBenchmarkPerfEventsMeasurer::listCounters();
+ exit(0);
+#endif
#ifdef HAVE_TICK_COUNTER
} else if (strcmp(argv[i], "-tickcounter") == 0) {
QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter);
@@ -1494,6 +1521,13 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
} else {
QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]);
}
+ } else if (strcmp(argv[i], "-minimumtotal") == 0) {
+ if (i + 1 >= argc) {
+ fprintf(stderr, "-minimumtotal needs an extra parameter to indicate the minimum total measurement\n");
+ exit(1);
+ } else {
+ QBenchmarkGlobalData::current->minimumTotal = qToInt(argv[++i]);
+ }
} else if (strcmp(argv[i], "-iterations") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "-iterations needs an extra parameter to indicate the number of iterations\n");
@@ -1623,6 +1657,15 @@ struct QTestDataSetter
}
};
+namespace {
+
+qreal addResult(qreal current, const QBenchmarkResult& r)
+{
+ return current + r.value;
+}
+
+}
+
static void qInvokeTestMethodDataEntry(char *slot)
{
/* Benchmarking: for each median iteration*/
@@ -1631,6 +1674,7 @@ static void qInvokeTestMethodDataEntry(char *slot)
int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
QList<QBenchmarkResult> results;
+ bool minimumTotalReached = false;
do {
QBenchmarkTestMethodData::current->beginDataRun();
@@ -1689,8 +1733,16 @@ static void qInvokeTestMethodDataEntry(char *slot)
}
}
}
+
+ // Verify if the minimum total measurement is reached, if it was specified:
+ if (QBenchmarkGlobalData::current->minimumTotal == -1) {
+ minimumTotalReached = true;
+ } else {
+ const qreal total = std::accumulate(results.begin(), results.end(), 0.0, addResult);
+ minimumTotalReached = (total >= QBenchmarkGlobalData::current->minimumTotal);
+ }
} while (isBenchmark
- && (++i < QBenchmarkGlobalData::current->adjustMedianIterationCount())
+ && ((++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()) || !minimumTotalReached)
&& !QTestResult::skipCurrentTest() && !QTestResult::currentTestFailed());
// If the test is a benchmark, finalize the result after all iterations have finished.
@@ -2078,7 +2130,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
int callgrindChildExitCode = 0;
#endif
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
bool macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
IOPMAssertionID powerID;
#endif
@@ -2093,7 +2145,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
#endif
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
if (macNeedsActivate) {
CFStringRef reasonForActivity= CFSTR("No Display Sleep");
IOReturn ok = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, reasonForActivity, &powerID);
@@ -2146,7 +2198,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
}
QTestLog::stopLogging();
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
if (macNeedsActivate) {
IOPMAssertionRelease(powerID);
}
@@ -2163,7 +2215,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
QSignalDumper::endDump();
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
if (macNeedsActivate) {
IOPMAssertionRelease(powerID);
}
@@ -2684,6 +2736,10 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac
\internal
*/
+/*! \fn bool QTest::qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
/*! \fn bool QTest::qCompare(QFlags<T> const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
@@ -2692,6 +2748,30 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac
\internal
*/
+/*! \fn bool QTest::qCompare(qint64 const &t1, qint32 const &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
+/*! \fn bool QTest::qCompare(qint64 const &t1, quint32 const &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
+/*! \fn bool QTest::qCompare(quint64 const &t1, quint32 const &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
+/*! \fn bool QTest::qCompare(qint32 const &t1, qint64 const &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
+/*! \fn bool QTest::qCompare(quint32 const &t1, qint64 const &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
+/*! \fn bool QTest::qCompare(quint32 const &t1, quint64 const &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+*/
+
/*! \fn bool QTest::qCompare(bool const &t1, int const &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index a13bd49338..6b5e7a574b 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -51,8 +51,6 @@
#include <string.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -352,6 +350,4 @@ namespace QTest
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestcoreelement_p.h b/src/testlib/qtestcoreelement_p.h
index 22aa676263..023c50ab2c 100644
--- a/src/testlib/qtestcoreelement_p.h
+++ b/src/testlib/qtestcoreelement_p.h
@@ -56,8 +56,6 @@
#include <QtTest/private/qtestcorelist_p.h>
#include <QtTest/private/qtestelementattribute_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -174,6 +172,4 @@ const QTestElementAttribute *QTestCoreElement<ElementType>::attribute(QTest::Att
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestcorelist_p.h b/src/testlib/qtestcorelist_p.h
index b5044df8ed..bd08ede949 100644
--- a/src/testlib/qtestcorelist_p.h
+++ b/src/testlib/qtestcorelist_p.h
@@ -55,8 +55,6 @@
#include <QtCore/qglobal.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -141,6 +139,4 @@ int QTestCoreList<T>::count()
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestdata.h b/src/testlib/qtestdata.h
index 6c4ef15bdc..d1bc3e7b4e 100644
--- a/src/testlib/qtestdata.h
+++ b/src/testlib/qtestdata.h
@@ -47,8 +47,6 @@
#include <QtCore/qmetatype.h>
#include <QtCore/qstring.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -99,6 +97,4 @@ inline QTestData &operator<<(QTestData &data, const QStringBuilder<A, B> &value)
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestelement_p.h b/src/testlib/qtestelement_p.h
index 77204c4ce5..71f05f94af 100644
--- a/src/testlib/qtestelement_p.h
+++ b/src/testlib/qtestelement_p.h
@@ -55,8 +55,6 @@
#include <QtTest/private/qtestcoreelement_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -80,6 +78,4 @@ class QTestElement: public QTestCoreElement<QTestElement>
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestelementattribute_p.h b/src/testlib/qtestelementattribute_p.h
index 54afb7cd93..c84b6d07c8 100644
--- a/src/testlib/qtestelementattribute_p.h
+++ b/src/testlib/qtestelementattribute_p.h
@@ -55,8 +55,6 @@
#include <QtTest/private/qtestcorelist_p.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -116,6 +114,4 @@ class QTestElementAttribute: public QTestCoreList<QTestElementAttribute>
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h
index 20f988b216..a96cfa7370 100644
--- a/src/testlib/qtestevent.h
+++ b/src/testlib/qtestevent.h
@@ -58,8 +58,6 @@
#include <stdlib.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -227,6 +225,4 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QTestEventList)
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestevent.qdoc b/src/testlib/qtestevent.qdoc
index bef4d1553a..0e7a7e7ac2 100644
--- a/src/testlib/qtestevent.qdoc
+++ b/src/testlib/qtestevent.qdoc
@@ -25,7 +25,7 @@
**
****************************************************************************/
-/*!
+/*!
\class QTestEventList
\inmodule QtTest
diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h
index 15356bc445..b70954cf66 100644
--- a/src/testlib/qtesteventloop.h
+++ b/src/testlib/qtesteventloop.h
@@ -49,8 +49,6 @@
#include <QtCore/qobject.h>
#include <QtCore/qpointer.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -131,6 +129,4 @@ inline void QTestEventLoop::timerEvent(QTimerEvent *e)
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h
index b1f135a722..878806737e 100644
--- a/src/testlib/qtestkeyboard.h
+++ b/src/testlib/qtestkeyboard.h
@@ -62,8 +62,6 @@
#include <QtWidgets/qapplication.h>
#endif
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
@@ -298,6 +296,4 @@ namespace QTest
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QTESTKEYBOARD_H
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h
index c24b09b14c..ea57ac5b8c 100644
--- a/src/testlib/qtestmouse.h
+++ b/src/testlib/qtestmouse.h
@@ -54,14 +54,13 @@
#include <QtCore/qpoint.h>
#include <QtCore/qstring.h>
#include <QtGui/qevent.h>
+#include <QtGui/qwindow.h>
#ifdef QT_WIDGETS_LIB
#include <QtWidgets/qapplication.h>
#include <QtWidgets/qwidget.h>
#endif
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier);
@@ -227,6 +226,4 @@ namespace QTest
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QTESTMOUSE_H
diff --git a/src/testlib/qtestspontaneevent.h b/src/testlib/qtestspontaneevent.h
index ac8ea74cc2..e299981670 100644
--- a/src/testlib/qtestspontaneevent.h
+++ b/src/testlib/qtestspontaneevent.h
@@ -49,8 +49,6 @@
#pragma qt_no_master_include
#endif
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -73,7 +71,7 @@ public:
class QSpontaneKeyEvent
{
public:
- void setSpontaneous() { spont = 1; }
+ void setSpontaneous() { spont = 1; Q_UNUSED(posted) Q_UNUSED(m_accept) Q_UNUSED(reserved) }
bool spontaneous() { return spont; }
virtual void dummyFunc() {}
virtual ~QSpontaneKeyEvent() {}
@@ -112,6 +110,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h
index 5633b06e02..2a719e96f1 100644
--- a/src/testlib/qtestsystem.h
+++ b/src/testlib/qtestsystem.h
@@ -52,8 +52,6 @@
# include <QtWidgets/QWidget>
#endif
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
namespace QTest
@@ -72,7 +70,7 @@ namespace QTest
}
#ifdef QT_GUI_LIB
- inline static bool qWaitForWindowActive(QWindow *window, int timeout = 1000)
+ inline static bool qWaitForWindowActive(QWindow *window, int timeout = 5000)
{
QElapsedTimer timer;
timer.start();
@@ -101,7 +99,7 @@ namespace QTest
return window->isActive();
}
- inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 1000)
+ inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 5000)
{
QElapsedTimer timer;
timer.start();
@@ -145,7 +143,5 @@ namespace QTest
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qtesttouch.h b/src/testlib/qtesttouch.h
index a291507142..9a661b4ecd 100644
--- a/src/testlib/qtesttouch.h
+++ b/src/testlib/qtesttouch.h
@@ -53,12 +53,11 @@
#include <QtTest/qtestspontaneevent.h>
#include <QtCore/qmap.h>
#include <QtGui/qevent.h>
+#include <QtGui/qwindow.h>
#ifdef QT_WIDGETS_LIB
#include <QtWidgets/qwidget.h>
#endif
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device,
@@ -233,6 +232,4 @@ private:
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif // QTESTTOUCH_H
diff --git a/src/testlib/qtestxunitstreamer_p.h b/src/testlib/qtestxunitstreamer_p.h
index e047f644d3..c3278b2b53 100644
--- a/src/testlib/qtestxunitstreamer_p.h
+++ b/src/testlib/qtestxunitstreamer_p.h
@@ -55,8 +55,6 @@
#include <QtCore/qglobal.h>
-QT_BEGIN_HEADER
-
QT_BEGIN_NAMESPACE
@@ -90,6 +88,4 @@ class QTestXunitStreamer
QT_END_NAMESPACE
-QT_END_HEADER
-
#endif
diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp
index 9bc5255bf6..3f77f152b5 100644
--- a/src/testlib/qxmltestlogger.cpp
+++ b/src/testlib/qxmltestlogger.cpp
@@ -246,12 +246,13 @@ void QXmlTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
benchmarkMetricName(result.metric));
xmlQuote(&quotedTag, result.context.tag.toUtf8().constData());
+ const qreal valuePerIteration = qreal(result.value) / qreal(result.iterations);
QTest::qt_asprintf(
&buf,
QTest::benchmarkResultFormatString(),
quotedMetric.constData(),
quotedTag.constData(),
- QByteArray::number(result.value).constData(), //no 64-bit qsnprintf support
+ QByteArray::number(valuePerIteration).constData(), //no 64-bit qsnprintf support
result.iterations);
outputString(buf.constData());
}
diff --git a/src/testlib/qxunittestlogger.cpp b/src/testlib/qxunittestlogger.cpp
index bfe9de2158..0a1a5fb6f9 100644
--- a/src/testlib/qxunittestlogger.cpp
+++ b/src/testlib/qxunittestlogger.cpp
@@ -232,7 +232,9 @@ void QXunitTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
QTest::AI_Metric,
QTest::benchmarkMetricName(QBenchmarkTestMethodData::current->result.metric));
benchmarkElement->addAttribute(QTest::AI_Tag, result.context.tag.toUtf8().data());
- benchmarkElement->addAttribute(QTest::AI_Value, QByteArray::number(result.value).constData());
+
+ const qreal valuePerIteration = qreal(result.value) / qreal(result.iterations);
+ benchmarkElement->addAttribute(QTest::AI_Value, QByteArray::number(valuePerIteration).constData());
char buf[100];
qsnprintf(buf, sizeof(buf), "%i", result.iterations);
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 6b74f23454..97301de151 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -16,6 +16,7 @@ HEADERS = qbenchmark.h \
qbenchmarkmeasurement_p.h \
qbenchmarkvalgrind_p.h \
qbenchmarkevent_p.h \
+ qbenchmarkperfevents_p.h \
qbenchmarkmetric_p.h \
qsignalspy.h \
qtestaccessible.h \
@@ -48,6 +49,7 @@ SOURCES = qtestcase.cpp \
qbenchmarkmeasurement.cpp \
qbenchmarkvalgrind.cpp \
qbenchmarkevent.cpp \
+ qbenchmarkperfevents.cpp \
qbenchmarkmetric.cpp \
qtestelement.cpp \
qtestelementattribute.cpp \
@@ -74,9 +76,3 @@ mac {
}
load(qt_module)
-
-QMAKE_TARGET_PRODUCT = QTestLib
-QMAKE_TARGET_DESCRIPTION = Qt \
- Unit \
- Testing \
- Library