Skip to content
Snippets Groups Projects
Commit 4cad99e4 authored by Simon Gene Gottlieb's avatar Simon Gene Gottlieb
Browse files

patch: removing test and doc

parent e8ad4394
No related branches found
No related tags found
No related merge requests found
Showing
with 0 additions and 962 deletions
cmake_minimum_required (VERSION 3.8)
# Find doxygen.
find_package (Doxygen QUIET)
if (${DOXYGEN_FOUND})
message (STATUS "Found Doxygen: ${DOXYGEN_EXECUTABLE}")
# Configure doxygen options.
set (APP_TEMPLATE_DOXYFILE_IN ${CMAKE_SOURCE_DIR}/doc/doxygen_cfg)
set (APP_TEMPLATE_DOXYGEN_OUTPUT_DIR "${PROJECT_BINARY_DIR}/doc")
set (APP_TEMPLATE_DOXYGEN_EXCLUDE_SYMBOLS "")
set (APP_TEMPLATE_DOXYGEN_PREDEFINED_NDEBUG "")
set (APP_TEMPLATE_DOXYGEN_ENABLED_SECTIONS "DEV")
set (APP_TEMPLATE_DOXYGEN_EXTRACT_PRIVATE "YES")
configure_file (${APP_TEMPLATE_DOXYFILE_IN} ${APP_TEMPLATE_DOXYGEN_OUTPUT_DIR}/Doxyfile)
add_custom_target (doc
COMMAND ${DOXYGEN_EXECUTABLE}
WORKING_DIRECTORY ${APP_TEMPLATE_DOXYGEN_OUTPUT_DIR}
COMMENT "Generating (developer) API documentation with Doxygen."
VERBATIM)
message (STATUS "${FontBold}You can run `make doc` to build api documentation.${FontReset}")
else ()
message (STATUS "Doxygen not found.")
endif ()
# Documentation
To build the API documentation, you need to install `doxygen`. We use Doxygen version 1.8.17.
Run `make doc` and open the API documentation via `open doc/html/index.html`.
You can run `doxygen -u doxygen_cfg` to convert the configuration file to its verbose version.
`doxygen -u -s doxygen_cfg` will convert it back to its compact version.
# Doxyfile 1.9.1
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = fastq_to_fasta
PROJECT_NUMBER =
PROJECT_BRIEF = "A template for creation of SeqAn3 apps, with a FASTQ to FASTA example app."
PROJECT_LOGO =
OUTPUT_DIRECTORY = ${APP_TEMPLATE_DOXYGEN_OUTPUT_DIR}
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = ${CMAKE_SOURCE_DIR}
STRIP_FROM_INC_PATH = ${CMAKE_SOURCE_DIR}/include
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
PYTHON_DOCSTRING = YES
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
NUM_PROC_THREADS = 1
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_PRIV_VIRTUAL = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
RESOLVE_UNNAMED_PARAMS = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ${CMAKE_SOURCE_DIR}/include \
${CMAKE_SOURCE_DIR}/src \
${CMAKE_SOURCE_DIR}/LICENSE.md
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.idl \
*.ddl \
*.odl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.cs \
*.d \
*.php \
*.php4 \
*.php5 \
*.phtml \
*.inc \
*.m \
*.markdown \
*.md \
*.mm \
*.dox \
*.doc \
*.txt \
*.py \
*.pyw \
*.f90 \
*.f95 \
*.f03 \
*.f08 \
*.f \
*.for \
*.tcl \
*.vhd \
*.vhdl \
*.ucf \
*.qsf \
*.ice
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
CLANG_ASSISTED_PARSING = NO
CLANG_ADD_INC_PATHS = YES
CLANG_OPTIONS =
CLANG_DATABASE_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
FORMULA_MACROFILE =
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME =
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH = ${CMAKE_SOURCE_DIR}/include
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
DOT_UML_DETAILS = NO
DOT_WRAP_THRESHOLD = 17
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
cmake_minimum_required (VERSION 3.8)
# Set directories for test output files, input data and binaries.
file (MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/output)
add_definitions (-DOUTPUTDIR=\"${CMAKE_CURRENT_BINARY_DIR}/output/\")
add_definitions (-DDATADIR=\"${CMAKE_CURRENT_BINARY_DIR}/data/\")
add_definitions (-DBINDIR=\"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/\")
# Define cmake configuration flags to configure and build external projects with the same flags as specified for
# this project.
# We also pass the C_COMPILER such that googletest is built with the corresponding GCC.
# Otherwise, it might happen that the app is built with, e.g., g++-11, but gtest with gcc-7, which might cause trouble.
set (SEQAN3_EXTERNAL_PROJECT_CMAKE_ARGS "")
list (APPEND SEQAN3_EXTERNAL_PROJECT_CMAKE_ARGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}")
list (APPEND SEQAN3_EXTERNAL_PROJECT_CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
list (APPEND SEQAN3_EXTERNAL_PROJECT_CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
list (APPEND SEQAN3_EXTERNAL_PROJECT_CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}")
list (APPEND SEQAN3_EXTERNAL_PROJECT_CMAKE_ARGS "-DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE}")
set (SEQAN3_TEST_CLONE_DIR "${PROJECT_BINARY_DIR}/vendor/googletest")
include (seqan3_require_test)
seqan3_require_test ()
# Build tests just before their execution, because they have not been built with "all" target.
# The trick is here to provide a cmake file as a directory property that executes the build command.
file (WRITE "${CMAKE_CURRENT_BINARY_DIR}/build_test_targets.cmake"
"execute_process (COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target api_test)\n"
"execute_process (COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target cli_test)\n"
"execute_process (COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target header_test)\n")
set_directory_properties (PROPERTIES TEST_INCLUDE_FILE "${CMAKE_CURRENT_BINARY_DIR}/build_test_targets.cmake")
# Test executables and libraries should not mix with the application files.
unset (CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
unset (CMAKE_LIBRARY_OUTPUT_DIRECTORY)
unset (CMAKE_RUNTIME_OUTPUT_DIRECTORY)
include (seqan3_test_component)
# A macro that adds an api or cli test.
macro (add_app_test test_filename)
# Extract the test target name.
file (RELATIVE_PATH source_file "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_LIST_DIR}/${test_filename}")
seqan3_test_component (target "${source_file}" TARGET_NAME)
seqan3_test_component (test_name "${source_file}" TEST_NAME)
# Create the test target.
add_executable (${target} ${test_filename})
target_link_libraries (${target} "${PROJECT_NAME}_lib" seqan3::seqan3 gtest gtest_main)
# Make seqan3::test available for both cli and api tests.
target_include_directories (${target} PUBLIC "${SEQAN3_CLONE_DIR}/test/include")
target_include_directories (${target} PUBLIC "${SEQAN3_TEST_CLONE_DIR}/googletest/include/")
# Generate and set the test name.
add_test (NAME "${test_name}" COMMAND ${target})
unset (source_file)
unset (target)
unset (test_name)
endmacro ()
string (TOUPPER ${PROJECT_NAME} uppercase_project_name)
set (${uppercase_project_name}_HEADER_TEST_ONLY OFF CACHE BOOL "Only build header test.")
if (${uppercase_project_name}_HEADER_TEST_ONLY)
add_subdirectory (header)
else ()
# Fetch data and add the tests.
include (data/datasources.cmake)
add_subdirectory (api)
add_subdirectory (cli)
add_subdirectory (coverage)
endif ()
message (STATUS "${FontBold}You can run `make test` to build and run tests.${FontReset}")
cmake_minimum_required (VERSION 3.8)
add_custom_target (api_test ALL)
macro (add_api_test test_filename)
add_app_test (${test_filename})
seqan3_test_component (target "${test_filename}" TARGET_NAME)
add_dependencies (api_test ${target})
endmacro ()
add_api_test (convert_fastq_test.cpp)
target_use_datasources (convert_fastq_test FILES in.fastq)
# API Test
Here are test files for API tests, i.e. the internal functions of the app are executed with different input parameters.
The test then validates whether the functions work correctly.
Attention: The default `make` target does not build tests.
Please invoke the build with `make api_test` or use `make test` to build and run all kinds of tests.
#include <gtest/gtest.h>
#include <seqan3/alphabet/nucleotide/dna5.hpp>
#include <seqan3/core/detail/debug_stream_alphabet.hpp>
#include <seqan3/io/sequence_file/input.hpp>
#include <seqan3/test/expect_range_eq.hpp>
#include "fastq_conversion.hpp"
TEST(group1, out_empty)
{
std::string expected{"> seq1\nACGTTTGATTCGCG\n> seq2\nTCGGGGGATTCGCG\n"};
testing::internal::CaptureStdout();
convert_fastq(DATADIR"in.fastq", "");
std::string std_cout = testing::internal::GetCapturedStdout();
EXPECT_RANGE_EQ(expected, std_cout);
}
TEST(group1, out_not_empty)
{
std::filesystem::path tmp_dir = std::filesystem::temp_directory_path(); // get the temp directory
convert_fastq(DATADIR"in.fastq", tmp_dir/"out.fasta"); // create out.fasta
// Check if out.fasta is correct
using seqan3::operator""_dna5;
std::vector<seqan3::dna5_vector> expected_seqs = {"ACGTTTGATTCGCG"_dna5, "TCGGGGGATTCGCG"_dna5};
std::vector<std::string> expected_ids{"seq1", "seq2"};
std::vector<seqan3::dna5_vector> seqs{};
std::vector<std::string> ids{};
seqan3::sequence_file_input fin{tmp_dir/"out.fasta"};
for (auto & [seq, id, qual] : fin)
{
ids.push_back(id);
seqs.push_back(seq);
}
EXPECT_RANGE_EQ(seqs, expected_seqs);
EXPECT_RANGE_EQ(ids, expected_ids);
}
# Benchmarks
Here are test files for benchmarks with respect to time, space consumption and memory.
They are usually based on the command-line interface, but you can also add micro benchmark if you wish.
The benchmark tests are not yet implemented.
cmake_minimum_required (VERSION 3.8)
# CLI Test
Here are test files for command line interface tests, i.e. the app is executed with defined input files and parameters.
The test then validates whether the output is correct.
Each test fixture should be inherited from the `cli_test` class: It provides the functionality of executing the app,
finding the input files, capturing the output and creating individual test directories.
We provide a new test macro `EXPECT_RANGE_EQ` for the comparison of whole ranges.
It provides more insights about differences than an implementation with `EXPECT_TRUE(std::ranges::equal())`.
The test output files are stored in the directory `test/output`.
To prevent issues when running multiple CLI tests in parallel, each CLI should use its own derived test fixture.
For example, if two CLI tests run a test called `my_test` and both use the `cli_test` test fixture, there may
be issues because both tests will use the same working directory. Instead, define different test fixtures for both
tests, e.g. `struct my_test_fixture : public cli_test {};`.
Attention: The default `make` target does not build tests.
Please invoke the build with `make cli_test` or use `make test` to build and run all kinds of tests.
#include <gtest/gtest.h>
#include <cstdlib> // system calls
#include <seqan3/std/filesystem> // test directory creation
#include <sstream> // ostringstream
#include <string> // strings
#pragma once
// Provides functions for CLI test implementation.
struct cli_test : public ::testing::Test
{
private:
// Holds the original work directory where Gtest has been started.
std::filesystem::path original_workdir{};
protected:
// Result struct for captured streams and exit code.
struct cli_test_result
{
std::string out{};
std::string err{};
int exit_code{};
};
// Invoke the app execution. The command line call should be given as separate parameters.
template <typename... CommandItemTypes>
cli_test_result execute_app(CommandItemTypes &&... command_items)
{
cli_test_result result{};
// Assemble the command string and disable version check.
std::ostringstream command{};
command << "SEQAN3_NO_VERSION_CHECK=1 " << BINDIR;
int a[] = {0, ((void)(command << command_items << ' '), 0) ... };
(void) a;
// Always capture the output streams.
testing::internal::CaptureStdout();
testing::internal::CaptureStderr();
// Run the command and return results.
result.exit_code = std::system(command.str().c_str());
result.out = testing::internal::GetCapturedStdout();
result.err = testing::internal::GetCapturedStderr();
return result;
}
// Generate the full path of a test input file that is provided in the data directory.
static std::filesystem::path data(std::string const & filename)
{
return std::filesystem::path{std::string{DATADIR}}.concat(filename);
}
// Create an individual work directory for the current test.
void SetUp() override
{
// Assemble the directory name.
::testing::TestInfo const * const info = ::testing::UnitTest::GetInstance()->current_test_info();
std::filesystem::path const test_dir{std::string{OUTPUTDIR} +
std::string{info->test_case_name()} +
std::string{"."} +
std::string{info->name()}};
try
{
std::filesystem::remove_all(test_dir); // delete the directory if it exists
std::filesystem::create_directories(test_dir); // create the new empty directory
original_workdir = std::filesystem::current_path(); // store original work dir path
std::filesystem::current_path(test_dir); // change the work dir
}
catch (std::exception const & exc)
{
FAIL() << "Failed to set up the test directory " << test_dir << ":\n" << exc.what();
}
}
// Switch back to the initial work directory.
void TearDown() override
{
try
{
std::filesystem::current_path(original_workdir); // restore the original work dir
}
catch (std::exception const & exc)
{
FAIL() << "Failed to set the work directory to " << original_workdir << ":\n" << exc.what();
}
}
};
#include <seqan3/std/ranges> // range comparisons
#include <string> // strings
#include <vector> // vectors
#include <seqan3/alphabet/nucleotide/dna5.hpp>
#include <seqan3/core/detail/debug_stream_alphabet.hpp>
#include <seqan3/core/detail/debug_stream_tuple.hpp>
#include <seqan3/core/detail/debug_stream_type.hpp>
#include <seqan3/io/sequence_file/input.hpp>
// Include the EXPECT_RANGE_EQ macro for better information if range elements differ.
#include <seqan3/test/expect_range_eq.hpp>
#include "cli_test.hpp"
// To prevent issues when running multiple CLI tests in parallel, give each CLI test unique names:
struct fastq_to_fasta : public cli_test {};
TEST_F(fastq_to_fasta, no_options)
{
cli_test_result result = execute_app("app-template");
std::string expected
{
"Fastq-to-Fasta-Converter\n"
"========================\n"
" Try -h or --help for more information.\n"
};
EXPECT_EQ(result.exit_code, 0);
EXPECT_EQ(result.out, expected);
EXPECT_EQ(result.err, std::string{});
}
TEST_F(fastq_to_fasta, fail_no_argument)
{
cli_test_result result = execute_app("app-template", "-v");
std::string expected
{
"Parsing error. Not enough positional arguments provided (Need at least 1). "
"See -h/--help for more information.\n"
};
EXPECT_NE(result.exit_code, 0);
EXPECT_EQ(result.out, std::string{});
EXPECT_EQ(result.err, expected);
}
TEST_F(fastq_to_fasta, with_argument)
{
cli_test_result result = execute_app("app-template", data("in.fastq"));
EXPECT_EQ(result.exit_code, 0);
EXPECT_EQ(result.out, "> seq1\nACGTTTGATTCGCG\n> seq2\nTCGGGGGATTCGCG\n");
EXPECT_EQ(result.err, std::string{});
}
TEST_F(fastq_to_fasta, with_argument_verbose)
{
cli_test_result result = execute_app("app-template", data("in.fastq"), "-v");
EXPECT_EQ(result.exit_code, 0);
EXPECT_EQ(result.out, "> seq1\nACGTTTGATTCGCG\n> seq2\nTCGGGGGATTCGCG\n");
EXPECT_EQ(result.err, "Conversion was a success. Congrats!\n");
}
TEST_F(fastq_to_fasta, with_out_file)
{
cli_test_result result = execute_app("app-template", data("in.fastq"), "-o", "out.fasta");
seqan3::sequence_file_input fin{"out.fasta", seqan3::fields<seqan3::field::seq, seqan3::field::id>{}};
// create records to compare
using record_type = typename decltype(fin)::record_type;
using seqan3::operator""_dna5;
std::vector<record_type> records{};
records.emplace_back("ACGTTTGATTCGCG"_dna5, std::string{"seq1"});
records.emplace_back("TCGGGGGATTCGCG"_dna5, std::string{"seq2"});
EXPECT_RANGE_EQ(fin, records);
EXPECT_EQ(result.exit_code, 0);
EXPECT_EQ(result.out, std::string{});
EXPECT_EQ(result.err, std::string{});
}
include (ExternalProject)
# Example call:
#
# ```cmake
# declare_datasource (
# FILE pdb100d.ent.gz # build/data/pdb100d.ent.gz
# URL ftp://ftp.wwpdb.org/pub/pdb/data/structures/divided/pdb/00/pdb100d.ent.gz # 16KiloByte
# URL_HASH SHA256=c2b8f884568b07f58519966e256e2f3aa440508e8013bd10e0ee338e138e62a0)
# ```
#
# Options:
#
# declare_datasource (FILE <datasource name> URL <url1> [<url2>...] [URL_HASH <algo>=<hashValue>] [<option>...])
#
# FILE <datasource name> (required):
# The name of the downloaded file (must be unique across all declared datasources).
# This will put the file into the ``<build>/data/<datasource name>`` folder.
#
# URL <url1> [<url2>...] (required):
# List of paths and/or URL(s) of the external datasource. When more than one URL is given, they are tried in
# turn until one succeeds. A URL may be an ordinary path in the local file system (in which case it must be the only
# URL provided) or any downloadable URL supported by the file(DOWNLOAD) command. A local filesystem path may refer to
# either an existing directory or to an archive file, whereas a URL is expected to point to a file which can be
# treated as an archive.
#
# URL_HASH <algo>=<hashValue> (optional):
# Hash of the archive file to be downloaded. The argument should be of the form <algo>=<hashValue> where algo can be
# any of the hashing algorithms supported by the file() command. Specifying this option is strongly recommended for
# URL downloads, as it ensures the integrity of the downloaded content. It is also used as a check for a previously
# downloaded file, allowing connection to the remote location to be avoided altogether if the local directory already
# has a file from an earlier download that matches the specified hash.
#
# This uses under the hood ExternalProject's and you can pass any viable option of ExternalProject to this function and
# overwrite the default behaviour. See https://cmake.org/cmake/help/latest/module/ExternalProject.html for more
# information.
function (declare_datasource)
set (options "")
set (one_value_args FILE URL_HASH)
set (multi_value_args URL)
cmake_parse_arguments (ARG "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
string (TOLOWER "datasource--${ARG_FILE}" datasource_name)
# create data folder
file (MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data)
ExternalProject_Add (
"${datasource_name}"
URL "${ARG_URL}"
URL_HASH "${ARG_URL_HASH}"
DOWNLOAD_NAME "${ARG_FILE}"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND
${CMAKE_COMMAND} -E create_symlink <DOWNLOADED_FILE> ${CMAKE_CURRENT_BINARY_DIR}/data/${ARG_FILE}
TEST_COMMAND ""
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_datasources"
DOWNLOAD_NO_EXTRACT TRUE # don't extract archive files like .tar.gz.
${ARG_UNPARSED_ARGUMENTS}
)
endfunction ()
# Example call:
#
# ```cmake
# # my_app uses and needs the files RF00001.fa.gz, pdb100d.ent.gz, and GRCh38_latest_clinvar.vcf.gz.
# target_use_datasources (my_app FILES RF00001.fa.gz pdb100d.ent.gz GRCh38_latest_clinvar.vcf.gz)
# ```
#
# Options:
#
# target_use_datasources (<target> FILES <file1> [<file2>...])
#
# It declares that a <target> uses and depends on the following files.
#
# This also sets the build requirement that the files must be downloaded before the <target> will be build.
#
# The named <target> must have been created by a command such as add_executable() or add_library().
function (target_use_datasources target)
set (options "")
set (one_value_args)
set (multi_value_args "FILES")
cmake_parse_arguments (ARG "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
foreach (filename ${ARG_FILES})
string (TOLOWER "datasource--${filename}" datasource_name)
add_dependencies ("${target}" "${datasource_name}")
endforeach ()
endfunction ()
cmake_minimum_required (VERSION 3.8)
# Add a custom build type: Coverage
set (CMAKE_CXX_FLAGS_COVERAGE
"${CMAKE_CXX_FLAGS_DEBUG} --coverage -fprofile-arcs -ftest-coverage" CACHE STRING
"Flags used by the C++ compiler during coverage builds."
FORCE)
set (CMAKE_C_FLAGS_COVERAGE
"${CMAKE_C_FLAGS_DEBUG} --coverage -fprofile-arcs -ftest-coverage" CACHE STRING
"Flags used by the C compiler during coverage builds."
FORCE)
set (CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} -Wl,-lgcov" CACHE STRING
"Flags used for linking binaries during coverage builds."
FORCE)
set (CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -Wl,-lgcov" CACHE STRING
"Flags used by the shared libraries linker during coverage builds."
FORCE)
mark_as_advanced (
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
# Coverage Test
This is the test for the code coverage.
It reaches 100% if each code line is executed at least once through the app tests.
Coverage tests are not yet part of the CMake configuration like it is in SeqAn3.
However, the CI tests code coverage by running gcov and uploading the results to codecov.
The custom build type `Coverage` can be used to configure the project such that coverage reports are possible.
# Data Directory
Store the data here that should be used as input files for the tests.
Large files (>50kb) should not be stored here, but rather fetched from a webserver.
Register each file (from external or internal storage) in the `datasources.cmake` file.
cmake_minimum_required (VERSION 3.8)
include (cmake/app_datasources.cmake)
# copies file to <build>/data/in.fastq
declare_datasource (FILE in.fastq
URL ${CMAKE_SOURCE_DIR}/test/data/in.fastq
URL_HASH SHA256=6e30fc35f908a36fe0c68a7a35c47f51f9570da16622fb0c072a20e6a9ba5b3e)
@seq1
ACGTTTGATTCGCG
+
!**55CCF>>>>>C
@seq2
TCGGGGGATTCGCG
+
!**65CCF>CF>>C
cmake_minimum_required (VERSION 3.8)
include (seqan3_test_files)
include (seqan3_test_component)
add_library ("${PROJECT_NAME}_header_test_lib" INTERFACE)
target_link_libraries ("${PROJECT_NAME}_header_test_lib" INTERFACE "${PROJECT_NAME}_interface" gtest gtest_main)
target_include_directories ("${PROJECT_NAME}_header_test_lib" INTERFACE "${SEQAN3_TEST_CLONE_DIR}/googletest/include/")
# SeqAn3 script adds an include for <bechmark/benchmark.h>
target_include_directories ("${PROJECT_NAME}_header_test_lib" INTERFACE ./dummy_include)
set (target "header_test")
set (header_base_path "${CMAKE_CURRENT_LIST_DIR}/../../include/")
file (GLOB_RECURSE header_files RELATIVE "${header_base_path}" "${header_base_path}/*.hpp")
file (WRITE "${PROJECT_BINARY_DIR}/${target}.cpp" "")
add_executable (${target} ${PROJECT_BINARY_DIR}/${target}.cpp)
target_link_libraries (${target} ${PROJECT_NAME}_header_test_lib)
add_test (NAME "header/${target}" COMMAND ${target})
foreach (header ${header_files})
seqan3_test_component (header_test_name "${header}" TEST_NAME)
seqan3_test_component (header_target_name "${header}" TARGET_UNIQUE_NAME)
foreach (header_sub_test "header-guard" "no-self-include")
set (header_target_source "${PROJECT_BINARY_DIR}/${target}_files/${header_test_name}.hpp-${header_sub_test}.cpp")
set (header_target "${target}--${header_target_name}-${header_sub_test}")
string (REPLACE "-" "__" header_test_name_safe "${target}, ${header_target}")
# we use add_custom_command to detect changes to a header file, which will update the generated source file
add_custom_command (OUTPUT "${header_target_source}"
COMMAND "${CMAKE_COMMAND}"
"-DHEADER_FILE_ABSOLUTE=${header_base_path}/${header}"
"-DHEADER_FILE_INCLUDE=${header}"
"-DHEADER_TARGET_SOURCE=${header_target_source}"
"-DHEADER_TEST_NAME_SAFE=${header_test_name_safe}"
"-DHEADER_COMPONENT=${PROJECT_NAME}"
"-DHEADER_SUB_TEST=${header_sub_test}"
"-P"
"${SEQAN3_CLONE_DIR}/test/header/generate_header_source.cmake"
DEPENDS "${header_base_path}/${header}"
"${SEQAN3_CLONE_DIR}/test/header/generate_header_source.cmake")
add_library (${header_target} OBJECT "${header_target_source}")
# NOTE: a simple target_link_libraries (${header_target} ${PROJECT_NAME}_header_test_lib)
# is not possible for OBJECT libraries before cmake 3.12
if (CMAKE_VERSION VERSION_LESS 3.12)
target_compile_options (${header_target} PRIVATE $<TARGET_PROPERTY:${PROJECT_NAME}_header_test_lib,INTERFACE_COMPILE_OPTIONS>)
target_compile_definitions (${header_target} PRIVATE $<TARGET_PROPERTY:${PROJECT_NAME}_header_test_lib,INTERFACE_COMPILE_DEFINITIONS>)
target_include_directories (${header_target} PRIVATE $<TARGET_PROPERTY:${PROJECT_NAME}_header_test_lib,INTERFACE_INCLUDE_DIRECTORIES>)
add_dependencies (${header_target} "${PROJECT_NAME}_interface" gtest gtest_main)
else ()
target_link_libraries (${header_target} ${PROJECT_NAME}_header_test_lib)
endif ()
target_sources (${target} PRIVATE $<TARGET_OBJECTS:${header_target}>)
endforeach ()
endforeach ()
#pragma once
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment