+T_DECL(reject_old_events,
+ "ensure that kdebug rejects events from before tracing began",
+ T_META_ASROOT(true), T_META_CHECK_LEAKS(false))
+{
+ __block uint64_t event_horizon_ts;
+ __block int events = 0;
+
+ ktrace_session_t s = ktrace_session_create();
+ T_QUIET; T_ASSERT_NOTNULL(s, "ktrace_session_create");
+
+ ktrace_events_range(s, KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 0),
+ KDBG_EVENTID(DBG_BSD + 1, 0, 0),
+ ^(struct trace_point *tp)
+ {
+ events++;
+ T_EXPECT_GT(tp->timestamp, event_horizon_ts,
+ "events in trace should be from after tracing began");
+ });
+
+ ktrace_set_completion_handler(s, ^{
+ T_EXPECT_EQ(events, 2, "should see only two events");
+ ktrace_session_destroy(s);
+ T_END;
+ });
+
+ event_horizon_ts = mach_absolute_time();
+
+ T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
+ /* first, try an old event at the beginning of trace */
+ assert_kdebug_test(KDBG_TEST_OLD_TIMES);
+ /* after a good event has been traced, old events should be rejected */
+ assert_kdebug_test(KDBG_TEST_OLD_TIMES);
+ ktrace_end(s, 0);
+
+ dispatch_main();
+}
+
+#define ORDERING_TIMEOUT_SEC 5
+
+T_DECL(ascending_time_order,
+ "ensure that kdebug events are in ascending order based on time",
+ T_META_ASROOT(true), T_META_CHECK_LEAKS(false))
+{
+ __block uint64_t prev_ts = 0;
+ __block uint32_t prev_debugid = 0;
+ __block unsigned int prev_cpu = 0;
+ __block bool in_order = true;
+
+ ktrace_session_t s = ktrace_session_create();
+ T_QUIET; T_ASSERT_NOTNULL(s, "ktrace_session_create");
+
+ ktrace_events_all(s, ^(struct trace_point *tp) {
+ if (tp->timestamp < prev_ts) {
+ in_order = false;
+ T_FAIL("found timestamps out of order");
+ T_LOG("%" PRIu64 ": %#" PRIx32 " (cpu %d)",
+ prev_ts, prev_debugid, prev_cpu);
+ T_LOG("%" PRIu64 ": %#" PRIx32 " (cpu %d)",
+ tp->timestamp, tp->debugid, tp->cpuid);
+ }
+ });
+
+ ktrace_set_completion_handler(s, ^{
+ ktrace_session_destroy(s);
+ T_EXPECT_TRUE(in_order, "event timestamps were in-order");
+ T_END;
+ });
+
+ T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
+
+ /* try to inject old timestamps into trace */
+ assert_kdebug_test(KDBG_TEST_OLD_TIMES);
+
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, ORDERING_TIMEOUT_SEC * NSEC_PER_SEC),
+ dispatch_get_main_queue(), ^{
+ T_LOG("ending test after timeout");
+ ktrace_end(s, 1);
+ });
+
+ dispatch_main();
+
+}
+
+#pragma mark dyld tracing
+