1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <trace-reader/reader.h>
6
7#include <stdint.h>
8
9#include <fbl/algorithm.h>
10#include <fbl/vector.h>
11#include <unittest/unittest.h>
12
13namespace {
14
15template <typename T>
16uint64_t ToWord(const T& value) {
17    return *reinterpret_cast<const uint64_t*>(&value);
18}
19
20trace::TraceReader::RecordConsumer MakeRecordConsumer(
21    fbl::Vector<trace::Record>* out_records) {
22    return [out_records](trace::Record record) {
23        out_records->push_back(fbl::move(record));
24    };
25}
26
27trace::TraceReader::ErrorHandler MakeErrorHandler(fbl::String* out_error) {
28    return [out_error](fbl::String error) {
29        *out_error = fbl::move(error);
30    };
31}
32
33bool empty_chunk_test() {
34    BEGIN_TEST;
35
36    uint64_t value;
37    int64_t int64_value;
38    double double_value;
39    fbl::StringPiece string_value;
40    trace::Chunk subchunk;
41
42    trace::Chunk empty;
43    EXPECT_EQ(0u, empty.remaining_words());
44
45    EXPECT_FALSE(empty.ReadUint64(&value));
46
47    EXPECT_FALSE(empty.ReadInt64(&int64_value));
48
49    EXPECT_FALSE(empty.ReadDouble(&double_value));
50
51    EXPECT_TRUE(empty.ReadString(0u, &string_value));
52    EXPECT_TRUE(string_value.empty());
53    EXPECT_FALSE(empty.ReadString(1u, &string_value));
54
55    EXPECT_TRUE(empty.ReadChunk(0u, &subchunk));
56    EXPECT_EQ(0u, subchunk.remaining_words());
57    EXPECT_FALSE(empty.ReadChunk(1u, &subchunk));
58
59    END_TEST;
60}
61
62bool non_empty_chunk_test() {
63    BEGIN_TEST;
64
65    uint64_t value;
66    int64_t int64_value;
67    double double_value;
68    fbl::StringPiece string_value;
69    trace::Chunk subchunk;
70
71    uint64_t kData[] = {
72        // uint64 values
73        0,
74        UINT64_MAX,
75        // int64 values
76        ToWord(INT64_MIN),
77        ToWord(INT64_MAX),
78        // double values
79        ToWord(1.5),
80        ToWord(-3.14),
81        // string values (will be filled in)
82        0,
83        0,
84        // sub-chunk values
85        123,
86        456,
87        // more stuff beyond sub-chunk
88        789,
89    };
90    memcpy(kData + 6, "Hello World!----", 16);
91
92    trace::Chunk chunk(kData, fbl::count_of(kData));
93    EXPECT_EQ(fbl::count_of(kData), chunk.remaining_words());
94
95    EXPECT_TRUE(chunk.ReadUint64(&value));
96    EXPECT_EQ(0, value);
97    EXPECT_EQ(10u, chunk.remaining_words());
98
99    EXPECT_TRUE(chunk.ReadUint64(&value));
100    EXPECT_EQ(UINT64_MAX, value);
101    EXPECT_EQ(9u, chunk.remaining_words());
102
103    EXPECT_TRUE(chunk.ReadInt64(&int64_value));
104    EXPECT_EQ(INT64_MIN, int64_value);
105    EXPECT_EQ(8u, chunk.remaining_words());
106
107    EXPECT_TRUE(chunk.ReadInt64(&int64_value));
108    EXPECT_EQ(INT64_MAX, int64_value);
109    EXPECT_EQ(7u, chunk.remaining_words());
110
111    EXPECT_TRUE(chunk.ReadDouble(&double_value));
112    EXPECT_EQ(1.5, double_value);
113    EXPECT_EQ(6u, chunk.remaining_words());
114
115    EXPECT_TRUE(chunk.ReadDouble(&double_value));
116    EXPECT_EQ(-3.14, double_value);
117    EXPECT_EQ(5u, chunk.remaining_words());
118
119    EXPECT_TRUE(chunk.ReadString(0u, &string_value));
120    EXPECT_TRUE(string_value.empty());
121    EXPECT_EQ(5u, chunk.remaining_words());
122
123    EXPECT_TRUE(chunk.ReadString(12u, &string_value));
124    EXPECT_EQ(12u, string_value.length());
125    EXPECT_EQ(reinterpret_cast<const char*>(kData + 6), string_value.data());
126    EXPECT_TRUE(fbl::String(string_value) == "Hello World!");
127    EXPECT_EQ(3u, chunk.remaining_words());
128
129    EXPECT_TRUE(chunk.ReadChunk(2u, &subchunk));
130    EXPECT_EQ(2u, subchunk.remaining_words());
131    EXPECT_TRUE(subchunk.ReadUint64(&value));
132
133    EXPECT_EQ(123, value);
134    EXPECT_EQ(1u, subchunk.remaining_words());
135
136    EXPECT_TRUE(chunk.ReadUint64(&value));
137    EXPECT_EQ(789, value);
138    EXPECT_EQ(0u, chunk.remaining_words());
139
140    EXPECT_TRUE(subchunk.ReadUint64(&value));
141    EXPECT_EQ(456, value);
142    EXPECT_EQ(0u, subchunk.remaining_words());
143
144    EXPECT_FALSE(subchunk.ReadUint64(&value));
145    EXPECT_FALSE(chunk.ReadUint64(&value));
146
147    END_TEST;
148}
149
150bool initial_state_test() {
151    BEGIN_TEST;
152
153    fbl::Vector<trace::Record> records;
154    fbl::String error;
155    trace::TraceReader reader(MakeRecordConsumer(&records), MakeErrorHandler(&error));
156
157    EXPECT_EQ(0, reader.current_provider_id());
158    EXPECT_TRUE(reader.current_provider_name() == "");
159    EXPECT_TRUE(reader.GetProviderName(0) == "");
160    EXPECT_EQ(0, records.size());
161    EXPECT_TRUE(error.empty());
162
163    END_TEST;
164}
165
166bool empty_buffer_test() {
167    BEGIN_TEST;
168
169    fbl::Vector<trace::Record> records;
170    fbl::String error;
171    trace::TraceReader reader(MakeRecordConsumer(&records), MakeErrorHandler(&error));
172
173    trace::Chunk empty;
174    EXPECT_TRUE(reader.ReadRecords(empty));
175    EXPECT_EQ(0, records.size());
176    EXPECT_TRUE(error.empty());
177
178    END_TEST;
179}
180
181// NOTE: Most of the reader is covered by the libtrace tests.
182
183} // namespace
184
185BEGIN_TEST_CASE(reader_tests)
186RUN_TEST(empty_chunk_test)
187RUN_TEST(non_empty_chunk_test)
188RUN_TEST(initial_state_test)
189RUN_TEST(empty_buffer_test)
190END_TEST_CASE(reader_tests)
191