Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2013 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/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h"
     12 
     13 #include <stdio.h>
     14 
     15 #include <algorithm>
     16 #include <vector>
     17 
     18 #include "webrtc/base/constructormagic.h"
     19 #include "webrtc/base/scoped_ptr.h"
     20 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_fileutils.h"
     21 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
     22 #include "webrtc/test/testsupport/fileutils.h"
     23 
     24 namespace webrtc {
     25 namespace testing {
     26 namespace bwe {
     27 
     28 // The format of BWE test baseline files is extremely simple:
     29 //   1. All read/written entities are 32-bit unsigned integers in network byte
     30 //      order (Big Endian).
     31 //   2. Files beging with a 2 word header containing a magic marker and file
     32 //      format version indicator. The Magic marker reads "BWE!" in a hex dump.
     33 //   3. Each estimate is logged as a pair of words: time in milliseconds and
     34 //      estimated bit rate, in bits per second.
     35 const uint32_t kMagicMarker = 0x42574521;
     36 const uint32_t kFileVersion1 = 0x00000001;
     37 const char kResourceSubDir[] = "remote_bitrate_estimator";
     38 
     39 class BaseLineFileVerify : public BaseLineFileInterface {
     40  public:
     41   // If |allow_missing_file| is set, VerifyOrWrite() will return true even if
     42   // the baseline file is missing. This is the default when verifying files, but
     43   // not when updating (i.e. we always write it out if missing).
     44   BaseLineFileVerify(const std::string& filepath, bool allow_missing_file)
     45       : reader_(),
     46         fail_to_read_response_(false) {
     47     rtc::scoped_ptr<ResourceFileReader> reader;
     48     reader.reset(ResourceFileReader::Create(filepath, "bin"));
     49     if (!reader.get()) {
     50       printf("WARNING: Missing baseline file for BWE test: %s.bin\n",
     51              filepath.c_str());
     52       fail_to_read_response_ = allow_missing_file;
     53     } else {
     54       uint32_t magic_marker = 0;
     55       uint32_t file_version = 0;
     56       if (reader->Read(&magic_marker) && magic_marker == kMagicMarker &&
     57           reader->Read(&file_version) && file_version == kFileVersion1) {
     58         reader_.swap(reader);
     59       } else {
     60         printf("WARNING: Bad baseline file header for BWE test: %s.bin\n",
     61                filepath.c_str());
     62       }
     63     }
     64   }
     65   virtual ~BaseLineFileVerify() {}
     66 
     67   virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) {
     68     if (reader_.get()) {
     69       uint32_t read_ms = 0;
     70       uint32_t read_bps = 0;
     71       if (reader_->Read(&read_ms) && read_ms == time_ms &&
     72           reader_->Read(&read_bps) && read_bps == estimate_bps) {
     73       } else {
     74         printf("ERROR: Baseline differs starting at: %d ms (%d vs %d)!\n",
     75             static_cast<uint32_t>(time_ms), estimate_bps, read_bps);
     76         reader_.reset(NULL);
     77       }
     78     }
     79   }
     80 
     81   virtual bool VerifyOrWrite() {
     82     if (reader_.get()) {
     83       if (reader_->IsAtEnd()) {
     84         return true;
     85       } else {
     86         printf("ERROR: Baseline file contains more data!\n");
     87         return false;
     88       }
     89     }
     90     return fail_to_read_response_;
     91   }
     92 
     93  private:
     94   rtc::scoped_ptr<ResourceFileReader> reader_;
     95   bool fail_to_read_response_;
     96 
     97   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileVerify);
     98 };
     99 
    100 class BaseLineFileUpdate : public BaseLineFileInterface {
    101  public:
    102   BaseLineFileUpdate(const std::string& filepath,
    103                      BaseLineFileInterface* verifier)
    104       : verifier_(verifier),
    105         output_content_(),
    106         filepath_(filepath) {
    107     output_content_.push_back(kMagicMarker);
    108     output_content_.push_back(kFileVersion1);
    109   }
    110   virtual ~BaseLineFileUpdate() {}
    111 
    112   virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) {
    113     verifier_->Estimate(time_ms, estimate_bps);
    114     output_content_.push_back(static_cast<uint32_t>(time_ms));
    115     output_content_.push_back(estimate_bps);
    116   }
    117 
    118   virtual bool VerifyOrWrite() {
    119     if (!verifier_->VerifyOrWrite()) {
    120       std::string dir_path = webrtc::test::OutputPath() + kResourceSubDir;
    121       if (!webrtc::test::CreateDir(dir_path)) {
    122         printf("WARNING: Cannot create output dir: %s\n", dir_path.c_str());
    123         return false;
    124       }
    125       rtc::scoped_ptr<OutputFileWriter> writer;
    126       writer.reset(OutputFileWriter::Create(filepath_, "bin"));
    127       if (!writer.get()) {
    128         printf("WARNING: Cannot create output file: %s.bin\n",
    129             filepath_.c_str());
    130         return false;
    131       }
    132       printf("NOTE: Writing baseline file for BWE test: %s.bin\n",
    133              filepath_.c_str());
    134       for (std::vector<uint32_t>::iterator it = output_content_.begin();
    135           it != output_content_.end(); ++it) {
    136         writer->Write(*it);
    137       }
    138       return true;
    139     }
    140     printf("NOTE: No change, not writing: %s\n", filepath_.c_str());
    141     return true;
    142   }
    143 
    144  private:
    145   rtc::scoped_ptr<BaseLineFileInterface> verifier_;
    146   std::vector<uint32_t> output_content_;
    147   std::string filepath_;
    148 
    149   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileUpdate);
    150 };
    151 
    152 BaseLineFileInterface* BaseLineFileInterface::Create(
    153     const std::string& filename, bool write_output_file) {
    154   std::string filepath = filename;
    155   std::replace(filepath.begin(), filepath.end(), '/', '_');
    156   filepath = std::string(kResourceSubDir) + "/" + filepath;
    157 
    158   rtc::scoped_ptr<BaseLineFileInterface> result;
    159   result.reset(new BaseLineFileVerify(filepath, !write_output_file));
    160   if (write_output_file) {
    161     // Takes ownership of the |verifier| instance.
    162     result.reset(new BaseLineFileUpdate(filepath, result.release()));
    163   }
    164   return result.release();
    165 }
    166 }  // namespace bwe
    167 }  // namespace testing
    168 }  // namespace webrtc
    169