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