1 /*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <map>
12 #include <string>
13
14 #include "system_wrappers/interface/data_log.h"
15 #include "system_wrappers/interface/data_log_c.h"
16 #include "system_wrappers/source/data_log_c_helpers_unittest.h"
17 #include "gtest/gtest.h"
18
19 using ::webrtc::DataLog;
20
21 // A class for storing the values expected from a log table column when
22 // verifying a log table file.
23 struct ExpectedValues {
24 public:
ExpectedValuesExpectedValues25 ExpectedValues()
26 : values(NULL),
27 multi_value_length(1) {
28 }
29
ExpectedValuesExpectedValues30 ExpectedValues(std::vector<std::string> expected_values,
31 int expected_multi_value_length)
32 : values(expected_values),
33 multi_value_length(expected_multi_value_length) {
34 }
35
36 std::vector<std::string> values;
37 int multi_value_length;
38 };
39
40 typedef std::map<std::string, ExpectedValues> ExpectedValuesMap;
41
42 // A static class used for parsing and verifying data log files.
43 class DataLogParser {
44 public:
45 // Verifies that the log table stored in the file "log_file" corresponds to
46 // the cells and columns specified in "columns".
VerifyTable(FILE * log_file,const ExpectedValuesMap & columns)47 static int VerifyTable(FILE* log_file, const ExpectedValuesMap& columns) {
48 int row = 0;
49 char line_buffer[kMaxLineLength];
50 char* ret = fgets(line_buffer, kMaxLineLength, log_file);
51 EXPECT_FALSE(ret == NULL);
52 if (ret == NULL)
53 return -1;
54
55 std::string line(line_buffer, kMaxLineLength);
56 VerifyHeader(line, columns);
57 while (fgets(line_buffer, kMaxLineLength, log_file) != NULL) {
58 line = std::string(line_buffer, kMaxLineLength);
59 size_t line_position = 0;
60
61 for (ExpectedValuesMap::const_iterator it = columns.begin();
62 it != columns.end(); ++it) {
63 std::string str = ParseElement(line, &line_position,
64 it->second.multi_value_length);
65 EXPECT_EQ(str, it->second.values[row]);
66 if (str != it->second.values[row])
67 return -1;
68 }
69 ++row;
70 }
71 return 0;
72 }
73
74 // Verifies the table header stored in "line" to correspond with the header
75 // specified in "columns".
VerifyHeader(const std::string & line,const ExpectedValuesMap & columns)76 static int VerifyHeader(const std::string& line,
77 const ExpectedValuesMap& columns) {
78 size_t line_position = 0;
79 for (ExpectedValuesMap::const_iterator it = columns.begin();
80 it != columns.end(); ++it) {
81 std::string str = ParseElement(line, &line_position,
82 it->second.multi_value_length);
83 EXPECT_EQ(str, it->first);
84 if (str != it->first)
85 return -1;
86 }
87 return 0;
88 }
89
90 // Parses out and returns one element from the string "line", which contains
91 // one line read from a log table file. An element can either be a column
92 // header or a cell of a row.
ParseElement(const std::string & line,size_t * line_position,int multi_value_length)93 static std::string ParseElement(const std::string& line,
94 size_t* line_position,
95 int multi_value_length) {
96 std::string parsed_cell;
97 parsed_cell = "";
98 for (int i = 0; i < multi_value_length; ++i) {
99 size_t next_separator = line.find(',', *line_position);
100 EXPECT_NE(next_separator, std::string::npos);
101 if (next_separator == std::string::npos)
102 break;
103 parsed_cell += line.substr(*line_position,
104 next_separator - *line_position + 1);
105 *line_position = next_separator + 1;
106 }
107 return parsed_cell;
108 }
109
110 // This constant defines the maximum line length the DataLogParser can
111 // parse.
112 enum { kMaxLineLength = 100 };
113 };
114
TEST(TestDataLog,CreateReturnTest)115 TEST(TestDataLog, CreateReturnTest) {
116 for (int i = 0; i < 10; ++i)
117 ASSERT_EQ(DataLog::CreateLog(), 0);
118 ASSERT_EQ(DataLog::AddTable(DataLog::Combine("a proper table", 1)), 0);
119 for (int i = 0; i < 10; ++i)
120 DataLog::ReturnLog();
121 ASSERT_LT(DataLog::AddTable(DataLog::Combine("table failure", 1)), 0);
122 }
123
TEST(TestDataLog,VerifyCombineMethod)124 TEST(TestDataLog, VerifyCombineMethod) {
125 EXPECT_EQ(std::string("a proper table_1"),
126 DataLog::Combine("a proper table", 1));
127 }
128
TEST(TestDataLog,VerifySingleTable)129 TEST(TestDataLog, VerifySingleTable) {
130 DataLog::CreateLog();
131 DataLog::AddTable(DataLog::Combine("table", 1));
132 DataLog::AddColumn(DataLog::Combine("table", 1), "arrival", 1);
133 DataLog::AddColumn(DataLog::Combine("table", 1), "timestamp", 1);
134 DataLog::AddColumn(DataLog::Combine("table", 1), "size", 5);
135 WebRtc_UWord32 sizes[5] = {1400, 1500, 1600, 1700, 1800};
136 for (int i = 0; i < 10; ++i) {
137 DataLog::InsertCell(DataLog::Combine("table", 1), "arrival",
138 static_cast<double>(i));
139 DataLog::InsertCell(DataLog::Combine("table", 1), "timestamp",
140 static_cast<WebRtc_Word64>(4354 + i));
141 DataLog::InsertCell(DataLog::Combine("table", 1), "size", sizes, 5);
142 DataLog::NextRow(DataLog::Combine("table", 1));
143 }
144 DataLog::ReturnLog();
145 // Verify file
146 FILE* table = fopen("table_1.txt", "r");
147 ASSERT_FALSE(table == NULL);
148 // Read the column names and verify with the expected columns.
149 // Note that the columns are written to file in alphabetical order.
150 // Data expected from parsing the file
151 const int kNumberOfRows = 10;
152 std::string string_arrival[kNumberOfRows] = {
153 "0,", "1,", "2,", "3,", "4,",
154 "5,", "6,", "7,", "8,", "9,"
155 };
156 std::string string_timestamp[kNumberOfRows] = {
157 "4354,", "4355,", "4356,", "4357,",
158 "4358,", "4359,", "4360,", "4361,",
159 "4362,", "4363,"
160 };
161 std::string string_sizes = "1400,1500,1600,1700,1800,";
162 ExpectedValuesMap expected;
163 expected["arrival,"] = ExpectedValues(
164 std::vector<std::string>(string_arrival,
165 string_arrival +
166 kNumberOfRows),
167 1);
168 expected["size[5],,,,,"] = ExpectedValues(
169 std::vector<std::string>(10, string_sizes), 5);
170 expected["timestamp,"] = ExpectedValues(
171 std::vector<std::string>(string_timestamp,
172 string_timestamp +
173 kNumberOfRows),
174 1);
175 ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
176 fclose(table);
177 }
178
TEST(TestDataLog,VerifyMultipleTables)179 TEST(TestDataLog, VerifyMultipleTables) {
180 DataLog::CreateLog();
181 DataLog::AddTable(DataLog::Combine("table", 2));
182 DataLog::AddTable(DataLog::Combine("table", 3));
183 DataLog::AddColumn(DataLog::Combine("table", 2), "arrival", 1);
184 DataLog::AddColumn(DataLog::Combine("table", 2), "timestamp", 1);
185 DataLog::AddColumn(DataLog::Combine("table", 2), "size", 1);
186 DataLog::AddTable(DataLog::Combine("table", 4));
187 DataLog::AddColumn(DataLog::Combine("table", 3), "timestamp", 1);
188 DataLog::AddColumn(DataLog::Combine("table", 3), "arrival", 1);
189 DataLog::AddColumn(DataLog::Combine("table", 4), "size", 1);
190 for (WebRtc_Word32 i = 0; i < 10; ++i) {
191 DataLog::InsertCell(DataLog::Combine("table", 2), "arrival",
192 static_cast<WebRtc_Word32>(i));
193 DataLog::InsertCell(DataLog::Combine("table", 2), "timestamp",
194 static_cast<WebRtc_Word32>(4354 + i));
195 DataLog::InsertCell(DataLog::Combine("table", 2), "size",
196 static_cast<WebRtc_Word32>(1200 + 10 * i));
197 DataLog::InsertCell(DataLog::Combine("table", 3), "timestamp",
198 static_cast<WebRtc_Word32>(4354 + i));
199 DataLog::InsertCell(DataLog::Combine("table", 3), "arrival",
200 static_cast<WebRtc_Word32>(i));
201 DataLog::InsertCell(DataLog::Combine("table", 4), "size",
202 static_cast<WebRtc_Word32>(1200 + 10 * i));
203 DataLog::NextRow(DataLog::Combine("table", 4));
204 DataLog::NextRow(DataLog::Combine("table", 2));
205 DataLog::NextRow(DataLog::Combine("table", 3));
206 }
207 DataLog::ReturnLog();
208
209 // Data expected from parsing the file
210 const int kNumberOfRows = 10;
211 std::string string_arrival[kNumberOfRows] = {
212 "0,", "1,", "2,", "3,", "4,",
213 "5,", "6,", "7,", "8,", "9,"
214 };
215 std::string string_timestamp[kNumberOfRows] = {
216 "4354,", "4355,", "4356,", "4357,",
217 "4358,", "4359,", "4360,", "4361,",
218 "4362,", "4363,"
219 };
220 std::string string_size[kNumberOfRows] = {
221 "1200,", "1210,", "1220,", "1230,",
222 "1240,", "1250,", "1260,", "1270,",
223 "1280,", "1290,"
224 };
225
226 // Verify table 2
227 {
228 FILE* table = fopen("table_2.txt", "r");
229 ASSERT_FALSE(table == NULL);
230 ExpectedValuesMap expected;
231 expected["arrival,"] = ExpectedValues(
232 std::vector<std::string>(string_arrival,
233 string_arrival +
234 kNumberOfRows),
235 1);
236 expected["size,"] = ExpectedValues(
237 std::vector<std::string>(string_size,
238 string_size + kNumberOfRows),
239 1);
240 expected["timestamp,"] = ExpectedValues(
241 std::vector<std::string>(string_timestamp,
242 string_timestamp +
243 kNumberOfRows),
244 1);
245 ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
246 fclose(table);
247 }
248
249 // Verify table 3
250 {
251 FILE* table = fopen("table_3.txt", "r");
252 ASSERT_FALSE(table == NULL);
253 ExpectedValuesMap expected;
254 expected["arrival,"] = ExpectedValues(
255 std::vector<std::string>(string_arrival,
256 string_arrival +
257 kNumberOfRows),
258 1);
259 expected["timestamp,"] = ExpectedValues(
260 std::vector<std::string>(string_timestamp,
261 string_timestamp +
262 kNumberOfRows),
263 1);
264 ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
265 fclose(table);
266 }
267
268 // Verify table 4
269 {
270 FILE* table = fopen("table_4.txt", "r");
271 ASSERT_FALSE(table == NULL);
272 ExpectedValuesMap expected;
273 expected["size,"] = ExpectedValues(
274 std::vector<std::string>(string_size,
275 string_size +
276 kNumberOfRows),
277 1);
278 ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0);
279 fclose(table);
280 }
281 }
282
TEST(TestDataLogCWrapper,VerifyCWrapper)283 TEST(TestDataLogCWrapper, VerifyCWrapper) {
284 // Simply call all C wrapper log functions through the C helper unittests.
285 // Main purpose is to make sure that the linkage is correct.
286
287 EXPECT_EQ(0, WebRtcDataLogCHelper_TestCreateLog());
288 EXPECT_EQ(0, WebRtcDataLogCHelper_TestCombine());
289 EXPECT_EQ(0, WebRtcDataLogCHelper_TestAddTable());
290 EXPECT_EQ(0, WebRtcDataLogCHelper_TestAddColumn());
291 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int());
292 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int());
293 EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
294 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_float());
295 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_float());
296 EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
297 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_double());
298 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_double());
299 EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
300 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int32());
301 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int32());
302 EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
303 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_uint32());
304 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_uint32());
305 EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
306 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int64());
307 EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int64());
308 EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow());
309 EXPECT_EQ(0, WebRtcDataLogCHelper_TestReturnLog());
310 }
311