// Copyright (c) 2013 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 "gpu/gles2_conform_support/gles2_conform_test.h"

#include <stddef.h>
#include <stdint.h>

#include <string>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#endif
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/string_util.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
#include "gpu/config/gpu_test_config.h"
#include "gpu/config/gpu_test_expectations_parser.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

int RunHelper(base::TestSuite* test_suite) {
  return test_suite->Run();
}

}  // namespace

bool RunGLES2ConformTest(const char* path) {
  // Load test expectations, and return early if a test is marked as FAIL.
  base::FilePath src_path;
  base::PathService::Get(base::DIR_SOURCE_ROOT, &src_path);
  base::FilePath test_expectations_path =
      src_path.Append(FILE_PATH_LITERAL("gpu")).
      Append(FILE_PATH_LITERAL("gles2_conform_support")).
      Append(FILE_PATH_LITERAL("gles2_conform_test_expectations.txt"));
  if (!base::PathExists(test_expectations_path)) {
    LOG(ERROR) << "Fail to locate gles2_conform_test_expectations.txt";
    return false;
  }
  gpu::GPUTestExpectationsParser test_expectations;
  if (!test_expectations.LoadTestExpectations(test_expectations_path)) {
    LOG(ERROR) << "Fail to load gles2_conform_test_expectations.txt";
    return false;
  }
  gpu::GPUTestBotConfig bot_config;
  if (!bot_config.LoadCurrentConfig(nullptr)) {
    LOG(ERROR) << "Fail to load bot configuration";
    return false;
  }

  // Set the bot config api based on the OS and command line
  base::CommandLine* current_cmd_line = base::CommandLine::ForCurrentProcess();
  int32_t config_os = bot_config.os();
  if ((config_os & gpu::GPUTestConfig::kOsWin) != 0) {
    std::string angle_renderer =
        current_cmd_line->HasSwitch("use-angle")
            ? current_cmd_line->GetSwitchValueASCII("use-angle")
            : "d3d11";
    if (angle_renderer == "d3d11") {
      bot_config.set_api(gpu::GPUTestConfig::kAPID3D11);
    } else if (angle_renderer == "d3d9") {
      bot_config.set_api(gpu::GPUTestConfig::kAPID3D9);
    } else if (angle_renderer == "gl") {
      bot_config.set_api(gpu::GPUTestConfig::kAPIGLDesktop);
    } else if (angle_renderer == "gles") {
      bot_config.set_api(gpu::GPUTestConfig::kAPIGLES);
    } else {
      bot_config.set_api(gpu::GPUTestConfig::kAPIUnknown);
    }
  } else if ((config_os & gpu::GPUTestConfig::kOsMac) != 0 ||
             config_os == gpu::GPUTestConfig::kOsLinux) {
    bot_config.set_api(gpu::GPUTestConfig::kAPIGLDesktop);
  } else if (config_os == gpu::GPUTestConfig::kOsChromeOS ||
             config_os == gpu::GPUTestConfig::kOsAndroid) {
    bot_config.set_api(gpu::GPUTestConfig::kAPIGLES);
  } else {
    bot_config.set_api(gpu::GPUTestConfig::kAPIUnknown);
  }

  if (!bot_config.IsValid()) {
    LOG(ERROR) << "Invalid bot configuration";
    return false;
  }
  std::string path_string(path);
  std::string test_name;
  base::ReplaceChars(path_string, "\\/.", "_", &test_name);
  int32_t expectation =
      test_expectations.GetTestExpectation(test_name, bot_config);
  if (expectation != gpu::GPUTestExpectationsParser::kGpuTestPass) {
    LOG(WARNING) << "Test " << test_name << " is bypassed";
    return true;
  }

  base::FilePath test_path;
  base::PathService::Get(base::DIR_EXE, &test_path);
  base::FilePath program(test_path.Append(FILE_PATH_LITERAL(
      "gles2_conform_test_windowless")));

  base::CommandLine cmd_line(program);
  cmd_line.AppendArguments(*current_cmd_line, false);
  cmd_line.AppendSwitch(std::string("--"));
  cmd_line.AppendArg(std::string("-run=") + path);

  std::string output;
  bool success = base::GetAppOutputAndError(cmd_line, &output);
  if (success) {
    size_t success_index = output.find("Conformance PASSED all");
    size_t failed_index = output.find("FAILED");
    success = (success_index != std::string::npos) &&
              (failed_index == std::string::npos);
  }
  if (!success) {
    LOG(ERROR) << output;
  }
  return success;
}

int main(int argc, char** argv) {
  base::CommandLine::Init(argc, argv);
#if defined(OS_MACOSX)
  base::mac::ScopedNSAutoreleasePool pool;
#endif
  ::testing::InitGoogleTest(&argc, argv);
  base::TestSuite test_suite(argc, argv);
  int rt = base::LaunchUnitTestsSerially(
      argc, argv, base::BindOnce(&RunHelper, base::Unretained(&test_suite)));
  return rt;
}
