Skip to content

Commit c7fa42b

Browse files
authored
Add unit test cases and Continous Integration. (#113)
Added (i) CMake build scripts, test datasets, and test cases with Catch2 framework and (ii) Github workflow for CI :Build/Test with CMake/CTest and code coverage with codecov. and (iii) Functionality for sanity check (turned off by default), the fix the visual output bug, and test case for multiple references.
1 parent d776e34 commit c7fa42b

58 files changed

Lines changed: 280925 additions & 10 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/main.yml

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: Build with CMake and Test
2+
3+
run-name: Build FastANI with CMake and Test by ${{github.actor}}
4+
5+
on:
6+
push:
7+
branches: [ "master" ]
8+
pull_request:
9+
branches: [ "master" ]
10+
11+
# Allows to run this workflow from the Actions tab (w.o. trigger)
12+
workflow_dispatch:
13+
14+
env:
15+
# CMake build type (Release, Debug, RelWithDebInfo, etc.)
16+
BUILD_TYPE: Debug
17+
18+
jobs:
19+
Build-Test:
20+
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
- uses: actions/checkout@v3
25+
with:
26+
submodules: recursive
27+
lfs: true
28+
- name: Install zlib, gsl, cppcheck and lcov
29+
run: |
30+
sudo apt-get update
31+
sudo apt-get install zlib1g-dev libgsl-dev cppcheck lcov
32+
# Static Analysis with cppcheck
33+
- name: cppcheck
34+
run: cppcheck --enable=all --inconclusive --force --std=c++20 -iext/ -I src/ --output-file=cppcheck_report.txt .
35+
# uses: deep5050/cppcheck-action@main
36+
# with:
37+
# exclude_check: ext/
38+
# inconcusive: enable
39+
# force: enable
40+
# other_options: "--includes-file=src/cgi/include/*.hpp"
41+
# github_token: ${{ secrets.GITHUB_TOKEN}}
42+
# - name: publish report
43+
# uses: mikeal/publish-to-github-action@master
44+
# env:
45+
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46+
# BRANCH_NAME: 'master' # your branch name goes here
47+
- name: Upload CPPCheck Report as artifact
48+
uses: actions/upload-artifact@v3
49+
with:
50+
name: CPPCheck-Report
51+
path: ${{github.workspace}}/cppcheck_report.txt
52+
# Building
53+
- name: Configure CMake
54+
# https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
55+
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTING=ON
56+
- name: Build
57+
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
58+
# Testing
59+
- name: Test
60+
working-directory: ${{github.workspace}}/build
61+
# https://cmake.org/cmake/help/latest/manual/ctest.1.html
62+
run: ctest -C ${{env.BUILD_TYPE}}
63+
# Run code coverage
64+
- name: Run lcov to generate coverage
65+
working-directory: ${{github.workspace}}/build
66+
run: make lcov2
67+
# Reporting code coverage
68+
- name: Report code coverage
69+
uses: zgosalvez/github-actions-report-lcov@v2
70+
with:
71+
working-directory: ${{github.workspace}}/build
72+
coverage-files: ${{github.workspace}}/build/coverage.info
73+
artifact-name: code-coverage-report
74+
github-token: ${{ secrets.GITHUB_TOKEN }}
75+
# Uploading to Codecov
76+
- name: Upload coverage reports to codecov.io
77+
uses: codecov/codecov-action@v3
78+
with:
79+
token: ${{ secrets.CODECOV_TOKEN }}
80+
directory: ${{github.workspace}}/build
81+
files: ${{github.workspace}}/build/coverage.info
82+
fail_ci_if_error: true
83+
verbose: true
84+
# Uploading to Github Action as artifact
85+
- name: Upload Coverage Summary as artifact
86+
uses: actions/upload-artifact@v3
87+
with:
88+
name: Coverage-Summary
89+
path: ${{github.workspace}}/build/coverage_list.txt
90+
retention-days: 5

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "ext/Catch2"]
2+
path = ext/Catch2
3+
url = https://github.com/catchorg/Catch2.git

CMakeLists.txt

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
project(FastANI
3+
VERSION 1.34
4+
DESCRIPTION "Fast computation of whole-genome Average Nucleotide Identity (ANI)."
5+
LANGUAGES CXX)
6+
#
7+
# Main executable
8+
add_executable(FastANI src/cgi/core_genome_identity.cpp src/cgi/main.cpp)
9+
target_include_directories(FastANI PUBLIC "src/")
10+
#
11+
# by default, static linking
12+
option(GSL_SHARED "Build using shared libraries" OFF)
13+
option(BUILD_TESTING "Build tests" ON) # build tests
14+
#
15+
# zlib dependency
16+
find_package(ZLIB 1.1 REQUIRED)
17+
if(${ZLIB_FOUND})
18+
message("Using zlib library v${ZLIB_VERSION_STRING}")
19+
endif(${ZLIB_FOUND})
20+
target_link_libraries(FastANI PUBLIC ZLIB::ZLIB)
21+
#
22+
# openmp dependency
23+
find_package(OpenMP)
24+
if(${OpenMP_CXX_FOUND})
25+
message("Using OpenMP_CXX v${OpenMP_CXX_VERSION}")
26+
target_link_libraries(FastANI PUBLIC ${OpenMP_CXX_LIBRARIES})
27+
target_include_directories(FastANI PUBLIC ${OpenMP_CXX_INCLUDE_DIRS})
28+
target_compile_options(FastANI PUBLIC ${OpenMP_CXX_FLAGS})
29+
else()
30+
message("NOTE: OpenMP not found; Compiling as a single threaded app...")
31+
endif(${OpenMP_CXX_FOUND})
32+
#
33+
# GSL or Boost math
34+
find_package(GSL 1.6)
35+
if(${GSL_FOUND})
36+
message("GSL v${GSL_VERSION} Found: ${GSL_LIBDIR}")
37+
if(${GSL_SHARED})
38+
target_link_libraries(FastANI PUBLIC ${GSL_LIBRARIES})
39+
else()
40+
# GSL_LIBDIR is not documented
41+
target_link_libraries(FastANI PUBLIC
42+
${GSL_LIBDIR}/libgsl.a
43+
${GSL_LIBDIR}/libgslcblas.a)
44+
endif(${GSL_SHARED})
45+
target_include_directories(FastANI PUBLIC ${GSL_INCLUDE_DIRS})
46+
else()
47+
set(Boost_USE_STATIC_LIBS ON) # only find static libs
48+
set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and
49+
set(Boost_USE_RELEASE_LIBS ON) # only find release libs
50+
set(Boost_USE_MULTITHREADED ON)
51+
find_package(Boost 1.45 REQUIRED COMPONENTS math_c99)
52+
target_link_libraries(FastANI PUBLIC ${Boost_MATCH_C99_LIBRARY})
53+
target_include_directories(FastANI PUBLIC ${Boost_INCLUDE_DIRS})
54+
target_compile_definitions(FastANI PUBLIC USE_BOOST=1)
55+
endif(${GSL_FOUND})
56+
#
57+
#
58+
if(${BUILD_TESTING})
59+
add_subdirectory(ext/Catch2)
60+
include(CTest)
61+
include(Catch)
62+
add_executable(FastANITest tests/fastani_tests.cpp src/cgi/core_genome_identity.cpp)
63+
target_include_directories(FastANITest PUBLIC "src/"
64+
${OpenMP_CXX_INCLUDE_DIRS})
65+
target_compile_options(FastANITest PUBLIC
66+
--coverage -g -O0 -fprofile-arcs -ftest-coverage ${OpenMP_CXX_FLAGS})
67+
target_link_libraries(FastANITest PRIVATE
68+
Catch2::Catch2 Catch2::Catch2WithMain
69+
ZLIB::ZLIB GSL::gsl GSL::gslcblas
70+
${OpenMP_CXX_LIBRARIES}
71+
gcov)
72+
catch_discover_tests(FastANITest)
73+
file(COPY data DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
74+
add_custom_target(lcov lcov -c -d .. -o FastANITest.out
75+
COMMAND genhtml -o ../lcov/ FastANITest.out
76+
DEPENDS FastANITest)
77+
add_custom_target(lcov2 lcov -c -d ./ -o FastANITest.info
78+
COMMAND lcov -e FastANITest.info "*/FastANI/src/*/*.cpp" "*/FastANI/src/*/*.hpp" > coverage.info
79+
COMMAND lcov --list coverage.info |tee coverage_list.txt
80+
COMMAND lcov --summary coverage.info |tee coverage_summary.txt
81+
DEPENDS FastANITest)
82+
endif(${BUILD_TESTING})
83+
84+
set(CPACK_GENERATOR "TGZ")
85+
set(CPACK_SOURCE_GENERATOR "TGZ")
86+
set(CPACK_PACKAGE_DIRECTORY ${PROJECT_BINARY_DIR}/package)
87+
88+
set(CPACK_SOURCE_IGNORE_FILES .git/ .github/
89+
.vscode/ .cache/ .mypy_cache/
90+
.idea/ complie_comands.json
91+
lcov/ lcov0/ lcov2/ data/ cmake-build-debug/
92+
_CPack_Packages/ build.sh/ build/ build.clang/
93+
${CMAKE_BINARY_DIR}/ ${PROJECT_BINARY_DIR}/)
94+
95+
include(CPack)

Makefile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ else
1010
CFLAGS += -include src/common/memcpyLink.h
1111
endif
1212

13-
SOURCES=src/cgi/core_genome_identity.cpp
13+
SOURCES=src/cgi/core_genome_identity.cpp src/cgi/main.cpp
1414

1515
all : fastANI
1616

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ FastANI
33
[![Apache 2.0 License](https://img.shields.io/badge/license-Apache%20v2.0-blue.svg)](LICENSE)
44
[![BioConda Install](https://img.shields.io/conda/dn/bioconda/fastani.svg?style=flag&label=BioConda%20install)](https://anaconda.org/bioconda/fastani)
55
[![GitHub Downloads](https://img.shields.io/github/downloads/ParBLiSS/FastANI/total.svg?style=social&logo=github&label=Download)](https://github.com/ParBLiSS/FastANI/releases)
6+
![Build with CMake and Test](https://github.com/ParBLiSS/FastANI/actions/workflows/main.yml/badge.svg)
7+
[![codecov](https://codecov.io/gh/ParBLiSS/FastANI/branch/master/graph/badge.svg?token=B7YFZ56BW2)](https://codecov.io/gh/srirampc/FastANI)
68

79
FastANI is developed for fast alignment-free computation of whole-genome Average Nucleotide Identity (ANI). ANI is defined as mean nucleotide identity of orthologous gene pairs shared between two microbial genomes. FastANI supports pairwise comparison of both complete and draft genome assemblies. Its underlying procedure follows a similar workflow as described by [Goris et al. 2007](http://www.ncbi.nlm.nih.gov/pubmed/17220447). However, it avoids expensive sequence alignments and uses [Mashmap](https://github.com/marbl/MashMap) as its MinHash based sequence mapping engine to compute the orthologous mappings and alignment identity estimates. Based on our experiments with complete and draft genomes, its accuracy is on par with [BLAST-based ANI solver](http://enve-omics.ce.gatech.edu/ani/) and it achieves two to three orders of magnitude speedup. Therefore, it is useful for pairwise ANI computation of large number of genome pairs. More details about its speed, accuracy and potential applications are described here: "[High Throughput ANI Analysis of 90K Prokaryotic Genomes Reveals Clear Species Boundaries](https://doi.org/10.1038/s41467-018-07641-9)".
810

configure.ac

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
AC_INIT(src/cgi/core_genome_identity.cpp)
1+
AC_INIT
2+
AC_CONFIG_SRCDIR([src/cgi/core_genome_identity.cpp])
3+
AC_CONFIG_SRCDIR([src/cgi/main.cpp])
24

35
AC_ARG_WITH(gsl, [ --with-gsl=<path/to/gsl> GNU Scientific Library install dir (default: /usr/local/)])
46
AC_ARG_ENABLE(static-gsl, [ --enable-static-gsl])
@@ -56,4 +58,5 @@ else
5658
AC_SUBST(amcppflags, "-DUSE_BOOST")
5759
fi
5860

59-
AC_OUTPUT(Makefile)
61+
AC_CONFIG_FILES([Makefile])
62+
AC_OUTPUT

0 commit comments

Comments
 (0)