// 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(base::as_wcstr(path.value()),
                                 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::char16 kDLLName[] = STRING16_LITERAL("FileVersionInfoTest1.dll");

  const base::char16* const kExpectedValues[15] = {
      // FileVersionInfoTest.dll
      STRING16_LITERAL("Goooooogle"),                      // company_name
      STRING16_LITERAL("Google"),                          // company_short_name
      STRING16_LITERAL("This is the product name"),        // product_name
      STRING16_LITERAL("This is the product short name"),  // product_short_name
      STRING16_LITERAL("The Internal Name"),               // internal_name
      STRING16_LITERAL("4.3.2.1"),                         // product_version
      STRING16_LITERAL("Special build property"),          // special_build
      STRING16_LITERAL("This is the original filename"),  // original_filename
      STRING16_LITERAL("This is my file description"),    // file_description
      STRING16_LITERAL("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++], version_info->company_name());
  EXPECT_EQ(kExpectedValues[j++], version_info->company_short_name());
  EXPECT_EQ(kExpectedValues[j++], version_info->product_name());
  EXPECT_EQ(kExpectedValues[j++], version_info->product_short_name());
  EXPECT_EQ(kExpectedValues[j++], version_info->internal_name());
  EXPECT_EQ(kExpectedValues[j++], version_info->product_version());
  EXPECT_EQ(kExpectedValues[j++], version_info->special_build());
  EXPECT_EQ(kExpectedValues[j++], version_info->original_filename());
  EXPECT_EQ(kExpectedValues[j++], version_info->file_description());
  EXPECT_EQ(kExpectedValues[j++], 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());
}
