1e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes/*
2e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes *
4e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes *  Use of this source code is governed by a BSD-style license
5e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes *  that can be found in the LICENSE file in the root of the source
6e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes *  tree. An additional intellectual property rights grant can be found
7e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes *  in the file PATENTS.  All contributing project authors may
8e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes *  be found in the AUTHORS file in the root of the source tree.
9e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes */
10e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
11e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes#include "webrtc/modules/remote_bitrate_estimator/test/metric_recorder.h"
12e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
132386a45dc710f74174ae8b3ba18b744839b969d9Cesar Magalhaes#include <math.h>
14e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes#include <algorithm>
15e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes#include <vector>
16e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
17e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes#include "testing/gtest/include/gtest/gtest.h"
18e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
19e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaesnamespace webrtc {
20e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaesnamespace testing {
21e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaesnamespace bwe {
22e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
23e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaesclass MetricRecorderTest : public ::testing::Test {
24e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes public:
25e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  MetricRecorderTest() : metric_recorder_("Test", 0, nullptr, nullptr) {}
26e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
27e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  ~MetricRecorderTest() {}
28e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
29e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes protected:
30e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  MetricRecorder metric_recorder_;
31e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes};
32e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
33e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar MagalhaesTEST_F(MetricRecorderTest, NoPackets) {
34e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.AverageBitrateKbps(0), 0);
35e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.DelayStdDev(), 0.0);
36e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(0), 0);
37e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(5), 0);
38e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(95), 0);
39e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(100), 0);
40e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes}
41e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
42e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar MagalhaesTEST_F(MetricRecorderTest, RegularPackets) {
43e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  const size_t kPayloadSizeBytes = 1200;
44e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  const int64_t kDelayMs = 20;
45e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  const int64_t kInterpacketGapMs = 5;
46e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  const int kNumPackets = 1000;
47e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
48e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  for (int i = 0; i < kNumPackets; ++i) {
49e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    int64_t arrival_time_ms = kInterpacketGapMs * i + kDelayMs;
502386a45dc710f74174ae8b3ba18b744839b969d9Cesar Magalhaes    metric_recorder_.UpdateTimeMs(arrival_time_ms);
51e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    metric_recorder_.PushDelayMs(kDelayMs, arrival_time_ms);
52e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    metric_recorder_.PushThroughputBytes(kPayloadSizeBytes, arrival_time_ms);
53e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  }
54e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
55e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_NEAR(
56e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes      metric_recorder_.AverageBitrateKbps(0),
57e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes      static_cast<uint32_t>(kPayloadSizeBytes * 8) / (kInterpacketGapMs), 10);
58e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
59e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.DelayStdDev(), 0.0);
60e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
61e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(0), kDelayMs);
62e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(5), kDelayMs);
63e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(95), kDelayMs);
64e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(100), kDelayMs);
65e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes}
66e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
67e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar MagalhaesTEST_F(MetricRecorderTest, VariableDelayPackets) {
68e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  const size_t kPayloadSizeBytes = 1200;
69e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  const int64_t kInterpacketGapMs = 2000;
70e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  const int kNumPackets = 1000;
71e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
72e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  std::vector<int64_t> delays_ms;
73e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  for (int i = 0; i < kNumPackets; ++i) {
74e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    delays_ms.push_back(static_cast<int64_t>(i + 1));
75e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  }
76e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  // Order of packets should not matter here.
77e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  std::random_shuffle(delays_ms.begin(), delays_ms.end());
78e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
79e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  int first_received_ms = delays_ms[0];
80e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  int64_t last_received_ms = 0;
81e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  for (int i = 0; i < kNumPackets; ++i) {
82e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    int64_t arrival_time_ms = kInterpacketGapMs * i + delays_ms[i];
83e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    last_received_ms = std::max(last_received_ms, arrival_time_ms);
842386a45dc710f74174ae8b3ba18b744839b969d9Cesar Magalhaes    metric_recorder_.UpdateTimeMs(arrival_time_ms);
85e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    metric_recorder_.PushDelayMs(delays_ms[i], arrival_time_ms);
86e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes    metric_recorder_.PushThroughputBytes(kPayloadSizeBytes, arrival_time_ms);
87e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  }
88e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
89e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  size_t received_bits = kPayloadSizeBytes * 8 * kNumPackets;
90e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_NEAR(metric_recorder_.AverageBitrateKbps(0),
91e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes              static_cast<uint32_t>(received_bits) /
92e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes                  ((last_received_ms - first_received_ms)),
93e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes              10);
94e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
95e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  double expected_x = (kNumPackets + 1) / 2.0;
96e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  double expected_x2 = ((kNumPackets + 1) * (2 * kNumPackets + 1)) / 6.0;
97e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  double var = expected_x2 - pow(expected_x, 2.0);
98e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_NEAR(metric_recorder_.DelayStdDev(), sqrt(var), kNumPackets / 1000.0);
99e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
100e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(0), 1);
101e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(5), (5 * kNumPackets) / 100);
102e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(95), (95 * kNumPackets) / 100);
103e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes  EXPECT_EQ(metric_recorder_.NthDelayPercentile(100), kNumPackets);
104e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes}
105e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes
106e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes}  // namespace bwe
107e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes}  // namespace testing
108e2cb1f12c3d1c5500de1b733dfc8bbfea504d89fCesar Magalhaes}  // namespace webrtc
109