blob: 78f6ab7e522bf4a1ec2b1812e83ba651acbda4f4 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "trace-test-utils/compare_records.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>
#include <fbl/string.h>
#include <fbl/string_buffer.h>
#include <trace-reader/reader.h>
#include <trace-reader/reader_internal.h>
#include <unittest/unittest.h>
#include "trace-test-utils/read_records.h"
#include "trace-test-utils/squelch.h"
namespace trace_testing {
bool CompareRecords(const fbl::Vector<trace::Record>& records,
size_t start_record, size_t max_num_records,
const char* expected) {
// Strip out timestamps and other varying data that is not controlled by
// the tests.
std::unique_ptr<Squelcher> squelcher =
Squelcher::Create("([0-9]+/[0-9]+)"
"|koid\\(([0-9]+)\\)"
"|koid: ([0-9]+)"
"|ts: ([0-9]+)"
"|end_ts: ([0-9]+)"
"|(0x[0-9a-f]+)");
ZX_DEBUG_ASSERT(squelcher);
fbl::StringBuffer<16384u> buf;
size_t num_recs = 0;
for (size_t i = start_record; i < records.size(); ++i) {
if (num_recs == max_num_records)
break;
const auto& record = records[i];
fbl::String from_str = record.ToString();
fbl::String to_str = squelcher->Squelch(from_str.c_str());
UNITTEST_TRACEF(2, "Squelch from: %s\n", from_str.c_str());
UNITTEST_TRACEF(2, "Squelch to: %s\n", to_str.c_str());
buf.Append(to_str);
buf.Append('\n');
++num_recs;
}
if (strcmp(buf.c_str(), expected) != 0) {
fprintf(stderr, "Records do not match expected contents:\n");
fprintf(stderr, "Buffer:\n%s\n", buf.c_str());
fprintf(stderr, "Expected:\n%s\n", expected);
return false;
}
return true;
}
bool ComparePartialBuffer(const fbl::Vector<trace::Record>& records,
size_t max_num_records, const char* expected,
size_t* out_leading_to_skip) {
// A valid buffer should at least have the initialization record.
if (records.size() == 0) {
fprintf(stderr, "expected an initialization record\n");
return false;
}
if (records[0].type() != trace::RecordType::kInitialization) {
fprintf(stderr, "expected initialization record\n");
return false;
}
// Sanity check the recorded ticks/seconds.
if (records[0].GetInitialization().ticks_per_second != zx_ticks_per_second()) {
fprintf(stderr, "Bad ticks/second field in initialization record\n");
return false;
}
// Done with this record, skip it in further analysis.
size_t skip_count = 1;
if (!CompareRecords(records, skip_count, max_num_records, expected)) {
// Diagnostic messages already printed.
return false;
}
if (out_leading_to_skip) {
*out_leading_to_skip = skip_count;
}
return true;
}
bool CompareBuffer(const fbl::Vector<trace::Record>& records,
const char* expected) {
return ComparePartialBuffer(records, SIZE_MAX, expected, nullptr);
}
} // namespace trace_testing