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: 25 ExpectedValues() 26 : values(NULL), 27 multi_value_length(1) { 28 } 29 30 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". 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". 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. 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 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 124 TEST(TestDataLog, VerifyCombineMethod) { 125 EXPECT_EQ(std::string("a proper table_1"), 126 DataLog::Combine("a proper table", 1)); 127 } 128 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 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 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