# Copyright (c) 2015-2016 The Khronos Group Inc.
#
# 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.

if (${SPIRV_SKIP_TESTS})
  return()
endif()

if (TARGET gmock_main)
  message(STATUS "Found Google Mock, building tests.")
else()
  message(STATUS "Did not find googletest, tests will not be built. "
    "To enable tests place googletest in '<spirv-dir>/external/googletest'.")
endif()

# Add a SPIR-V Tools unit test. Signature:
#   add_spvtools_unittest(
#     TARGET target_name
#     SRCS   src_file.h src_file.cpp
#     LIBS   lib1 lib2
#   )
function(add_spvtools_unittest)
  if (NOT "${SPIRV_SKIP_TESTS}" AND TARGET gmock_main)
    set(one_value_args TARGET PCH_FILE)
    set(multi_value_args SRCS LIBS ENVIRONMENT DEFINES)
    cmake_parse_arguments(
      ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
    set(target test_${ARG_TARGET})
    set(SRC_COPY ${ARG_SRCS})
    if (DEFINED ARG_PCH_FILE)
      spvtools_pch(SRC_COPY ${ARG_PCH_FILE})
    endif()
    add_executable(${target} ${SRC_COPY})
    target_compile_definitions(${target} PUBLIC ${ARG_DEFINES})
    spvtools_default_compile_options(${target})
    if(${COMPILER_IS_LIKE_GNU})
      target_compile_options(${target} PRIVATE -Wno-undef)
      # Effcee and RE2 headers exhibit shadowing.
      target_compile_options(${target} PRIVATE -Wno-shadow)
    endif()
    if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
      # Disable C4503 "decorated name length exceeded" warning,
      # triggered by some heavily templated types.
      # We don't care much about that in test code.
      # Important to do since we have warnings-as-errors.
      target_compile_options(${target} PRIVATE /wd4503)
      # Googletest accidentally turns off support for ::testing::Combine
      # in VS 2017.  See https://github.com/google/googletest/issues/1352
      # Forcibly turn it on again.
      target_compile_options(${target} PRIVATE /DGTEST_HAS_COMBINE=1)
    endif()
    target_include_directories(${target} PRIVATE
      ${SPIRV_HEADER_INCLUDE_DIR}
      ${spirv-tools_SOURCE_DIR}
      ${spirv-tools_SOURCE_DIR}/include
      ${spirv-tools_SOURCE_DIR}/test
      ${spirv-tools_BINARY_DIR}
      ${gtest_SOURCE_DIR}/include
      ${gmock_SOURCE_DIR}/include
    )
    if (TARGET effcee)
      # If using Effcee for testing, then add its include directory.
      target_include_directories(${target} PRIVATE ${effcee_SOURCE_DIR})
    endif()
    target_link_libraries(${target} PRIVATE ${ARG_LIBS})
    if (TARGET effcee)
      target_link_libraries(${target} PRIVATE effcee)
    endif()
    target_link_libraries(${target} PRIVATE gmock_main)
    add_test(NAME spirv-tools-${target} COMMAND ${target})
    if (DEFINED ARG_ENVIRONMENT)
      set_tests_properties(spirv-tools-${target} PROPERTIES ENVIRONMENT ${ARG_ENVIRONMENT})
    endif()
    set_property(TARGET ${target} PROPERTY FOLDER "SPIRV-Tools tests")
  endif()
endfunction()

set(TEST_SOURCES
  test_fixture.h
  unit_spirv.h

  assembly_context_test.cpp
  assembly_format_test.cpp
  binary_destroy_test.cpp
  binary_endianness_test.cpp
  binary_header_get_test.cpp
  binary_parse_test.cpp
  binary_strnlen_s_test.cpp
  binary_to_text_test.cpp
  binary_to_text.literal_test.cpp
  comment_test.cpp
  diagnostic_test.cpp
  enum_string_mapping_test.cpp
  enum_set_test.cpp
  ext_inst.cldebug100_test.cpp
  ext_inst.debuginfo_test.cpp
  ext_inst.glsl_test.cpp
  ext_inst.non_semantic_test.cpp
  ext_inst.opencl_test.cpp
  fix_word_test.cpp
  generator_magic_number_test.cpp
  hex_float_test.cpp
  immediate_int_test.cpp
  libspirv_macros_test.cpp
  named_id_test.cpp
  name_mapper_test.cpp
  opcode_make_test.cpp
  opcode_require_capabilities_test.cpp
  opcode_split_test.cpp
  opcode_table_get_test.cpp
  operand_capabilities_test.cpp
  operand_test.cpp
  operand_pattern_test.cpp
  parse_number_test.cpp
  preserve_numeric_ids_test.cpp
  software_version_test.cpp
  string_utils_test.cpp
  target_env_test.cpp
  text_advance_test.cpp
  text_destroy_test.cpp
  text_literal_test.cpp
  text_start_new_inst_test.cpp
  text_to_binary.annotation_test.cpp
  text_to_binary.barrier_test.cpp
  text_to_binary.composite_test.cpp
  text_to_binary.constant_test.cpp
  text_to_binary.control_flow_test.cpp
  text_to_binary_test.cpp
  text_to_binary.debug_test.cpp
  text_to_binary.device_side_enqueue_test.cpp
  text_to_binary.extension_test.cpp
  text_to_binary.function_test.cpp
  text_to_binary.group_test.cpp
  text_to_binary.image_test.cpp
  text_to_binary.literal_test.cpp
  text_to_binary.memory_test.cpp
  text_to_binary.misc_test.cpp
  text_to_binary.mode_setting_test.cpp
  text_to_binary.pipe_storage_test.cpp
  text_to_binary.type_declaration_test.cpp
  text_to_binary.subgroup_dispatch_test.cpp
  text_to_binary.reserved_sampling_test.cpp
  text_word_get_test.cpp

  unit_spirv.cpp
)

spvtools_pch(TEST_SOURCES pch_test)

add_spvtools_unittest(
  TARGET spirv_unit_tests
  SRCS ${TEST_SOURCES}
  LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})

add_spvtools_unittest(
  TARGET c_interface
  SRCS c_interface_test.cpp
  LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})

add_spvtools_unittest(
  TARGET c_interface_shared
  SRCS c_interface_test.cpp
  LIBS ${SPIRV_TOOLS}-shared
  ENVIRONMENT PATH=$<TARGET_FILE_DIR:${SPIRV_TOOLS}-shared>)

add_spvtools_unittest(
  TARGET cpp_interface
  SRCS cpp_interface_test.cpp
  LIBS SPIRV-Tools-opt)

if (${SPIRV_TIMER_ENABLED})
add_spvtools_unittest(
  TARGET timer
  SRCS timer_test.cpp
  LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
endif()


add_subdirectory(diff)
add_subdirectory(link)
add_subdirectory(lint)
add_subdirectory(opt)
add_subdirectory(reduce)
add_subdirectory(fuzz)
add_subdirectory(tools)
add_subdirectory(util)
add_subdirectory(val)
add_subdirectory(fuzzers)
