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