Răsfoiți Sursa

[linux-port] gtest interface for HLSL tests (#1413)

On Windows, HLSL tests run using TAEF. Since that's not available
on other platforms, this change adapts the tests to work on gtest
framework with minimal alterations to the tests themselves.

TestMain.cpp is pilfered and enhanced from Spirv tests. It provides
a starting point for the gtest binary to initialize variables and
launch tests, though gtest hides most of that.

Derived from SpirvTestOptions, this lists a number of potential
options from the command line and provides a crude, but effective
mechanism to access the as needed.

With this commit, you can run clang-hlsl-tests, but it does't really
do anything. Tests will follow shortly.
Greg Roth 7 ani în urmă
părinte
comite
41e6028c9e

+ 1 - 1
tools/clang/unittests/CMakeLists.txt

@@ -36,8 +36,8 @@ endif (CLANG_INCLUDE_TESTS) # HLSL Change
 # HLSL Change Starts
 
 if (HLSL_INCLUDE_TESTS) 
+  add_subdirectory(HLSL)
   if (WIN32) # These tests require MS specific TAEF and DIA SDK
-    add_subdirectory(HLSL)
     add_subdirectory(HLSLHost)
     add_subdirectory(dxc_batch)
   endif (WIN32)

+ 53 - 0
tools/clang/unittests/HLSL/CMakeLists.txt

@@ -1,8 +1,10 @@
 # Copyright (C) Microsoft Corporation. All rights reserved.
 # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details.
+if(WIN32)
 find_package(TAEF REQUIRED)
 find_package(DiaSDK REQUIRED) # Used for constants and declarations.
 find_package(D3D12 REQUIRED) # Used for ExecutionTest.cpp.
+ENDif(WIN32)
 
 set( LLVM_LINK_COMPONENTS
   support
@@ -17,6 +19,11 @@ set( LLVM_LINK_COMPONENTS
   irreader
   )
 
+if(WIN32)
+set(HLSL_IGNORE_SOURCES
+  TestMain.cpp
+  HLSLTestOptions.cpp
+)
 add_clang_library(clang-hlsl-tests SHARED
   AllocatorTest.cpp
   CompilationResult.h
@@ -43,29 +50,75 @@ add_clang_library(clang-hlsl-tests SHARED
   VerifierTest.cpp
   clang-hlsl-tests.rc
   )
+else (WIN32)
+set(HLSL_IGNORE_SOURCES
+  AllocatorTest.cpp
+  CompilerTest.cpp
+  DxilContainerTest.cpp
+  DxilModuleTest.cpp
+  DXIsenseTest.cpp
+  ExecutionTest.cpp
+  ExtensionTest.cpp
+  FileCheckerTest.cpp
+  FileCheckForTest.cpp
+  FunctionTest.cpp
+  LinkerTest.cpp
+  MSFileSysTest.cpp
+  Objects.cpp
+  OptimizerTest.cpp
+  OptionsTest.cpp
+  RewriterTest.cpp
+  ShaderOpTest.cpp
+  SystemValueTest.cpp
+  ValidationTest.cpp
+  VerifierTest.cpp
+  )
+
+add_clang_unittest(clang-hlsl-tests
+  TestMain.cpp
+  HLSLTestOptions.cpp
+  )
+
+endif(WIN32)
+
 set_target_properties(clang-hlsl-tests PROPERTIES FOLDER "Clang tests")
 
+if (WIN32)
 target_link_libraries(clang-hlsl-tests PRIVATE
   dxcompiler
   ${TAEF_LIBRARIES}
   ${DIASDK_LIBRARIES}
   ${D3D12_LIBRARIES}
   )
+else(WIN32)
+target_link_libraries(clang-hlsl-tests
+  dxcompiler
+  )
+endif(WIN32)
 
+if(WIN32)
 # Add includes for platform helpers and dxc API.
 include_directories(${TAEF_INCLUDE_DIRS})
 include_directories(${DIASDK_INCLUDE_DIRS})
 include_directories(${D3D12_INCLUDE_DIRS})
+endif(WIN32)
 
 # Add includes to directly reference intrinsic tables.
 include_directories(../../lib/Sema)
 
 add_dependencies(clang-hlsl-tests dxcompiler)
 
+if(WIN32)
 install(TARGETS clang-hlsl-tests
   RUNTIME DESTINATION bin)
+else(WIN32)
+set_output_directory(clang-hlsl-tests
+  ${LLVM_RUNTIME_OUTPUT_INTDIR} ${LLVM_LIBRARY_OUTPUT_INTDIR})
+endif(WIN32)
 
+if(WIN32)
 # Add a .user file with settings for te.exe.
 file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" DOS_STYLE_SOURCE_DIR)
 file(TO_NATIVE_PATH "${TAEF_BIN_DIR}" DOS_TAEF_BIN_DIR)
 configure_file(clang-hlsl-tests.vcxproj.user.txt clang-hlsl-tests.vcxproj.user)
+endif(WIN32)

+ 46 - 0
tools/clang/unittests/HLSL/HLSLTestOptions.cpp

@@ -0,0 +1,46 @@
+//===- unittests/HLSL/HLSLTestOptions.cpp ----- Test Options Init -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines and initializes command line options that can be passed to
+// HLSL gtests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "HLSLTestOptions.h"
+#include "dxc/Support/WinAdapter.h"
+
+namespace clang {
+namespace hlsl {
+namespace testOptions {
+
+#define ARG_DEFINE(argname) std::string argname = "";
+ARG_LIST(ARG_DEFINE)
+
+} // namespace testOptions
+} // namespace hlsl
+} // namespace clang
+
+namespace WEX {
+namespace TestExecution {
+namespace RuntimeParameters {
+HRESULT TryGetValue(const wchar_t *param, std::wstring &retStr) {
+#define RETURN_ARG(argname)                                                    \
+  if (wcscmp(param, L## #argname) == 0) {                                      \
+    if (!clang::hlsl::testOptions::argname.empty()) {                          \
+      retStr.assign(CA2W(clang::hlsl::testOptions::argname.c_str()).m_psz);    \
+      return S_OK;                                                             \
+    } else                                                                     \
+      return E_FAIL;                                                           \
+  }
+  ARG_LIST(RETURN_ARG)
+  return E_NOTIMPL;
+}
+} // namespace RuntimeParameters
+} // namespace TestExecution
+} // namespace WEX

+ 48 - 0
tools/clang/unittests/HLSL/HLSLTestOptions.h

@@ -0,0 +1,48 @@
+//===- unittests/HLSL/HLSLTestOptions.h ----- Command Line Options ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the command line options that can be passed to HLSL
+// gtests. This file should be included in any test file that intends to use any
+// options.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_HLSL_TEST_OPTIONS_H
+#define LLVM_CLANG_UNITTESTS_HLSL_TEST_OPTIONS_H
+
+#include <string>
+
+namespace clang {
+namespace hlsl {
+
+/// \brief Includes any command line options that may be passed to gtest for
+/// running the SPIR-V tests. New options should be added in this namespace.
+namespace testOptions {
+
+/// \brief Command line option that specifies the path to the directory that
+/// contains files that have the HLSL source code (used for the CodeGen test flow).
+#define ARG_DECLARE(argname) extern std::string argname;
+
+#define ARG_LIST(ARGOP)\
+    ARGOP(HlslDataDir)\
+    ARGOP(TestName)\
+    ARGOP(DXBC)\
+    ARGOP(SaveImages)\
+    ARGOP(ExperimentalShaders)\
+    ARGOP(DebugLayer)\
+    ARGOP(SuitePath)\
+    ARGOP(InputFile)
+
+ARG_LIST(ARG_DECLARE)
+
+} // namespace testOptions
+} // namespace hlsl
+} // namespace clang
+
+#endif

+ 144 - 0
tools/clang/unittests/HLSL/TestMain.cpp

@@ -0,0 +1,144 @@
+//===--- utils/unittest/HLSL/TestMain.cpp - unittest driver --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "llvm/Support/Signals.h"
+
+#include "HLSLTestOptions.h"
+
+#if defined(_WIN32)
+#include <windows.h>
+#if defined(_MSC_VER)
+#include <crtdbg.h>
+#endif
+#endif
+
+namespace {
+using namespace ::testing;
+
+/// A GoogleTest event printer that only prints test failures.
+class FailurePrinter : public TestEventListener {
+public:
+  explicit FailurePrinter(TestEventListener *listener)
+      : defaultListener(listener) {}
+
+  ~FailurePrinter() override { delete defaultListener; }
+
+  void OnTestProgramStart(const UnitTest &ut) override {
+    defaultListener->OnTestProgramStart(ut);
+  }
+
+  void OnTestIterationStart(const UnitTest &ut, int iteration) override {
+    defaultListener->OnTestIterationStart(ut, iteration);
+  }
+
+  void OnEnvironmentsSetUpStart(const UnitTest &ut) override {
+    defaultListener->OnEnvironmentsSetUpStart(ut);
+  }
+
+  void OnEnvironmentsSetUpEnd(const UnitTest &ut) override {
+    defaultListener->OnEnvironmentsSetUpEnd(ut);
+  }
+
+  void OnTestCaseStart(const TestCase &tc) override {
+    defaultListener->OnTestCaseStart(tc);
+  }
+
+  void OnTestStart(const TestInfo &ti) override {
+    // Do not output on test start
+    // defaultListener->OnTestStart(ti);
+  }
+
+  void OnTestPartResult(const TestPartResult &result) override {
+    defaultListener->OnTestPartResult(result);
+  }
+
+  void OnTestEnd(const TestInfo &ti) override {
+    // Only output if failure on test end
+    if (ti.result()->Failed())
+      defaultListener->OnTestEnd(ti);
+  }
+
+  void OnTestCaseEnd(const TestCase &tc) override {
+    defaultListener->OnTestCaseEnd(tc);
+  }
+
+  void OnEnvironmentsTearDownStart(const UnitTest &ut) override {
+    defaultListener->OnEnvironmentsTearDownStart(ut);
+  }
+
+  void OnEnvironmentsTearDownEnd(const UnitTest &ut) override {
+    defaultListener->OnEnvironmentsTearDownEnd(ut);
+  }
+
+  void OnTestIterationEnd(const UnitTest &ut, int iteration) override {
+    defaultListener->OnTestIterationEnd(ut, iteration);
+  }
+
+  void OnTestProgramEnd(const UnitTest &ut) override {
+    defaultListener->OnTestProgramEnd(ut);
+  }
+
+private:
+  TestEventListener *defaultListener;
+};
+} // namespace
+
+const char *TestMainArgv0;
+
+#define SAVE_ARG(argname)                                                      \
+  if (std::string("--" #argname) == argv[i]) {                                 \
+    if (i + 1 < argc) {                                                        \
+      clang::hlsl::testOptions::argname = argv[++i];                           \
+    } else {                                                                   \
+      fprintf(stderr, "Error: --" #argname " requires an argument\n");         \
+      return 1;                                                                \
+    }                                                                          \
+  }
+
+int main(int argc, char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(true /* Disable crash reporting */);
+
+  for (int i = 1; i < argc; ++i) {
+    ARG_LIST(SAVE_ARG)
+  }
+
+  // Initialize both gmock and gtest.
+  testing::InitGoogleMock(&argc, argv);
+
+  // Switch event listener to one that only prints failures.
+  testing::TestEventListeners &listeners =
+      ::testing::UnitTest::GetInstance()->listeners();
+  auto *defaultPrinter = listeners.Release(listeners.default_result_printer());
+  // Google Test takes the ownership.
+  listeners.Append(new FailurePrinter(defaultPrinter));
+
+  // Make it easy for a test to re-execute itself by saving argv[0].
+  TestMainArgv0 = argv[0];
+
+#if defined(_WIN32)
+  // Disable all of the possible ways Windows conspires to make automated
+  // testing impossible.
+  ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+#if defined(_MSC_VER)
+  ::_set_error_mode(_OUT_TO_STDERR);
+  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+#endif
+#endif
+
+  int rv = RUN_ALL_TESTS();
+  return rv;
+}