// Copyright (c) 2011 The Chromium 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 "base/file_version_info_win.h"

#include <windows.h>

#include <stddef.h>

#include <memory>

#include "base/file_version_info.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/scoped_native_library.h"
#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::FilePath;

namespace {

FilePath GetTestDataPath() {
  FilePath path;
  base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
  path = path.AppendASCII("base");
  path = path.AppendASCII("test");
  path = path.AppendASCII("data");
  path = path.AppendASCII("file_version_info_unittest");
  return path;
}

class FileVersionInfoFactory {
 public:
  explicit FileVersionInfoFactory(const FilePath& path) : path_(path) {}

  std::unique_ptr<FileVersionInfo> Create() const {
    return FileVersionInfo::CreateFileVersionInfo(path_);
  }

 private:
  const FilePath path_;

  DISALLOW_COPY_AND_ASSIGN(FileVersionInfoFactory);
};

class FileVersionInfoForModuleFactory {
 public:
  explicit FileVersionInfoForModuleFactory(const FilePath& path)
      // Load the library with LOAD_LIBRARY_AS_IMAGE_RESOURCE since it shouldn't
      // be executed.
      : library_(::LoadLibraryEx(path.value().c_str(),
                                 nullptr,
                                 LOAD_LIBRARY_AS_IMAGE_RESOURCE)) {
    EXPECT_TRUE(library_.is_valid());
  }

  std::unique_ptr<FileVersionInfo> Create() const {
    return FileVersionInfo::CreateFileVersionInfoForModule(library_.get());
  }

 private:
  const base::ScopedNativeLibrary library_;

  DISALLOW_COPY_AND_ASSIGN(FileVersionInfoForModuleFactory);
};

template <typename T>
class FileVersionInfoTest : public testing::Test {};

using FileVersionInfoFactories =
    ::testing::Types<FileVersionInfoFactory, FileVersionInfoForModuleFactory>;

}  // namespace

TYPED_TEST_SUITE(FileVersionInfoTest, FileVersionInfoFactories);

TYPED_TEST(FileVersionInfoTest, HardCodedProperties) {
  const base::FilePath::CharType kDLLName[] =
      FILE_PATH_LITERAL("FileVersionInfoTest1.dll");

  const wchar_t* const kExpectedValues[15] = {
      // FileVersionInfoTest.dll
      L"Goooooogle",                      // company_name
      L"Google",                          // company_short_name
      L"This is the product name",        // product_name
      L"This is the product short name",  // product_short_name
      L"The Internal Name",               // internal_name
      L"4.3.2.1",                         // product_version
      L"Special build property",          // special_build
      L"This is the original filename",   // original_filename
      L"This is my file description",     // file_description
      L"1.2.3.4",                         // file_version
  };

  FilePath dll_path = GetTestDataPath();
  dll_path = dll_path.Append(kDLLName);

  TypeParam factory(dll_path);
  std::unique_ptr<FileVersionInfo> version_info(factory.Create());
  ASSERT_TRUE(version_info);

  int j = 0;
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->company_name()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->company_short_name()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->product_name()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->product_short_name()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->internal_name()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->product_version()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->special_build()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->original_filename()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->file_description()));
  EXPECT_EQ(kExpectedValues[j++],
            base::AsWStringPiece(version_info->file_version()));
}

TYPED_TEST(FileVersionInfoTest, CustomProperties) {
  FilePath dll_path = GetTestDataPath();
  dll_path = dll_path.AppendASCII("FileVersionInfoTest1.dll");

  TypeParam factory(dll_path);
  std::unique_ptr<FileVersionInfo> version_info(factory.Create());
  ASSERT_TRUE(version_info);

  // Test few existing properties.
  base::string16 str;
  FileVersionInfoWin* version_info_win =
      static_cast<FileVersionInfoWin*>(version_info.get());
  EXPECT_TRUE(
      version_info_win->GetValue(STRING16_LITERAL("Custom prop 1"), &str));
  EXPECT_EQ(STRING16_LITERAL("Un"), str);
  EXPECT_EQ(STRING16_LITERAL("Un"), version_info_win->GetStringValue(
                                        STRING16_LITERAL("Custom prop 1")));

  EXPECT_TRUE(
      version_info_win->GetValue(STRING16_LITERAL("Custom prop 2"), &str));
  EXPECT_EQ(STRING16_LITERAL("Deux"), str);
  EXPECT_EQ(STRING16_LITERAL("Deux"), version_info_win->GetStringValue(
                                          STRING16_LITERAL("Custom prop 2")));

  EXPECT_TRUE(
      version_info_win->GetValue(STRING16_LITERAL("Custom prop 3"), &str));
  EXPECT_EQ(
      STRING16_LITERAL("1600 Amphitheatre Parkway Mountain View, CA 94043"),
      str);
  EXPECT_EQ(
      STRING16_LITERAL("1600 Amphitheatre Parkway Mountain View, CA 94043"),
      version_info_win->GetStringValue(STRING16_LITERAL("Custom prop 3")));

  // Test an non-existing property.
  EXPECT_FALSE(
      version_info_win->GetValue(STRING16_LITERAL("Unknown property"), &str));
  EXPECT_EQ(base::string16(), version_info_win->GetStringValue(
                                  STRING16_LITERAL("Unknown property")));

  EXPECT_EQ(base::Version(std::vector<uint32_t>{1, 0, 0, 1}),
            version_info_win->GetFileVersion());
}

TYPED_TEST(FileVersionInfoTest, NoVersionInfo) {
  FilePath dll_path = GetTestDataPath();
  dll_path = dll_path.AppendASCII("no_version_info.dll");

  TypeParam factory(dll_path);
  ASSERT_FALSE(factory.Create());
}
