function(Octopus_add_test name)
	#[===[.md
	# Octopus_add_test

	Internal helper for adding Octopus regressions tests

	## Synopsis
	```cmake
	Octopus_add_test(<name>
			[TEST_NAME <test_name>]
			[LABELS <label1> <label2>])
	```

	## Options

	`<name>`
	  Name the test-suite test without the `.test` suffix and relative to `${CMAKE_CURRENT_SOURCE_DIR}`

	`TEST_NAME` [Default: `<name>`]
	  Name for the test to be used as the ctest name

	`LABELS`
	  Additional labels to be added. This is in addition to the labels that are defined in the `.test` file

	]===]

	list(APPEND CMAKE_MESSAGE_CONTEXT Octopus_add_test)

	set(ARGS_Options)
	set(ARGS_OneValue
			TEST_NAME
	)
	set(ARGS_MultiValue
			LABELS
	)
	cmake_parse_arguments(PARSE_ARGV 1 ARGS "${ARGS_Options}" "${ARGS_OneValue}" "${ARGS_MultiValue}")
	# Check required/optional arguments
	if (ARGC LESS 1)
		message(FATAL_ERROR "Missing test name in Octopus_add_test call")
	endif ()
	if (NOT DEFINED ARGS_TEST_NAME)
		set(ARGS_TEST_NAME ${name})
	endif ()

	# Read the test file and get the line that contains TestGroups (ignoring single spaces)
	# We are assuming here that the tags do not span multiple lines
	file(STRINGS ${name}.test file_content
			REGEX "TestGroups[ \t\r\n]*:")
	# Extract the text after "TestGroups:" and save it in ${CMAKE_MATCH_1} (ignore output to _)
	string(REGEX MATCHALL "TestGroups[ \t\r\n]*:[ \t\r\n]*(.*)" _ "${file_content}")
	# Change comma or semi-colon separated list to cmake list
	string(REGEX REPLACE "(,|\\\;)[ ]*" ";" tags_list "${CMAKE_MATCH_1}")

	set(report_flags)
	if (OCTOPUS_TESTS_REPORT)
		set(report_name "report.yaml")
		# Buildbot needs to inject the name of the toolchain from CHECK_REPORT variable
		if (DEFINED ENV{CHECK_REPORT})
			set(report_name "$ENV{CHECK_REPORT}.yaml")
		endif ()
		if (NOT IS_ABSOLUTE report_name)
			# Use a common file for all reports. Note if there is a race condition the perl script side will die
			set(report_name ${PROJECT_BINARY_DIR}/testsuite/${report_name})
		endif ()
		set(report_flags -r ${report_name})
	endif ()

	set(serial_flags)
	if (OCTOPUS_TESTS_RUN_SERIAL)
		set(serial_flags -s)
	endif ()

	add_test(NAME ${ARGS_TEST_NAME}
			COMMAND ${PERL_EXECUTABLE} ${PROJECT_SOURCE_DIR}/testsuite/oct-run_regression_test.pl
			# Location of the test file
			-f ${CMAKE_CURRENT_SOURCE_DIR}/${name}.test
			# Binary folder where to find the executables
			-D ${PROJECT_BINARY_DIR}
			# Parse warnings
			-w
			# Location of the log files
			-l -L ${name}.log
			# Add -r report flags to generate yaml file
			${report_flags}
			# Add -s flag if tests are forced to run in serial
			${serial_flags}
			WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
	)
	set_tests_properties(${ARGS_TEST_NAME} PROPERTIES
			LABELS "${tags_list};${ARGS_LABELS}"
			SKIP_RETURN_CODE 254
	)
	set_property(TEST ${ARGS_TEST_NAME} APPEND
			PROPERTY ENVIRONMENT
			# OCTOPUS_SHARE is necessary to be able to run from build directory
			"OCTOPUS_SHARE=${PROJECT_BINARY_DIR}/share"
			# TMPDIR is used by OpenMPI (and maybe other tools)
			"TMPDIR=${CMAKE_CURRENT_BINARY_DIR}/${ARGS_TEST_NAME}"
	)

	# Set the appropriate parallelization properties
	# Note: In principle these should be done dynamically using `TEST_INCLUDE_FILE`, however this functionality cannot
	# get and manipulate the test properties
	# https://gitlab.kitware.com/cmake/cmake/-/issues/25362
	if (OCTOPUS_OpenMP AND DEFINED ENV{OMP_NUM_THREADS})
		set(omp_num_threads $ENV{OMP_NUM_THREADS})
	else ()
		set(omp_num_threads 1)
	endif ()

	if (OCTOPUS_TESTS_RUN_SERIAL)
		set(mpi_processes 1)
	else ()
		# Read the test file and get the line that contains Processors (ignoring single spaces). This property can occur
		# multiple times
		file(STRINGS ${name}.test file_content
				REGEX "Processors[ \t\r\n]*:")
		if (NOT file_content)
			# If there were no lines specifying Processors, set the default value [2] from oct-run_regression_test.pl
			set(mpi_processes 2)
		else ()
			# Otherwise get the maximum value and store that.
			set(mpi_processes 0)
			foreach (match_string IN LISTS file_content)
				# Extract the text after "Processors:" and save it in ${CMAKE_MATCH_1} (ignore output to _)
				string(REGEX MATCHALL "Processors[ \t\r\n]*:[ \t\r\n]*([0-9]*)" _ "${match_string}")
				if (CMAKE_MATCH_1 GREATER mpi_processes)
					set(mpi_processes ${CMAKE_MATCH_1})
				endif ()
			endforeach ()
		endif ()
	endif ()
	# Make sure OMP_NUM_THREADS is set to an appropriate value
	set_property(TEST ${ARGS_TEST_NAME} APPEND PROPERTY
			ENVIRONMENT "OMP_NUM_THREADS=${omp_num_threads}"
	)
	# Set PROCESSORS property to omp_num_threads * mpi_processes
	math(EXPR test_processors "${omp_num_threads} * ${mpi_processes}")
	set_tests_properties(${ARGS_TEST_NAME} PROPERTIES
			PROCESSORS ${test_processors}
	)

	# If the tests are not run with `ctest --resource-spec-file`, these properties should be ignored
	# Number of GPUs used is assumed to be number of mpi processes
	set_tests_properties(${ARGS_TEST_NAME} PROPERTIES
			RESOURCE_GROUPS "${mpi_processes},gpus:1"
	)

endfunction()

set(curr_path)
foreach (dir IN ITEMS
		components
		errors
		finite_systems_1d
		finite_systems_2d
		finite_systems_3d
		functionals
		lda_u
		linear_response
		maxwell
		modelmb
		multisystem
		optimal_control
		performance
		periodic_systems
		photo_electron
		pseudopotentials
		real_time
		symmetries
		tutorials
)
	# TODO: Remove when requiring cmake >= 3.25
	if (CMAKE_VERSION VERSION_LESS 3.25)
		set(temp_curr_path ${curr_path})
		cmake_path(APPEND curr_path ${dir})
		add_subdirectory(${dir})
		set(curr_path ${temp_curr_path})
	else ()
		block()
			cmake_path(APPEND curr_path ${dir})
			add_subdirectory(${dir})
		endblock()
	endif ()
endforeach ()

set(prefix "${CMAKE_INSTALL_PREFIX}")
set(datarootdir "\${prefix}/share")
set(datadir "\${datarootdir}")
set(PACKAGE "octopus")
set(EGREP "grep -E")
configure_file(oct-run_testsuite.sh.in oct-run_testsuite.sh @ONLY)
install(PROGRAMS
	oct-run_regression_test.pl
	${CMAKE_CURRENT_BINARY_DIR}/oct-run_testsuite.sh
	DESTINATION ${CMAKE_INSTALL_BINDIR})
