# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

set(CMAKE_COMPILE_WARNING_AS_ERROR FALSE)

set(INSTALL_GTEST
    OFF
    CACHE BOOL "" FORCE)

fetchcontent_declare(googletest
                     GIT_REPOSITORY https://github.com/google/googletest.git
                     GIT_TAG b514bdc898e2951020cbdca1304b75f5950d1f59 # release-1.15.2
                     FIND_PACKAGE_ARGS
                     NAMES
                     GTest)

fetchcontent_makeavailable(googletest)

set(ICEBERG_TEST_RESOURCES "${CMAKE_SOURCE_DIR}/src/iceberg/test/resources")

configure_file("test_config.h.in" "test_config.h")

function(add_iceberg_test test_name)
  set(options USE_BUNDLE USE_DATA)
  set(oneValueArgs)
  set(multiValueArgs SOURCES)
  cmake_parse_arguments(ARG
                        "${options}"
                        "${oneValueArgs}"
                        "${multiValueArgs}"
                        ${ARGN})

  add_executable(${test_name})
  target_include_directories(${test_name} PRIVATE "${CMAKE_BINARY_DIR}/iceberg/test/")

  target_sources(${test_name} PRIVATE ${ARG_SOURCES})

  if(ARG_USE_BUNDLE)
    target_link_libraries(${test_name}
                          PRIVATE "$<IF:$<TARGET_EXISTS:iceberg_bundle_static>,iceberg_bundle_static,iceberg_bundle_shared>"
                                  GTest::gmock_main)
  elseif(ARG_USE_DATA)
    target_link_libraries(${test_name}
                          PRIVATE "$<IF:$<TARGET_EXISTS:iceberg_data_static>,iceberg_data_static,iceberg_data_shared>"
                                  GTest::gmock_main)
  else()
    target_link_libraries(${test_name}
                          PRIVATE "$<IF:$<TARGET_EXISTS:iceberg_static>,iceberg_static,iceberg_shared>"
                                  GTest::gmock_main)
  endif()

  if(MSVC_TOOLCHAIN)
    target_compile_options(${test_name} PRIVATE /bigobj)
  endif()

  add_test(NAME ${test_name} COMMAND ${test_name})
endfunction()

add_iceberg_test(schema_test
                 SOURCES
                 assign_id_visitor_test.cc
                 name_mapping_test.cc
                 partition_field_test.cc
                 partition_spec_test.cc
                 partition_value_test.cc
                 schema_field_test.cc
                 schema_test.cc
                 schema_util_test.cc
                 sort_field_test.cc
                 sort_order_test.cc
                 transform_human_string_test.cc
                 transform_test.cc
                 type_test.cc)

add_iceberg_test(table_test
                 SOURCES
                 location_provider_test.cc
                 metrics_config_test.cc
                 metrics_reporter_test.cc
                 metrics_test.cc
                 snapshot_summary_builder_test.cc
                 snapshot_test.cc
                 snapshot_util_test.cc
                 table_metadata_builder_test.cc
                 table_requirement_test.cc
                 table_requirements_test.cc
                 table_test.cc
                 table_update_test.cc)

add_iceberg_test(expression_test
                 SOURCES
                 aggregate_test.cc
                 expression_json_test.cc
                 expression_test.cc
                 expression_visitor_test.cc
                 inclusive_metrics_evaluator_test.cc
                 inclusive_metrics_evaluator_with_transform_test.cc
                 literal_test.cc
                 manifest_evaluator_test.cc
                 predicate_test.cc
                 projections_test.cc
                 residual_evaluator_test.cc
                 strict_metrics_evaluator_test.cc)

add_iceberg_test(json_serde_test
                 SOURCES
                 json_serde_test.cc
                 metadata_serde_test.cc
                 schema_json_test.cc)

add_iceberg_test(util_test
                 USE_DATA
                 SOURCES
                 base64_test.cc
                 bucket_util_test.cc
                 config_test.cc
                 data_file_set_test.cc
                 decimal_test.cc
                 endian_test.cc
                 file_io_test.cc
                 formatter_test.cc
                 lazy_test.cc
                 location_util_test.cc
                 math_util_internal_test.cc
                 roaring_position_bitmap_test.cc
                 position_delete_index_test.cc
                 position_delete_range_consumer_test.cc
                 retry_util_test.cc
                 string_util_test.cc
                 struct_like_set_test.cc
                 task_group_test.cc
                 temporal_util_test.cc
                 transform_util_test.cc
                 truncate_util_test.cc
                 url_encoder_test.cc
                 uuid_test.cc
                 visit_type_test.cc)

add_iceberg_test(puffin_test
                 USE_DATA
                 SOURCES
                 puffin_format_test.cc
                 puffin_json_test.cc
                 puffin_reader_writer_test.cc)

if(ICEBERG_BUILD_BUNDLE)
  add_iceberg_test(avro_test
                   USE_BUNDLE
                   SOURCES
                   avro_data_test.cc
                   avro_test.cc
                   avro_schema_test.cc
                   avro_stream_test.cc)

  add_iceberg_test(arrow_test
                   USE_BUNDLE
                   SOURCES
                   arrow_io_test.cc
                   arrow_test.cc
                   gzip_decompress_test.cc
                   metadata_io_test.cc
                   struct_like_test.cc)

  if(ICEBERG_S3)
    add_iceberg_test(file_io_test USE_BUNDLE SOURCES arrow_s3_file_io_test.cc)
  endif()

  add_iceberg_test(catalog_test USE_BUNDLE SOURCES in_memory_catalog_test.cc)

  add_iceberg_test(eval_expr_test
                   USE_BUNDLE
                   SOURCES
                   eval_expr_test.cc
                   evaluator_test.cc)

  add_iceberg_test(manifest_test
                   USE_BUNDLE
                   SOURCES
                   delete_file_index_test.cc
                   manifest_group_test.cc
                   manifest_list_versions_test.cc
                   manifest_merge_manager_test.cc
                   manifest_reader_stats_test.cc
                   manifest_reader_test.cc
                   manifest_writer_versions_test.cc
                   rolling_manifest_writer_test.cc)

  add_iceberg_test(parquet_test
                   USE_BUNDLE
                   SOURCES
                   metrics_test_base.cc
                   parquet_data_test.cc
                   parquet_metrics_test.cc
                   parquet_schema_test.cc
                   parquet_test.cc)

  add_iceberg_test(scan_test
                   USE_BUNDLE
                   SOURCES
                   file_scan_task_test.cc
                   incremental_append_scan_test.cc
                   incremental_changelog_scan_test.cc
                   table_scan_test.cc)

  add_iceberg_test(table_update_test
                   USE_BUNDLE
                   SOURCES
                   expire_snapshots_test.cc
                   fast_append_test.cc
                   manifest_filter_manager_test.cc
                   merging_snapshot_update_test.cc
                   name_mapping_update_test.cc
                   snapshot_manager_test.cc
                   transaction_test.cc
                   update_location_test.cc
                   update_partition_spec_test.cc
                   update_partition_statistics_test.cc
                   update_properties_test.cc
                   update_schema_test.cc
                   update_sort_order_test.cc
                   update_statistics_test.cc)

  add_iceberg_test(data_test
                   USE_BUNDLE
                   SOURCES
                   arrow_c_data_util_test.cc
                   data_writer_test.cc
                   delete_filter_test.cc
                   delete_loader_test.cc
                   file_scan_task_reader_test.cc)

endif()

if(ICEBERG_BUILD_SQL_CATALOG
   AND ICEBERG_SQL_SQLITE
   AND ICEBERG_BUILD_BUNDLE)
  add_executable(sql_catalog_test)
  target_include_directories(sql_catalog_test PRIVATE "${CMAKE_BINARY_DIR}/iceberg/test/")
  target_sources(sql_catalog_test PRIVATE sql_catalog_test.cc)
  target_link_libraries(sql_catalog_test
                        PRIVATE iceberg_sql_catalog_static
                                "$<IF:$<TARGET_EXISTS:iceberg_bundle_static>,iceberg_bundle_static,iceberg_bundle_shared>"
                                GTest::gmock_main)
  if(MSVC_TOOLCHAIN)
    target_compile_options(sql_catalog_test PRIVATE /bigobj)
  endif()
  add_test(NAME sql_catalog_test COMMAND sql_catalog_test)
endif()

if(ICEBERG_BUILD_REST)
  function(add_rest_iceberg_test test_name)
    set(options USE_BUNDLE)
    set(oneValueArgs)
    set(multiValueArgs SOURCES)
    cmake_parse_arguments(ARG
                          "${options}"
                          "${oneValueArgs}"
                          "${multiValueArgs}"
                          ${ARGN})

    add_executable(${test_name})
    target_include_directories(${test_name} PRIVATE "${CMAKE_BINARY_DIR}/iceberg/test/")
    target_sources(${test_name} PRIVATE ${ARG_SOURCES})
    target_link_libraries(${test_name} PRIVATE GTest::gmock_main iceberg_rest_static)
    if(MSVC_TOOLCHAIN)
      target_compile_options(${test_name} PRIVATE /bigobj)
    endif()
    add_test(NAME ${test_name} COMMAND ${test_name})
  endfunction()

  add_rest_iceberg_test(rest_catalog_test
                        SOURCES
                        auth_manager_test.cc
                        endpoint_test.cc
                        rest_file_io_test.cc
                        rest_json_serde_test.cc
                        rest_util_test.cc)

  if(ICEBERG_BUILD_REST_INTEGRATION_TESTS)
    add_rest_iceberg_test(rest_catalog_integration_test
                          SOURCES
                          rest_catalog_integration_test.cc
                          util/cmd_util.cc
                          util/docker_compose_util.cc)
  endif()
endif()
