/*
 *  Copyright 2018 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 "test/scenario/stats_collection.h"

#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "call/audio_receive_stream.h"
#include "call/video_receive_stream.h"
#include "call/video_send_stream.h"
#include "test/gtest.h"
#include "test/scenario/scenario.h"
#include "test/scenario/scenario_config.h"
#include "test/scenario/video_stream.h"

namespace webrtc {
namespace test {
namespace {
void CreateAnalyzedStream(Scenario* s,
                          NetworkSimulationConfig network_config,
                          VideoQualityAnalyzer* analyzer,
                          CallStatsCollectors* collectors) {
  VideoStreamConfig config;
  config.encoder.codec = VideoStreamConfig::Encoder::Codec::kVideoCodecVP8;
  config.encoder.implementation =
      VideoStreamConfig::Encoder::Implementation::kSoftware;
  config.hooks.frame_pair_handlers = {
      analyzer->Handler(s->net()->time_controller()->GetClock())};
  auto* caller = s->CreateClient("caller", CallClientConfig());
  auto* callee = s->CreateClient("callee", CallClientConfig());
  auto route =
      s->CreateRoutes(caller, {s->CreateSimulationNode(network_config)}, callee,
                      {s->CreateSimulationNode(NetworkSimulationConfig())});
  VideoStreamPair* video = s->CreateVideoStream(route->forward(), config);
  auto* audio = s->CreateAudioStream(route->forward(), AudioStreamConfig());
  s->Every(TimeDelta::Seconds(1), [=] {
    collectors->call.AddStats(caller->GetStats(), s->Now());

    VideoSendStream::Stats send_stats;
    caller->SendTask([&]() { send_stats = video->send()->GetStats(); });
    collectors->video_send.AddStats(send_stats, s->Now());

    AudioReceiveStreamInterface::Stats receive_stats;
    caller->SendTask([&]() { receive_stats = audio->receive()->GetStats(); });
    collectors->audio_receive.AddStats(receive_stats, s->Now());

    // Querying the video stats from within the expected runtime environment
    // (i.e. the TQ that belongs to the CallClient, not the Scenario TQ that
    // we're currently on).
    VideoReceiveStreamInterface::Stats video_receive_stats;
    auto* video_stream = video->receive();
    callee->SendTask([&video_stream, &video_receive_stats]() {
      video_receive_stats = video_stream->GetStats();
    });
    collectors->video_receive.AddStats(video_receive_stats, s->Now());
  });
}
}  // namespace

TEST(ScenarioAnalyzerTest, PsnrIsHighWhenNetworkIsGood) {
  VideoQualityAnalyzer analyzer;
  CallStatsCollectors stats;
  {
    Scenario s;
    NetworkSimulationConfig good_network;
    good_network.bandwidth = DataRate::KilobitsPerSec(1000);
    CreateAnalyzedStream(&s, good_network, &analyzer, &stats);
    s.RunFor(TimeDelta::Seconds(3));
  }
  // This is a change detecting test, the targets are based on previous runs and
  // might change due to changes in configuration and encoder etc. The main
  // purpose is to show how the stats can be used. To avoid being overly
  // sensistive to change, the ranges are chosen to be quite large.
  EXPECT_NEAR(analyzer.stats().psnr_with_freeze.Mean(), 43, 10);
  EXPECT_NEAR(stats.call.stats().target_rate.Mean().kbps(), 700, 300);
  EXPECT_NEAR(stats.video_send.stats().media_bitrate.Mean().kbps(), 500, 200);
  EXPECT_NEAR(stats.video_receive.stats().resolution.Mean(), 180, 10);
  EXPECT_NEAR(stats.audio_receive.stats().jitter_buffer.Mean().ms(), 40, 20);
}

TEST(ScenarioAnalyzerTest, PsnrIsLowWhenNetworkIsBad) {
  VideoQualityAnalyzer analyzer;
  CallStatsCollectors stats;
  {
    Scenario s;
    NetworkSimulationConfig bad_network;
    bad_network.bandwidth = DataRate::KilobitsPerSec(100);
    bad_network.loss_rate = 0.02;
    CreateAnalyzedStream(&s, bad_network, &analyzer, &stats);
    s.RunFor(TimeDelta::Seconds(3));
  }
  // This is a change detecting test, the targets are based on previous runs and
  // might change due to changes in configuration and encoder etc.
  EXPECT_NEAR(analyzer.stats().psnr_with_freeze.Mean(), 20, 10);
  EXPECT_NEAR(stats.call.stats().target_rate.Mean().kbps(), 75, 50);
  EXPECT_NEAR(stats.video_send.stats().media_bitrate.Mean().kbps(), 70, 30);
  EXPECT_NEAR(stats.video_receive.stats().resolution.Mean(), 180, 10);
  EXPECT_NEAR(stats.audio_receive.stats().jitter_buffer.Mean().ms(), 250, 200);
}

TEST(ScenarioAnalyzerTest, CountsCapturedButNotRendered) {
  VideoQualityAnalyzer analyzer;
  CallStatsCollectors stats;
  {
    Scenario s;
    NetworkSimulationConfig long_delays;
    long_delays.delay = TimeDelta::Seconds(5);
    CreateAnalyzedStream(&s, long_delays, &analyzer, &stats);
    // Enough time to send frames but not enough to deliver.
    s.RunFor(TimeDelta::Millis(100));
  }
  EXPECT_GE(analyzer.stats().capture.count, 1);
  EXPECT_EQ(analyzer.stats().render.count, 0);
}
}  // namespace test
}  // namespace webrtc
