// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "components/update_client/cobalt_slot_management.h"

#include "base/strings/string_util.h"
#include "starboard/common/file.h"
#include "starboard/loader_app/app_key_files.h"
#include "starboard/loader_app/drain_file.h"
#include "starboard/loader_app/installation_manager.h"
#include "starboard/loader_app/system_get_extension_shim.h"
#include "testing/gtest/include/gtest/gtest.h"

#if SB_API_VERSION >= 12
namespace update_client {
namespace {

constexpr char kTestAppKey1[] = "test_key1";
constexpr char kTestAppKey2[] = "test_key2";
constexpr char kManifestV1[] = R"json({
  "manifest_version": 2,
  "name": "Cobalt",
  "description": "Cobalt",
  "version": "1.1.0"
})json";

constexpr char kManifestV2[] = R"json(
{
  "manifest_version": 2,
  "name": "Cobalt",
  "description": "Cobalt",
  "version": "1.2.0"
})json";

class CobaltSlotManagementTest : public testing::Test {
 protected:
  virtual void SetUp() override {
    std::vector<char> buf(kSbFileMaxPath);
    storage_path_implemented_ = SbSystemGetPath(kSbSystemPathStorageDirectory,
                                                buf.data(), kSbFileMaxPath);
    if (!storage_path_implemented_) {
      return;
    }

    storage_path_ = buf.data();
    ASSERT_TRUE(!storage_path_.empty());

    starboard::SbFileDeleteRecursive(storage_path_.c_str(), true);
    ImInitialize(3, kTestAppKey1);
    api_ = static_cast<const CobaltExtensionInstallationManagerApi*>(
        starboard::loader_app::SbSystemGetExtensionShim(
            kCobaltExtensionInstallationManagerName));
  }

  virtual void TearDown() override {
    starboard::SbFileDeleteRecursive(storage_path_.c_str(), true);
    ImUninitialize();
  }

  void CreateManifest(const char* slot_path,
                      const char* data,
                      size_t data_length) {
    std::string manifest1_path = storage_path_;
    manifest1_path += kSbFileSepString;
    manifest1_path += slot_path;
    manifest1_path += kSbFileSepString;
    manifest1_path += "manifest.json";

    ASSERT_TRUE(SbFileAtomicReplace(manifest1_path.c_str(), data, data_length));
  }

  const CobaltExtensionInstallationManagerApi* api_;
  bool storage_path_implemented_;
  std::string storage_path_;
};

TEST_F(CobaltSlotManagementTest, Init) {
  if (!storage_path_implemented_) {
    return;
  }
  CobaltSlotManagement cobalt_slot_management;
  ASSERT_TRUE(cobalt_slot_management.Init(api_));
}

TEST_F(CobaltSlotManagementTest, NegativeInit) {
  if (!storage_path_implemented_) {
    return;
  }
  CobaltSlotManagement cobalt_slot_management;
  ASSERT_FALSE(cobalt_slot_management.Init(nullptr));
}

TEST_F(CobaltSlotManagementTest, SelectEmptySlot) {
  if (!storage_path_implemented_) {
    return;
  }
  CobaltSlotManagement cobalt_slot_management;
  ASSERT_TRUE(cobalt_slot_management.Init(api_));
  base::FilePath dir;
  ASSERT_TRUE(cobalt_slot_management.SelectSlot(&dir));
  ASSERT_TRUE(DrainFileDraining(dir.value().c_str(), kTestAppKey1));
  ASSERT_TRUE(base::EndsWith(dir.value(), "installation_1",
                             base::CompareCase::SENSITIVE));
}

TEST_F(CobaltSlotManagementTest, SelectSlotBailOnDraining) {
  if (!storage_path_implemented_) {
    return;
  }

  CobaltSlotManagement cobalt_slot_management;
  std::string slot_path = storage_path_;
  slot_path += kSbFileSepString;
  slot_path += "installation_1";

  // If there is is non-expired drain file from
  // different app the current app should bail out.
  ASSERT_TRUE(DrainFileTryDrain(slot_path.c_str(), kTestAppKey2));
  ASSERT_TRUE(cobalt_slot_management.Init(api_));

  base::FilePath dir;
  ASSERT_FALSE(cobalt_slot_management.SelectSlot(&dir));
}

TEST_F(CobaltSlotManagementTest, SelectMinVersionSlot) {
  if (!storage_path_implemented_) {
    return;
  }

  // In slot 2 create manifest v1.
  CreateManifest("installation_2", kManifestV1, SbStringGetLength(kManifestV1));

  // In slot 1 create manifest v2.
  CreateManifest("installation_1", kManifestV2, SbStringGetLength(kManifestV2));

  CobaltSlotManagement cobalt_slot_management;
  ASSERT_TRUE(cobalt_slot_management.Init(api_));
  base::FilePath dir;
  cobalt_slot_management.SelectSlot(&dir);
  ASSERT_TRUE(DrainFileDraining(dir.value().c_str(), kTestAppKey1));
  SB_LOG(INFO) << "dir=" << dir;

  ASSERT_TRUE(base::EndsWith(dir.value(), "installation_2",
                             base::CompareCase::SENSITIVE));
}

TEST_F(CobaltSlotManagementTest, ConfirmSlot) {
  if (!storage_path_implemented_) {
    return;
  }

  ImRollForward(1);
  ImDecrementInstallationNumTries(1);
  ASSERT_LE(ImGetInstallationNumTriesLeft(1), IM_MAX_NUM_TRIES);
  ImMarkInstallationSuccessful(1);
  ASSERT_EQ(IM_INSTALLATION_STATUS_SUCCESS, ImGetInstallationStatus(1));
  CobaltSlotManagement cobalt_slot_management;
  ASSERT_TRUE(cobalt_slot_management.Init(api_));
  base::FilePath dir;
  ASSERT_TRUE(cobalt_slot_management.SelectSlot(&dir));
  SB_LOG(INFO) << "dir=" << dir;

  ASSERT_TRUE(base::EndsWith(dir.value(), "installation_1",
                             base::CompareCase::SENSITIVE));

  ASSERT_TRUE(DrainFileDraining(dir.value().c_str(), kTestAppKey1));

  ASSERT_TRUE(cobalt_slot_management.ConfirmSlot(dir));

  ASSERT_EQ(IM_INSTALLATION_STATUS_NOT_SUCCESS, ImGetInstallationStatus(1));
  ASSERT_EQ(IM_MAX_NUM_TRIES, ImGetInstallationNumTriesLeft(1));
}

TEST_F(CobaltSlotManagementTest, CobaltFinishInstallation) {
  std::string slot_path = storage_path_;
  slot_path += kSbFileSepString;
  slot_path += "installation_1";
  std::string good_file_path =
      starboard::loader_app::GetGoodAppKeyFilePath(slot_path, kTestAppKey1);

  ImRollForward(2);

  // Cleanup pending requests for roll forward.
  ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());

  ASSERT_EQ(2, ImGetCurrentInstallationIndex());
  ASSERT_FALSE(SbFileExists(good_file_path.c_str()));
  ASSERT_TRUE(CobaltFinishInstallation(api_, 1, slot_path, kTestAppKey1));
  ASSERT_TRUE(SbFileExists(good_file_path.c_str()));
  ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());
  ASSERT_EQ(1, ImGetCurrentInstallationIndex());
}

TEST_F(CobaltSlotManagementTest, GoodCobaltQuickUpdate) {
  // In slot 1 create manifest v1.
  CreateManifest("installation_1", kManifestV1, SbStringGetLength(kManifestV1));

  // In slot 2 create manifest v2.
  CreateManifest("installation_2", kManifestV2, SbStringGetLength(kManifestV2));

  // Mark slot 2 good for app 2.
  std::string slot_path = storage_path_;
  slot_path += kSbFileSepString;
  slot_path += "installation_2";
  std::string good_file_path =
      starboard::loader_app::GetGoodAppKeyFilePath(slot_path, kTestAppKey2);
  starboard::loader_app::CreateAppKeyFile(good_file_path);
  base::Version version("1.1.0");
  ASSERT_TRUE(CobaltQuickUpdate(api_, version));
}

TEST_F(CobaltSlotManagementTest, NegativeCobaltQuickUpdateBadVersion) {
  base::Version version;
  ASSERT_FALSE(CobaltQuickUpdate(api_, version));
}

TEST_F(CobaltSlotManagementTest, NegativeCobaltQuickUpdate) {
  base::Version version("1.0.0");
  ASSERT_FALSE(CobaltQuickUpdate(api_, version));
}
}  // namespace

}  // namespace update_client
#endif  // SB_API_VERSION >= 12
