// 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/sys/appmgr/util.h"

#include <gtest/gtest.h>

namespace component {
namespace {

TEST(UtilTests, GetLabelFromURL) {
  std::string values[][2] = {{"", ""},        {"foo/bar", "bar"},  {"foo/bar/", "foo/bar/"},
                             {"/foo", "foo"}, {"/foo/bar", "bar"}, {"foo", "foo"},
                             {"foo/", "foo/"}};
  for (auto value : values) {
    auto& url = value[0];
    auto& expected = value[1];
    EXPECT_EQ(Util::GetLabelFromURL(url), expected) << "for url: " << url;
  }
}

TEST(UtilTests, GetArgsString) {
  ::fidl::VectorPtr<::std::string> null_vec;
  EXPECT_EQ(Util::GetArgsString(null_vec), "");

  ::fidl::VectorPtr<::std::string> empty_vec(3);
  EXPECT_EQ(Util::GetArgsString(empty_vec), "  ");

  std::vector<::std::string> vec;
  vec.push_back("foo");
  EXPECT_EQ(Util::GetArgsString(vec), "foo");
  vec.push_back("bar");
  EXPECT_EQ(Util::GetArgsString(vec), "foo bar");
  vec.push_back("blah");
  EXPECT_EQ(Util::GetArgsString(vec), "foo bar blah");
}

TEST(UtilTests, BindDirectory) {
  zx::channel dir, dir_req;
  ASSERT_EQ(zx::channel::create(0, &dir, &dir_req), ZX_OK);
  fuchsia::sys::LaunchInfo launchInfo;
  launchInfo.directory_request = std::move(dir_req);
  auto channels = Util::BindDirectory(&launchInfo);
  ASSERT_TRUE(channels.exported_dir.is_valid());
  ASSERT_TRUE(channels.client_request.is_valid());

  const char* msg1 = "message1";
  dir.write(0, msg1, strlen(msg1) + 1, nullptr, 0);

  const char* msg2 = "message2";
  channels.exported_dir.write(0, msg2, strlen(msg2) + 1, nullptr, 0);

  char got1[strlen(msg1) + 1];
  char got2[strlen(msg2) + 1];

  channels.client_request.read(0, got1, nullptr, sizeof(got1), 0, nullptr, nullptr);
  launchInfo.directory_request.read(0, got2, nullptr, sizeof(got2), 0, nullptr, nullptr);

  EXPECT_STREQ(got1, msg1);
  EXPECT_STREQ(got2, msg2);
}

class RestartBackOffTester : public RestartBackOff {
 public:
  RestartBackOffTester(zx::duration min_backoff, zx::duration max_backoff,
                       zx::duration alive_reset_limit)
      : RestartBackOff(min_backoff, max_backoff, alive_reset_limit) {}
  void SetCurrentTime(zx::time time) { current_time_ = time; }

 protected:
  zx::time GetCurrentTime() const override { return current_time_; }

 private:
  zx::time current_time_;
};

TEST(RestartBackOffTest, WaitIncreasesAndResets) {
  auto start_time = zx::time() + zx::hour(10);
  auto within_limit = start_time + zx::msec(100);
  auto after_limit = start_time + zx::msec(1100);
  RestartBackOffTester util(zx::sec(1), zx::sec(10), zx::sec(1));
  util.SetCurrentTime(start_time);
  util.Start();
  util.SetCurrentTime(within_limit);
  EXPECT_GE(util.GetNext(), zx::sec(1));
  for (int i = 0; i < 10; i++) {
    util.GetNext();
  }
  // Ensure we don't go over the limit.
  EXPECT_EQ(util.GetNext(), zx::sec(10));

  // If the task succeeded for long enough, ensure backoff is reset.
  util.SetCurrentTime(after_limit);
  EXPECT_LT(util.GetNext(), zx::sec(10));
}

}  // namespace
}  // namespace component
