project(
  'nix-util-tests',
  'cpp',
  version : files('.version'),
  default_options : [
    'cpp_std=c++23',
    # TODO(Qyriad): increase the warning level
    'warning_level=1',
    'errorlogs=true', # Please print logs for tests that fail
  ],
  meson_version : '>= 1.8',
  license : 'LGPL-2.1-or-later',
)

cxx = meson.get_compiler('cpp')

subdir('nix-meson-build-support/deps-lists')

deps_private_maybe_subproject = [
  dependency('nix-util'),
  dependency('nix-util-c'),
  dependency('nix-util-test-support'),
]
deps_public_maybe_subproject = []
subdir('nix-meson-build-support/subprojects')

subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')

rapidcheck = dependency('rapidcheck')
deps_private += rapidcheck

gtest = dependency('gtest', main : false)
deps_private += gtest

gmock = dependency('gmock')
deps_private += gmock

zstd = dependency('libzstd', version : '>= 1.4.0')
deps_private += zstd

if host_machine.system() == 'windows'
  # Boost.ASIO needs this unconditionally.
  socket = cxx.find_library('ws2_32')
  deps_other += socket
endif

configdata = configuration_data()
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())

config_priv_h = configure_file(
  configuration : configdata,
  output : 'util-tests-config.hh',
)

subdir('nix-meson-build-support/common')

sources = files(
  'alignment.cc',
  'archive.cc',
  'args.cc',
  'base-n.cc',
  'bump-memory-resource.cc',
  'canon-path.cc',
  'checked-arithmetic.cc',
  'chunked-vector.cc',
  'closure.cc',
  'compression.cc',
  'config.cc',
  'current-process.cc',
  'executable-path.cc',
  'file-content-address.cc',
  'file-descriptor.cc',
  'file-system-at.cc',
  'file-system.cc',
  'fun.cc',
  'git.cc',
  'hash.cc',
  'hilite.cc',
  'json-utils.cc',
  'local-keys.cc',
  'logging.cc',
  'lru-cache.cc',
  'main.cc',
  'memo.cc',
  'memory-source-accessor.cc',
  'monitorfdhup.cc',
  'nar-listing.cc',
  'nix_api_util.cc',
  'nix_api_util_internal.cc',
  'pool.cc',
  'position.cc',
  'processes.cc',
  'ref.cc',
  'serialise.cc',
  'sort.cc',
  'source-accessor.cc',
  'spawn.cc',
  'strings.cc',
  'suggestions.cc',
  'terminal.cc',
  'topo-sort.cc',
  'url.cc',
  'util.cc',
  'xml-writer.cc',
)

if host_machine.system() != 'windows'
  subdir('unix')
endif

include_dirs = [ include_directories('.') ]


this_exe = executable(
  meson.project_name(),
  sources,
  config_priv_h,
  dependencies : deps_private_subproject + deps_private + deps_other,
  include_directories : include_dirs,
  # TODO: -lrapidcheck, see ../libutil-support/build.meson
  link_args : linker_export_flags + [ '-lrapidcheck' ],
  # get main from gtest
  install : true,
  cpp_pch : do_pch ? [ 'pch/precompiled-headers.hh' ] : [],
)

if get_option('fuzzers')
  subdir('fuzz')
endif

test(
  meson.project_name(),
  this_exe,
  env : {
    '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
  },
  protocol : 'gtest',
)

# Run the same tests again under `enosys -d openat2` to exercise the
# iterative (non-openat2) fallback path on Linux.  `enosys` uses
# seccomp to make `openat2` return `ENOSYS`, which the wrapper in
# file-system-at.cc caches and falls back to the iterative impl.
if host_machine.system() == 'linux'
  enosys = find_program('enosys', required : false)
  if enosys.found()
    test(
      meson.project_name() + '-without-new-syscalls',
      enosys,
      args : [
        '--syscall', 'openat2',
        '--syscall', 'fchmodat2',
        '--syscall', 'close_range',
        '--',
        this_exe,
      ],
      env : {
        '_NIX_TEST_UNIT_DATA' : meson.current_source_dir() / 'data',
      },
      protocol : 'gtest',
    )
  endif
endif
