Merge pull request #252 Run Valgrind memcheck on Travis CI from SRombauts/travis-valgrind

Run Valgrind memcheck on Travis CI
This commit is contained in:
Sébastien Rombauts 2020-01-04 19:20:40 +01:00 committed by GitHub
commit d4bafc0e68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 188 additions and 134 deletions

View File

@ -11,4 +11,4 @@ end_of_line = lf
# 2 space indentation for CI configuration
[*.yml]
indent_style = space
indent_size = 4
indent_size = 2

View File

@ -16,25 +16,38 @@ matrix:
# GCC on Linux
##########################################################################
# GCC Debug build with GCov for coverage build
- dist: bionic
env:
- cc=gcc
- cxx=g++
- CXXFLAGS=""
- cc=gcc cxx=g++
- BUILD_TYPE=Debug
- ASAN=ON GCOV=ON
- COVERALLS=true
# GCC Debug build with Valgrind instead of Address Sanitizer
- dist: bionic
env:
- cc=gcc cxx=g++
- BUILD_TYPE=Debug
- VALGRIND=true
# GCC Release build
- dist: bionic
env:
- cc=gcc cxx=g++
- BUILD_TYPE=Release
- dist: xenial
env:
- cc=gcc
- cxx=g++
- CXXFLAGS=""
- cc=gcc cxx=g++
- BUILD_TYPE=Debug
- ASAN=ON
- dist: trusty
env:
- cc=gcc
- cxx=g++
- CXXFLAGS=""
- cc=gcc cxx=g++
- BUILD_TYPE=Debug
- ASAN=ON
##########################################################################
# Clang on Linux
@ -42,21 +55,21 @@ matrix:
- dist: bionic
env:
- cc=clang
- cxx=clang++
- CXXFLAGS=""
- cc=clang cxx=clang++
- BUILD_TYPE=Debug
- ASAN=ON
- dist: xenial
env:
- cc=clang
- cxx=clang++
- CXXFLAGS=""
- cc=clang cxx=clang++
- BUILD_TYPE=Debug
- ASAN=ON
- dist: trusty
env:
- cc=clang
- cxx=clang++
- CXXFLAGS=""
- cc=clang cxx=clang++
- BUILD_TYPE=Debug
- ASAN=ON
##########################################################################
# Clang on OSX
@ -65,17 +78,17 @@ matrix:
# Latest XCode
- os: osx
env:
- cc=clang
- cxx=clang++
- CXXFLAGS=""
- cc=clang cxx=clang++
- BUILD_TYPE=Debug
- ASAN=ON
# XCode 8.3
- os: osx
osx_image: xcode8.3
env:
- cc=clang
- cxx=clang++
- CXXFLAGS=""
- cc=clang cxx=clang++
- BUILD_TYPE=Debug
- ASAN=ON
before_install:
# Set the compiler environment variables properly
@ -83,6 +96,7 @@ before_install:
- export CXX=${cxx}
- ${CC} --version
- ${CXX} --version
- if [[ "$VALGRIND" == "true" ]]; then sudo apt-get install -qq valgrind ; fi
install:
# coveralls test coverage:
@ -92,13 +106,15 @@ install:
before_script:
- mkdir build
- cd build
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=Debug -DSQLITECPP_USE_ASAN=ON -DSQLITECPP_USE_GCOV=ON -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSQLITECPP_USE_ASAN=$ASAN -DSQLITECPP_USE_GCOV=$GCOV -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
# build examples, and run tests (ie make & make test)
script:
- cmake --build .
- export ASAN_OPTIONS=verbosity=1:debug=1
- ctest --verbose --output-on-failure
- if [[ "$VALGRIND" == "true" ]]; then valgrind --leak-check=full --error-exitcode=1 ./SQLiteCpp_example1 ; fi
- if [[ "$VALGRIND" == "true" ]]; then valgrind --leak-check=full --error-exitcode=1 ./SQLiteCpp_tests ; fi
# generate and publish GCov coveralls results
after_success:

View File

@ -2,12 +2,12 @@ Mar 30 2012
- Start of a new thin C++ SQLite wrapper
Apr 2 2012
- The wrapper is functionnal
- The wrapper is functional
- Added documentation and examples
- Publication on GitHub
Version 0.1.0 - Apr 4 2012
- Added a Database::exec() methode to execute simple SQL statement
- Added a Database::exec() method to execute simple SQL statement
- Added a version number like in sqlite3.h, starting with 0.1.0
Version 0.2.0 - Apr 11 2012
@ -75,7 +75,7 @@ Version 1.3.0 - November 1 2015
- Added Backup class
Version 1.3.1 - February 10 2016
- Swith Linux/Mac build to the provided SQLite3 C library
- Switch Linux/Mac build to the provided SQLite3 C library
- Update SQLite3 from 3.8.8.3 to latest 3.10.2 (2016-01-20)
- Remove warnings
- Remove biicode support (defunct service, servers will shutdown the 16th of February 2016)
@ -157,9 +157,11 @@ Version 2.5.0 - December 31 2019
- #251 Added example for getHeaderInfo()
Version 3.0.0 - January 1 2020
- C++11 minimum
- C++11 is now required
- CMake 3.1 minimum
- Visual Studio 2015 minimum
- Googletest 1.10
- Update Googletest to latest release 1.10
- Add Github Actions continuous integration solution
- Add Valgrind memcheck tool to Travis CI
- Remove Statement::isOk() deprecated in 2.2.0 when renamed to Statement::hasRow()
- Replace Database::backup() "C" implementation by calling the Backup class

View File

@ -43,14 +43,14 @@ else (MSVC)
set(CPPLINT_ARG_OUTPUT "--output=eclipse")
set(CPPCHECK_ARG_TEMPLATE "--template=gcc")
# Useful compile flags and extra warnings
add_compile_options(-fstack-protector -Wall -Wextra -Wpedantic -Wno-long-long -Wswitch-enum -Wshadow -Winline)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++0x-compat") # C++ only
add_compile_options(-fstack-protector)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Wswitch-enum -Wshadow -Wno-long-long") # C++ only, don't bother with sqlite3
if (CMAKE_COMPILER_IS_GNUCXX)
# GCC flags
option(SQLITECPP_USE_GCOV "USE GCov instrumentation." OFF)
if (SQLITECPP_USE_GCOV)
message (STATUS "Using GCov instrumentation")
add_compile_options (-coverage) # NOTE -fkeep-inline-functions would be usefull but not working with current google test and gcc 4.8
add_compile_options (-coverage) # NOTE -fkeep-inline-functions would be useful but not working with current Google test and GCC 4.8
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
endif ()
endif (CMAKE_COMPILER_IS_GNUCXX)
@ -83,7 +83,7 @@ endif ()
## Build the C++ Wrapper ##
# adding a new file require explicittly modifing the CMakeLists.txt
# adding a new file require explicitly modifying the CMakeLists.txt
# so that CMake knows that it should rebuild the project (it is best practice)
# list of sources files of the library
@ -307,7 +307,7 @@ if (SQLITECPP_BUILD_EXAMPLES)
# add the basic example executable
add_executable(SQLiteCpp_example1 ${SQLITECPP_EXAMPLES})
target_link_libraries(SQLiteCpp_example1 SQLiteCpp sqlite3)
# Link target with pthread and dl for linux
# Link target with pthread and dl for Linux
if (UNIX)
target_link_libraries(SQLiteCpp_example1 pthread)
if (NOT APPLE)
@ -329,12 +329,12 @@ if (SQLITECPP_BUILD_TESTS)
if (GTEST_FOUND)
target_link_libraries(SQLiteCpp_tests GTest::GTest GTest::Main SQLiteCpp sqlite3)
else (GTEST_FOUND)
# deactivate some warnings for compiling the gtest library
# deactivate some warnings for compiling the googletest library
if (NOT MSVC)
add_compile_options(-Wno-variadic-macros -Wno-long-long -Wno-switch-enum -Wno-float-equal -Wno-conversion-null -Wno-switch-default -Wno-pedantic)
endif (NOT MSVC)
# add the subdirectory containing the CMakeLists.txt for the gtest library
# add the subdirectory containing the CMakeLists.txt for the googletest library
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/googletest/CMakeLists.txt")
message(FATAL_ERROR "Missing 'googletest' submodule! Either use 'git submodule init' and 'git submodule update' to get googletest according to the README, or deactivate unit tests with -DSQLITECPP_BUILD_TESTS=OFF")
endif ()

View File

@ -72,6 +72,7 @@ Developments and tests are done under the following OSs:
- Windows 10, and Windows Server 2012 R2 & Windows Server 2016 (AppVeyor)
- OS X 10.11 (Travis CI)
- Github Actions
- Valgrind memcheck tool
And the following IDEs/Compilers
- GCC 4.8.4, 5.3.0 and 7.1.1 (C++11, C++14, C++17)

View File

@ -1,5 +1,3 @@
Switch to C++11 for v3.0.0
Add a Tutorial for SQLite newbies
Add a real example in the form of a small interactive console application

View File

@ -4,7 +4,7 @@
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
# exit on firts error
# exit on first error
set -e
mkdir -p build

View File

@ -477,6 +477,12 @@ public:
*/
static Header getHeaderInfo(const std::string& aFilename);
// Parse SQLite header data from a database file.
Header getHeaderInfo()
{
return getHeaderInfo(mFilename);
}
/**
* @brief BackupType for the backup() method
*/

View File

@ -287,28 +287,32 @@ Header Database::getHeaderInfo(const std::string& aFilename)
if (aFilename.empty())
{
throw SQLite::Exception("Could not open database, the aFilename parameter was empty.");
throw SQLite::Exception("Filename parameter is empty");
}
{
std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary);
if (fileBuffer.is_open())
{
fileBuffer.seekg(0, std::ios::beg);
fileBuffer.read(pBuf, 100);
fileBuffer.close();
strncpy(pHeaderStr, pBuf, 16);
if (fileBuffer.gcount() < 100)
{
throw SQLite::Exception("File " + aFilename + " is too short");
}
}
else
{
throw SQLite::Exception("Error opening file: " + aFilename);
throw SQLite::Exception("Error opening file " + aFilename);
}
}
// If the "magic string" can't be found then header is invalid, corrupt or unreadable
strncpy(pHeaderStr, pBuf, 16);
if (!strncmp(pHeaderStr, "SQLite format 3", 15) == 0)
{
throw SQLite::Exception("Invalid or encrypted SQLite header");
throw SQLite::Exception("Invalid or encrypted SQLite header in file " + aFilename);
}
h.pageSizeBytes = (buf[16] << 8) | buf[17];

View File

@ -24,6 +24,7 @@
TEST(Backup, initException)
{
remove("backup_test.db3");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
@ -32,6 +33,7 @@ TEST(Backup, initException)
EXPECT_THROW(SQLite::Backup backup(srcDB, "main", srcDB, "main"), SQLite::Exception);
const std::string name("main");
EXPECT_THROW(SQLite::Backup backup(srcDB, name, srcDB, name), SQLite::Exception);
}
remove("backup_test.db3");
}
@ -39,6 +41,7 @@ TEST(Backup, executeStepOne)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
@ -64,6 +67,7 @@ TEST(Backup, executeStepOne)
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(2, query.getColumn(0).getInt());
EXPECT_STREQ("second", query.getColumn(1));
}
remove("backup_test.db3");
remove("backup_test.db3.backup");
}
@ -72,6 +76,7 @@ TEST(Backup, executeStepAll)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
@ -93,6 +98,7 @@ TEST(Backup, executeStepAll)
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(2, query.getColumn(0).getInt());
EXPECT_STREQ("second", query.getColumn(1));
}
remove("backup_test.db3");
remove("backup_test.db3.backup");
}
@ -101,6 +107,7 @@ TEST(Backup, executeStepException)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
@ -114,6 +121,7 @@ TEST(Backup, executeStepException)
SQLite::Backup backup(destDB, srcDB);
EXPECT_THROW(backup.executeStep(), SQLite::Exception);
}
}
remove("backup_test.db3");
remove("backup_test.db3.backup");
}

View File

@ -140,15 +140,16 @@ TEST(Database, backup)
EXPECT_TRUE(db.tableExists("test"));
// Export the data into a file
remove("backup");
EXPECT_NO_THROW(db.backup("backup", SQLite::Database::Save));
remove("backup.db3");
EXPECT_NO_THROW(db.backup("backup.db3", SQLite::Database::Save));
// Trash the table
db.exec("DROP TABLE test;");
EXPECT_FALSE(db.tableExists("test"));
// Import the data back from the file
EXPECT_NO_THROW(db.backup("backup", SQLite::Database::Load));
EXPECT_NO_THROW(db.backup("backup.db3", SQLite::Database::Load));
remove("backup.db3");
EXPECT_TRUE(db.tableExists("test"));
}
@ -359,23 +360,41 @@ TEST(Database, getHeaderInfo)
{
remove("test.db3");
{
//Call without passing a database file name
// Call without passing a database file name
EXPECT_THROW(SQLite::Database::getHeaderInfo(""),SQLite::Exception);
//Call with a non existant database
// Call with a non-existent database
EXPECT_THROW(SQLite::Database::getHeaderInfo("test.db3"), SQLite::Exception);
//Simulate a corrupt header by writing garbage to a file
unsigned char badData[100];
char* pBadData = reinterpret_cast<char*>(&badData[0]);
// Simulate an incomplete header by writing garbage to a file
{
const unsigned char badData[] = "garbage...";
const char* pBadData = reinterpret_cast<const char*>(&badData[0]);
remove("short.db3");
std::ofstream corruptDb;
corruptDb.open("corrupt.db3", std::ios::app | std::ios::binary);
corruptDb.write(pBadData, 100);
corruptDb.open("short.db3", std::ios::app | std::ios::binary);
corruptDb.write(pBadData, sizeof(badData));
corruptDb.close();
EXPECT_THROW(SQLite::Database::getHeaderInfo("corrupt.db3"), SQLite::Exception);
EXPECT_THROW(SQLite::Database::getHeaderInfo("short.db3"), SQLite::Exception);
remove("short.db3");
}
// Simulate a corrupt header by writing garbage to a file
{
const unsigned char badData[100] = "garbage...";
const char* pBadData = reinterpret_cast<const char*>(&badData[0]);
remove("corrupt.db3");
std::ofstream corruptDb;
corruptDb.open("corrupt.db3", std::ios::app | std::ios::binary);
corruptDb.write(pBadData, sizeof(badData));
corruptDb.close();
EXPECT_THROW(SQLite::Database::getHeaderInfo("corrupt.db3"), SQLite::Exception);
remove("corrupt.db3");
}
// Create a new database
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
@ -388,7 +407,7 @@ TEST(Database, getHeaderInfo)
// Parse header fields from test database
SQLite::Header h = SQLite::Database::getHeaderInfo("test.db3");
//Test header values expliticly set via PRAGMA statements
//Test header values explicitly set via PRAGMA statements
EXPECT_EQ(h.userVersion, 12345);
EXPECT_EQ(h.applicationId, 2468);