Skip to content

Commit f358a98

Browse files
authored
Merge pull request #5 from jgaffiot/testing
Define some unitary tests with pytest!
2 parents 3cdbe44 + 0efbaa5 commit f358a98

File tree

5 files changed

+152
-77
lines changed

5 files changed

+152
-77
lines changed

README.md

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ of use.
2929
- Vector3: yet another implementation of the 3-dimensional mathematical vector.
3030

3131
## Build
32+
### Layout
3233
The library is built with `cmake` and has been tested with `g++` and `clang`.
3334

3435
The build layout is included in the repository, with the `source`, `build` and
@@ -38,8 +39,31 @@ The installation step is required, because some headers are generated
3839
at the compilation step in the `build/` subdirectories, so all the headers
3940
are only available in one place after installation.
4041

42+
The library contains an optional binding to Python, based on
43+
[Cppyy](https://cppyy.readthedocs.io). The binding will be automatically generated
44+
at the compilation if the optional prerequisites are installed and the Python
45+
virtual environment activated (with `poetry shell`).
46+
47+
### Prerequisites
48+
Required:
49+
50+
- `make`
51+
- `cmake`: >= 3.2
52+
- `gcc`: >= 5 or `clang`: >= 5
53+
54+
Optional:
55+
56+
- `clang`: >= 10
57+
- `libclang-dev`: same as clang
58+
- `python`: >= 3.6
59+
- `poetry`: >= 1.1
60+
61+
then run `poetry install` to install the optional Python packages
62+
63+
### Option
4164
A Makefile is provided at the root to run `cmake` then `make` in a single step,
4265
with the following options:
66+
4367
- `all`: same as `install_release`
4468
- `debug`: same as `install_debug`
4569
- `build_release`: create a `release/` directory in `build/` and run `cmake`
@@ -53,7 +77,7 @@ with the following options:
5377
- `clean_lib_bin`: remove the `install` directory
5478

5579
## Contribute
56-
### Tooling
80+
### Tooling set
5781
A set of formatters and static analysis tools is used to guarantee the homogeneity
5882
of the code and catch mistakes:
5983

@@ -77,7 +101,7 @@ to run `poetry shell` once and for all in the repository root when entering the
77101
An other solution is to use `poetry run git commit ...` (for configuration of an IDE)
78102
for instance.
79103

80-
### Installation
104+
### Tooling installation
81105
- `pre-commit`, as a Python tool, can be installed with:
82106

83107
- `pipx`
@@ -142,7 +166,7 @@ for instance.
142166
All together, on Ubuntu 20.04 or higher, run:
143167

144168
sudo apt install make cmake gcc g++ clang-11 clang-format-11 cppcheck \
145-
python3 python3-pip
169+
libclang-11-dev python3 python3-pip
146170
sudo apt remove --purge python3-virtualenv virtualenv
147171
pip3 install virtualenv pre-commit
148172
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -

source/CMakeLists.txt

Lines changed: 99 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,44 @@ project(tools)
99
set(REPOSITORY_DIR ${PROJECT_SOURCE_DIR}/../)
1010

1111
# ------------------------------------------------------------------------------------ #
12-
# Set version
13-
set(TOOLS_MAJOR_VERSION 1)
14-
set(TOOLS_MINOR_VERSION 0)
15-
set(TOOLS_PATCH_VERSION 0)
12+
# Set version from the git tag
13+
find_package(Git)
14+
if(NOT GIT_FOUND)
15+
message(FATAL_ERROR "Git not found")
16+
endif()
17+
execute_process(
18+
COMMAND "${GIT_EXECUTABLE}" describe --tags
19+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
20+
RESULT_VARIABLE git_result
21+
OUTPUT_VARIABLE git_tag
22+
ERROR_VARIABLE git_error
23+
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE
24+
)
25+
if(NOT git_result EQUAL 0)
26+
message(FATAL_ERROR "Failed to execute Git: ${git_error}")
27+
endif()
28+
if(git_tag MATCHES
29+
"^v([1-9][0-9]*)[.]([0-9]+)([.]([0-9]+))?-?([0-9]+)?(-g([0-9a-f-]+))?$"
30+
)
31+
set(TOOLS_MAJOR_VERSION "${CMAKE_MATCH_1}")
32+
set(TOOLS_MINOR_VERSION "${CMAKE_MATCH_2}")
33+
set(TOOLS_PATCH_VERSION "${CMAKE_MATCH_4}")
34+
set(NB_COMMIT "${CMAKE_MATCH_5}")
35+
set(GIT_HASH "${CMAKE_MATCH_7}")
36+
else()
37+
message(FATAL_ERROR "Git tag isn't valid semantic version: [${git_tag}]")
38+
endif()
39+
40+
if("${TOOLS_PATCH_VERSION}" STREQUAL "")
41+
set(TOOLS_PATCH_VERSION 0)
42+
endif()
1643
set(TOOLS_VERSION ${TOOLS_MAJOR_VERSION}.${TOOLS_MINOR_VERSION}.${TOOLS_PATCH_VERSION})
44+
if(NOT "${GIT_HASH}" EQUAL "")
45+
message(STATUS "Tools base version: ${TOOLS_VERSION}")
46+
message(STATUS "Commit: ${GIT_HASH}, ${NB_COMMIT} commits above latest version")
47+
else()
48+
message(STATUS "Tools version: ${TOOLS_VERSION}")
49+
endif()
1750

1851
# ------------------------------------------------------------------------------------ #
1952
# Set compilation version
@@ -105,26 +138,6 @@ set(CMAKE_CXX_FLAGS
105138
"${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Wno-long-long -Wno-vla"
106139
)
107140

108-
# ------------------------------------------------------------------------------------ #
109-
# Get the Cppyy and clang package
110-
execute_process(
111-
COMMAND bash -c "poetry show cppyy-backend | cut -d: -f2 | sed -n 2p"
112-
OUTPUT_VARIABLE CPPYY_BACKEND_VERSION
113-
OUTPUT_STRIP_TRAILING_WHITESPACE
114-
)
115-
message(STATUS "CPPYY_BACKEND_VERSION: ${CPPYY_BACKEND_VERSION}")
116-
117-
if(${CPPYY_BACKEND_VERSION} LESS_EQUAL 1.14.5)
118-
# Until version 1.14.5, use corrected cmake scripts to find Cppyy and libClang
119-
list(APPEND CMAKE_MODULE_PATH ${REPOSITORY_DIR}/cmake)
120-
endif()
121-
execute_process(
122-
COMMAND cling-config --cmake
123-
OUTPUT_VARIABLE CPPYY_MODULE_PATH
124-
OUTPUT_STRIP_TRAILING_WHITESPACE)
125-
list(APPEND CMAKE_MODULE_PATH ${CPPYY_MODULE_PATH})
126-
find_package(Cppyy REQUIRED)
127-
128141
# ------------------------------------------------------------------------------------ #
129142
# Set the headers directory
130143
include_directories(${PROJECT_SOURCE_DIR}/inc ${PROJECT_BINARY_DIR})
@@ -159,32 +172,6 @@ install(
159172
)
160173
set(TOOLS_LIB ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libTools.so)
161174

162-
# ------------------------------------------------------------------------------------ #
163-
# Target Cppyy binding
164-
message(STATUS "INSTALL_INCLUDE_DIR: ${INSTALL_INCLUDE_DIR}")
165-
# Generating the library
166-
cppyy_add_bindings(
167-
"PyTools"
168-
"${TOOLS_VERSION}"
169-
"jgaffiot"
170-
"j.gaffiot@laposte.net"
171-
LICENSE "LGPL-3.0-or-later"
172-
LICENSE_FILE ${REPOSITORY_DIR}/LICENSE
173-
README_FILE ${REPOSITORY_DIR}/README.md
174-
LANGUAGE_STANDARD "17"
175-
NAMESPACES "tools"
176-
LINKDEFS ${PROJECT_SOURCE_DIR}/Linkdef.h
177-
INCLUDE_DIRS ${PROJECT_BINARY_DIR}/
178-
LINK_LIBRARIES ${TOOLS_LIB}
179-
H_DIRS ${PROJECT_SOURCE_DIR}/inc/
180-
H_FILES ${TOOLS_INC}
181-
)
182-
add_dependencies(PyToolsCppyy Tools)
183-
install(CODE "message(STATUS \"Attempting pip install\" ${PY_WHEEL_FILE})"
184-
CODE "execute_process(COMMAND poetry run pip install --force-reinstall
185-
${PY_WHEEL_FILE})"
186-
)
187-
188175
# ------------------------------------------------------------------------------------ #
189176
# Create the package: add all targets to the build-tree export set
190177
export(TARGETS Tools FILE "${PROJECT_BINARY_DIR}/ToolsTargets.cmake")
@@ -222,3 +209,65 @@ install(
222209
DESTINATION "${INSTALL_CMAKE_DIR}"
223210
COMPONENT dev
224211
)
212+
213+
# ------------------------------------------------------------------------------------ #
214+
# Get the Cppyy and clang package
215+
execute_process(
216+
COMMAND bash -c "poetry show cppyy-backend | cut -d: -f2 | sed -n 2p"
217+
OUTPUT_VARIABLE CPPYY_BACKEND_VERSION
218+
OUTPUT_STRIP_TRAILING_WHITESPACE
219+
)
220+
message(STATUS "CPPYY_BACKEND_VERSION: ${CPPYY_BACKEND_VERSION}")
221+
222+
if(${CPPYY_BACKEND_VERSION} LESS_EQUAL 1.14.5)
223+
# Until version 1.14.5, use corrected cmake scripts to find Cppyy and libClang
224+
list(APPEND CMAKE_MODULE_PATH ${REPOSITORY_DIR}/cmake)
225+
endif()
226+
execute_process(
227+
COMMAND cling-config --cmake
228+
OUTPUT_VARIABLE CPPYY_MODULE_PATH
229+
ERROR_VARIABLE CPPYY_MODULE_ERROR
230+
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE
231+
)
232+
if (NOT CPPYY_MODULE_ERROR EQUAL 0)
233+
message(STATUS "Cppyy has not been installed, skipping the Python binding")
234+
return()
235+
endif()
236+
list(APPEND CMAKE_MODULE_PATH ${CPPYY_MODULE_PATH})
237+
find_package(Cppyy REQUIRED)
238+
239+
# ------------------------------------------------------------------------------------ #
240+
# Target Cppyy binding
241+
message(STATUS "INSTALL_INCLUDE_DIR: ${INSTALL_INCLUDE_DIR}")
242+
# Generating the library
243+
cppyy_add_bindings(
244+
"PyTools"
245+
"${TOOLS_VERSION}"
246+
"jgaffiot"
247+
"j.gaffiot@laposte.net"
248+
LICENSE
249+
"LGPL-3.0-or-later"
250+
LICENSE_FILE
251+
${REPOSITORY_DIR}/LICENSE
252+
README_FILE
253+
${REPOSITORY_DIR}/README.md
254+
LANGUAGE_STANDARD
255+
"17"
256+
NAMESPACES
257+
"tools"
258+
LINKDEFS
259+
${PROJECT_SOURCE_DIR}/Linkdef.h
260+
INCLUDE_DIRS
261+
${PROJECT_BINARY_DIR}/
262+
LINK_LIBRARIES
263+
${TOOLS_LIB}
264+
H_DIRS
265+
${PROJECT_SOURCE_DIR}/inc/
266+
H_FILES
267+
${TOOLS_INC}
268+
)
269+
add_dependencies(PyToolsCppyy Tools)
270+
install(CODE "message(STATUS \"Attempting pip install\" ${PY_WHEEL_FILE})"
271+
CODE "execute_process(COMMAND poetry run pip install --force-reinstall
272+
${PY_WHEEL_FILE})"
273+
)

source/inc/Rand.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ public:
140140
Z = 2
141141
};
142142

143-
inline static auto GetSeed() { return theSeed; }
144-
inline static auto GetGenerator() { return theGenerator; }
143+
inline static auto GetSeed() -> decltype(theSeed) { return theSeed; }
144+
inline static auto GetGenerator() -> decltype(theGenerator) { return theGenerator; }
145145

146146
inline static double Uniform() { return uniform_real_distro(theGenerator); }
147147
inline static double Uniform(double max) {

source/inc/Regex.hh

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,39 +44,37 @@ public:
4444
inline int Nb() const { return theTokens.size(); }
4545
inline int NbMatch() const { return theTokens.size(); }
4646
inline int GetNbMatch() const { return theTokens.size(); }
47-
inline const std::string& at(uint i) const { return theTokens.at(i); } // test on i
48-
inline const std::string& operator()(uint i) const {
49-
return theTokens.at(i);
50-
} // test on i
47+
inline const std::string& at(uint i) const { return theTokens.at(i); }
48+
inline const std::string& operator()(uint i) const { return theTokens.at(i); }
5149
inline const std::string& operator[](uint i) const {
5250
return theTokens[i];
5351
} // no test
5452

5553
// integrated cast to all numeric types
56-
inline auto stoi(uint i) const {
54+
inline auto stoi(uint i) -> decltype(std::stoi(std::string())) const {
5755
return std::stoi(theTokens.at(i), nullptr);
58-
} // test on i
59-
inline auto stol(uint i) const {
56+
}
57+
inline auto stol(uint i) -> decltype(std::stol(std::string())) const {
6058
return std::stol(theTokens.at(i), nullptr);
61-
} // test on i
62-
inline auto stoul(uint i) const {
59+
}
60+
inline auto stoul(uint i) -> decltype(std::stoul(std::string())) const {
6361
return std::stoul(theTokens.at(i), nullptr);
64-
} // test on i
65-
inline auto stoll(uint i) const {
62+
}
63+
inline auto stoll(uint i) -> decltype(std::stoll(std::string())) const {
6664
return std::stoll(theTokens.at(i), nullptr);
67-
} // test on i
68-
inline auto stoull(uint i) const {
65+
}
66+
inline auto stoull(uint i) -> decltype(std::stoull(std::string())) const {
6967
return std::stoull(theTokens.at(i), nullptr);
70-
} // test on i
71-
inline auto stof(uint i) const {
68+
}
69+
inline auto stof(uint i) -> decltype(std::stof(std::string())) const {
7270
return std::stof(theTokens.at(i), nullptr);
73-
} // test on i
74-
inline auto stod(uint i) const {
71+
}
72+
inline auto stod(uint i) -> decltype(std::stod(std::string())) const {
7573
return std::stod(theTokens.at(i), nullptr);
76-
} // test on i
77-
inline auto stold(uint i) const {
74+
}
75+
inline auto stold(uint i) -> decltype(std::stold(std::string())) const {
7876
return std::stold(theTokens.at(i), nullptr);
79-
} // test on i
77+
}
8078
inline const std::vector<std::string>& GetTokens() const { return theTokens; }
8179
inline const std::vector<std::string>& GetSplitResults() const { return theTokens; }
8280

source/inc/String.hh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef STRING_HH
1010
#define STRING_HH 1
1111

12+
#include <cstring>
1213
#include <sstream>
1314
#include <string>
1415
#include <utility>
@@ -33,14 +34,17 @@ template<typename... Args>
3334
inline const char* cat(Args&&... args) {
3435
std::ostringstream oss;
3536
detail_string::PushToStream(oss, std::forward<Args>(args)...);
36-
return oss.str().c_str();
37+
size_t len = std::strlen(oss.str().c_str()) + 1;
38+
char* new_str = new char[len];
39+
std::snprintf(new_str, len, "%s", oss.str().c_str());
40+
return new_str;
3741
}
3842

3943
template<typename... Args>
4044
inline std::string scat(Args&&... args) {
4145
std::ostringstream oss;
4246
detail_string::PushToStream(oss, std::forward<Args>(args)...);
43-
return std::move(oss.str());
47+
return oss.str();
4448
}
4549

4650
// stuff for emulation of switch with strings

0 commit comments

Comments
 (0)