|  | /* | 
|  | *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "webrtc/system_wrappers/interface/data_log.h" | 
|  |  | 
|  | #include <map> | 
|  | #include <string> | 
|  |  | 
|  | #include "gtest/gtest.h" | 
|  | #include "webrtc/system_wrappers/interface/data_log_c.h" | 
|  | #include "webrtc/system_wrappers/source/data_log_c_helpers_unittest.h" | 
|  |  | 
|  | using ::webrtc::DataLog; | 
|  |  | 
|  | // A class for storing the values expected from a log table column when | 
|  | // verifying a log table file. | 
|  | struct ExpectedValues { | 
|  | public: | 
|  | ExpectedValues() | 
|  | : values(), | 
|  | multi_value_length(1) { | 
|  | } | 
|  |  | 
|  | ExpectedValues(std::vector<std::string> expected_values, | 
|  | int expected_multi_value_length) | 
|  | : values(expected_values), | 
|  | multi_value_length(expected_multi_value_length) { | 
|  | } | 
|  |  | 
|  | std::vector<std::string> values; | 
|  | int multi_value_length; | 
|  | }; | 
|  |  | 
|  | typedef std::map<std::string, ExpectedValues> ExpectedValuesMap; | 
|  |  | 
|  | // A static class used for parsing and verifying data log files. | 
|  | class DataLogParser { | 
|  | public: | 
|  | // Verifies that the log table stored in the file "log_file" corresponds to | 
|  | // the cells and columns specified in "columns". | 
|  | static int VerifyTable(FILE* log_file, const ExpectedValuesMap& columns) { | 
|  | int row = 0; | 
|  | char line_buffer[kMaxLineLength]; | 
|  | char* ret = fgets(line_buffer, kMaxLineLength, log_file); | 
|  | EXPECT_FALSE(ret == NULL); | 
|  | if (ret == NULL) | 
|  | return -1; | 
|  |  | 
|  | std::string line(line_buffer, kMaxLineLength); | 
|  | VerifyHeader(line, columns); | 
|  | while (fgets(line_buffer, kMaxLineLength, log_file) != NULL) { | 
|  | line = std::string(line_buffer, kMaxLineLength); | 
|  | size_t line_position = 0; | 
|  |  | 
|  | for (ExpectedValuesMap::const_iterator it = columns.begin(); | 
|  | it != columns.end(); ++it) { | 
|  | std::string str = ParseElement(line, &line_position, | 
|  | it->second.multi_value_length); | 
|  | EXPECT_EQ(str, it->second.values[row]); | 
|  | if (str != it->second.values[row]) | 
|  | return -1; | 
|  | } | 
|  | ++row; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // Verifies the table header stored in "line" to correspond with the header | 
|  | // specified in "columns". | 
|  | static int VerifyHeader(const std::string& line, | 
|  | const ExpectedValuesMap& columns) { | 
|  | size_t line_position = 0; | 
|  | for (ExpectedValuesMap::const_iterator it = columns.begin(); | 
|  | it != columns.end(); ++it) { | 
|  | std::string str = ParseElement(line, &line_position, | 
|  | it->second.multi_value_length); | 
|  | EXPECT_EQ(str, it->first); | 
|  | if (str != it->first) | 
|  | return -1; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // Parses out and returns one element from the string "line", which contains | 
|  | // one line read from a log table file. An element can either be a column | 
|  | // header or a cell of a row. | 
|  | static std::string ParseElement(const std::string& line, | 
|  | size_t* line_position, | 
|  | int multi_value_length) { | 
|  | std::string parsed_cell; | 
|  | parsed_cell = ""; | 
|  | for (int i = 0; i < multi_value_length; ++i) { | 
|  | size_t next_separator = line.find(',', *line_position); | 
|  | EXPECT_NE(next_separator, std::string::npos); | 
|  | if (next_separator == std::string::npos) | 
|  | break; | 
|  | parsed_cell += line.substr(*line_position, | 
|  | next_separator - *line_position + 1); | 
|  | *line_position = next_separator + 1; | 
|  | } | 
|  | return parsed_cell; | 
|  | } | 
|  |  | 
|  | // This constant defines the maximum line length the DataLogParser can | 
|  | // parse. | 
|  | enum { kMaxLineLength = 100 }; | 
|  | }; | 
|  |  | 
|  | TEST(TestDataLog, CreateReturnTest) { | 
|  | for (int i = 0; i < 10; ++i) | 
|  | ASSERT_EQ(DataLog::CreateLog(), 0); | 
|  | ASSERT_EQ(DataLog::AddTable(DataLog::Combine("a proper table", 1)), 0); | 
|  | for (int i = 0; i < 10; ++i) | 
|  | DataLog::ReturnLog(); | 
|  | ASSERT_LT(DataLog::AddTable(DataLog::Combine("table failure", 1)), 0); | 
|  | } | 
|  |  | 
|  | TEST(TestDataLog, VerifyCombineMethod) { | 
|  | EXPECT_EQ(std::string("a proper table_1"), | 
|  | DataLog::Combine("a proper table", 1)); | 
|  | } | 
|  |  | 
|  | TEST(TestDataLog, VerifySingleTable) { | 
|  | DataLog::CreateLog(); | 
|  | DataLog::AddTable(DataLog::Combine("table", 1)); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 1), "arrival", 1); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 1), "timestamp", 1); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 1), "size", 5); | 
|  | WebRtc_UWord32 sizes[5] = {1400, 1500, 1600, 1700, 1800}; | 
|  | for (int i = 0; i < 10; ++i) { | 
|  | DataLog::InsertCell(DataLog::Combine("table", 1), "arrival", | 
|  | static_cast<double>(i)); | 
|  | DataLog::InsertCell(DataLog::Combine("table", 1), "timestamp", | 
|  | static_cast<WebRtc_Word64>(4354 + i)); | 
|  | DataLog::InsertCell(DataLog::Combine("table", 1), "size", sizes, 5); | 
|  | DataLog::NextRow(DataLog::Combine("table", 1)); | 
|  | } | 
|  | DataLog::ReturnLog(); | 
|  | // Verify file | 
|  | FILE* table = fopen("table_1.txt", "r"); | 
|  | ASSERT_FALSE(table == NULL); | 
|  | // Read the column names and verify with the expected columns. | 
|  | // Note that the columns are written to file in alphabetical order. | 
|  | // Data expected from parsing the file | 
|  | const int kNumberOfRows = 10; | 
|  | std::string string_arrival[kNumberOfRows] = { | 
|  | "0,", "1,", "2,", "3,", "4,", | 
|  | "5,", "6,", "7,", "8,", "9," | 
|  | }; | 
|  | std::string string_timestamp[kNumberOfRows] = { | 
|  | "4354,", "4355,", "4356,", "4357,", | 
|  | "4358,", "4359,", "4360,", "4361,", | 
|  | "4362,", "4363," | 
|  | }; | 
|  | std::string string_sizes = "1400,1500,1600,1700,1800,"; | 
|  | ExpectedValuesMap expected; | 
|  | expected["arrival,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_arrival, | 
|  | string_arrival + | 
|  | kNumberOfRows), | 
|  | 1); | 
|  | expected["size[5],,,,,"] = ExpectedValues( | 
|  | std::vector<std::string>(10, string_sizes), 5); | 
|  | expected["timestamp,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_timestamp, | 
|  | string_timestamp + | 
|  | kNumberOfRows), | 
|  | 1); | 
|  | ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0); | 
|  | fclose(table); | 
|  | } | 
|  |  | 
|  | TEST(TestDataLog, VerifyMultipleTables) { | 
|  | DataLog::CreateLog(); | 
|  | DataLog::AddTable(DataLog::Combine("table", 2)); | 
|  | DataLog::AddTable(DataLog::Combine("table", 3)); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 2), "arrival", 1); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 2), "timestamp", 1); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 2), "size", 1); | 
|  | DataLog::AddTable(DataLog::Combine("table", 4)); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 3), "timestamp", 1); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 3), "arrival", 1); | 
|  | DataLog::AddColumn(DataLog::Combine("table", 4), "size", 1); | 
|  | for (WebRtc_Word32 i = 0; i < 10; ++i) { | 
|  | DataLog::InsertCell(DataLog::Combine("table", 2), "arrival", | 
|  | static_cast<WebRtc_Word32>(i)); | 
|  | DataLog::InsertCell(DataLog::Combine("table", 2), "timestamp", | 
|  | static_cast<WebRtc_Word32>(4354 + i)); | 
|  | DataLog::InsertCell(DataLog::Combine("table", 2), "size", | 
|  | static_cast<WebRtc_Word32>(1200 + 10 * i)); | 
|  | DataLog::InsertCell(DataLog::Combine("table", 3), "timestamp", | 
|  | static_cast<WebRtc_Word32>(4354 + i)); | 
|  | DataLog::InsertCell(DataLog::Combine("table", 3), "arrival", | 
|  | static_cast<WebRtc_Word32>(i)); | 
|  | DataLog::InsertCell(DataLog::Combine("table", 4), "size", | 
|  | static_cast<WebRtc_Word32>(1200 + 10 * i)); | 
|  | DataLog::NextRow(DataLog::Combine("table", 4)); | 
|  | DataLog::NextRow(DataLog::Combine("table", 2)); | 
|  | DataLog::NextRow(DataLog::Combine("table", 3)); | 
|  | } | 
|  | DataLog::ReturnLog(); | 
|  |  | 
|  | // Data expected from parsing the file | 
|  | const int kNumberOfRows = 10; | 
|  | std::string string_arrival[kNumberOfRows] = { | 
|  | "0,", "1,", "2,", "3,", "4,", | 
|  | "5,", "6,", "7,", "8,", "9," | 
|  | }; | 
|  | std::string string_timestamp[kNumberOfRows] = { | 
|  | "4354,", "4355,", "4356,", "4357,", | 
|  | "4358,", "4359,", "4360,", "4361,", | 
|  | "4362,", "4363," | 
|  | }; | 
|  | std::string string_size[kNumberOfRows] = { | 
|  | "1200,", "1210,", "1220,", "1230,", | 
|  | "1240,", "1250,", "1260,", "1270,", | 
|  | "1280,", "1290," | 
|  | }; | 
|  |  | 
|  | // Verify table 2 | 
|  | { | 
|  | FILE* table = fopen("table_2.txt", "r"); | 
|  | ASSERT_FALSE(table == NULL); | 
|  | ExpectedValuesMap expected; | 
|  | expected["arrival,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_arrival, | 
|  | string_arrival + | 
|  | kNumberOfRows), | 
|  | 1); | 
|  | expected["size,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_size, | 
|  | string_size + kNumberOfRows), | 
|  | 1); | 
|  | expected["timestamp,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_timestamp, | 
|  | string_timestamp + | 
|  | kNumberOfRows), | 
|  | 1); | 
|  | ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0); | 
|  | fclose(table); | 
|  | } | 
|  |  | 
|  | // Verify table 3 | 
|  | { | 
|  | FILE* table = fopen("table_3.txt", "r"); | 
|  | ASSERT_FALSE(table == NULL); | 
|  | ExpectedValuesMap expected; | 
|  | expected["arrival,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_arrival, | 
|  | string_arrival + | 
|  | kNumberOfRows), | 
|  | 1); | 
|  | expected["timestamp,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_timestamp, | 
|  | string_timestamp + | 
|  | kNumberOfRows), | 
|  | 1); | 
|  | ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0); | 
|  | fclose(table); | 
|  | } | 
|  |  | 
|  | // Verify table 4 | 
|  | { | 
|  | FILE* table = fopen("table_4.txt", "r"); | 
|  | ASSERT_FALSE(table == NULL); | 
|  | ExpectedValuesMap expected; | 
|  | expected["size,"] = ExpectedValues( | 
|  | std::vector<std::string>(string_size, | 
|  | string_size + | 
|  | kNumberOfRows), | 
|  | 1); | 
|  | ASSERT_EQ(DataLogParser::VerifyTable(table, expected), 0); | 
|  | fclose(table); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST(TestDataLogCWrapper, VerifyCWrapper) { | 
|  | // Simply call all C wrapper log functions through the C helper unittests. | 
|  | // Main purpose is to make sure that the linkage is correct. | 
|  |  | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestCreateLog()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestCombine()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestAddTable()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestAddColumn()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_float()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_float()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_double()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_double()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int32()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int32()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_uint32()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_uint32()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertCell_int64()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestInsertArray_int64()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestNextRow()); | 
|  | EXPECT_EQ(0, WebRtcDataLogCHelper_TestReturnLog()); | 
|  | } |