// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/uploader/upload_scheduler.h"

#include <gtest/gtest.h>

namespace cobalt::uploader {

TEST(UploadScheduler, NoBackoff) {
  UploadScheduler scheduler =
      UploadScheduler::Create(UploadScheduleConfig{std::chrono::hours(1), std::chrono::seconds(0),
                                                   std::chrono::hours(1), 0.0})
          .value();

  // Interval stays at 3600 seconds forever
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
}

TEST(UploadScheduler, QuickBackoff) {
  UploadScheduler scheduler =
      UploadScheduler::Create(UploadScheduleConfig{std::chrono::hours(1), std::chrono::seconds(0),
                                                   std::chrono::minutes(10), 0})
          .value();

  auto expected_seconds = {600, 1200, 2400, 3600};
  for (auto seconds : expected_seconds) {
    EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(seconds));
  }

  // Interval maxes out at 3600 seconds (1 hour)
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
}

TEST(UploadScheduler, LongBackoff) {
  UploadScheduler scheduler =
      UploadScheduler::Create(UploadScheduleConfig{std::chrono::hours(1), std::chrono::seconds(0),
                                                   std::chrono::seconds(3), 0})
          .value();

  // Backoff should double every call to Interval, until the interval is >= 1
  // hour.
  auto expected_seconds = {3, 6, 12, 24, 48, 96, 192, 384, 768, 1536, 3072, 3600};
  for (auto seconds : expected_seconds) {
    EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(seconds));
  }

  // Interval maxes out at 3600 seconds (1 hour)
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
  EXPECT_EQ(scheduler.Interval(), std::chrono::seconds(3600));
}

TEST(UploadScheduler, JitterBounds) {
  UploadScheduler scheduler =
      UploadScheduler::Create(UploadScheduleConfig{std::chrono::hours(1), std::chrono::seconds(0),
                                                   std::chrono::minutes(10), .1})
          .value();

  // Without jitter the expected intervals are {600, 1200, 2400, 3600}
  // Jitter will add or subtract a random value up to 10% of the current
  // interval.
  auto upper_bound = {660, 1320, 2640, 3960, 3960, 3960, 3960};
  auto lower_bound = {540, 1080, 2160, 3240, 3240, 3240, 3240};
  for (unsigned int i = 0; i < upper_bound.size(); i++) {
    std::chrono::seconds test_interval = scheduler.Interval();
    EXPECT_GE(test_interval, std::chrono::seconds(lower_bound.begin()[i]));
    EXPECT_LT(test_interval, std::chrono::seconds(upper_bound.begin()[i]));
  }
}

}  // namespace cobalt::uploader
