diff --git a/.travis.sh b/.travis.sh new file mode 100644 index 0000000..86f6727 --- /dev/null +++ b/.travis.sh @@ -0,0 +1,32 @@ +#!/bin/bash +function generate() { + OPTIONS="" + + if [ "$ASAN" = "ON" ] ; then + OPTIONS="$OPTIONS -DCPPCORE_ASAN=ON" + else + OPTIONS="$OPTIONS -DCPPCORE_ASAN=OFF" + fi + + if [ "$UBSAN" = "ON" ] ; then + OPTIONS="$OPTIONS -DCPPCORE_UBSAN=ON" + else + OPTIONS="$OPTIONS -DCPPCORE_UBSAN=OFF" + fi + + cd build + cmake -G "Unix Makefiles" $OPTIONS +} + +if [ "$TRAVIS_OS_NAME" = "linux" ]; then + if [ "$ANALYZE" = "ON" ] ; then + if [ "$CC" = "clang" ]; then + cd build + scan-build cmake -G "Unix Makefiles" + scan-build --status-bugs make -j4 + fi + else + generate \ + && make -j4 && cd bin && ./cppcore_unittest + fi +fi diff --git a/.travis.yml b/.travis.yml index 2289b6c..02de489 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ before_install: - sudo apt-get install cmake os: -# - windows - linux language: @@ -13,8 +12,26 @@ language: compiler: - gcc - clang -script: - - cd build && cmake -G "Unix Makefiles" && make -j4 && cd bin && ./cppcore_unittest - + +matrix: + include: + - os: linux + compiler: clang + env: ASAN=ON + - os: linux + compiler: clang + env: ANALYZE=ON + - os: linux + compiler: clang + env: UBSAN=ON + - os: linux + compiler: gcc + - os: linux + compiler: gcc + env: ANALYZE=ON +before_script: + - cd build && cmake -G "Unix Makefiles" && cd .. +script: + - . ./.travis.sh diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 2b89b6f..c2da8bf 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -10,7 +10,18 @@ if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX ) find_package(Threads) endif() -option( BUILD_UNITTESTS "Build unit tests." ON ) +option( BUILD_UNITTESTS + "Build unit tests." + ON +) +option( CPPCORE_ASAN + "Enable AddressSanitizer." + OFF +) +option( CPPCORE_UBSAN + "Enable Undefined Behavior sanitizer." + OFF +) add_definitions( -DCPPCORE_BUILD ) add_definitions( -D_VARIADIC_MAX=10 ) @@ -45,6 +56,18 @@ elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11") endif() +IF (ASSIMP_ASAN) + MESSAGE(STATUS "AddressSanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +ENDIF() + +IF (ASSIMP_UBSAN) + MESSAGE(STATUS "Undefined Behavior sanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") +ENDIF() + SET ( cppcore_src ../code/cppcore.cpp ../include/cppcore/CPPCoreCommon.h diff --git a/include/cppcore/Memory/TPoolAllocator.h b/include/cppcore/Memory/TPoolAllocator.h index 0876b86..a28ca42 100644 --- a/include/cppcore/Memory/TPoolAllocator.h +++ b/include/cppcore/Memory/TPoolAllocator.h @@ -86,26 +86,39 @@ class TPoolAllocator { CPPCORE_NONE_COPYING(Pool) }; + Pool *getFreePool() { + Pool *current(m_freeList); + if (nullptr != m_freeList) { + m_freeList = m_freeList->m_next; + } + return current; + } + Pool *m_first; Pool *m_current; + Pool *m_freeList; size_t m_capacity; }; template inline TPoolAllocator::TPoolAllocator() -: m_first(nullptr) -, m_current(nullptr) -, m_capacity(0L) { +: m_first( nullptr ) +, m_current( nullptr ) +, m_freeList( nullptr ) +, m_capacity( 0L ) { // empty } template inline TPoolAllocator::TPoolAllocator(size_t numItems) -: m_first(nullptr) -, m_current(nullptr) { +: m_first( nullptr ) +, m_current( nullptr ) +, m_freeList( nullptr ) +, m_capacity(0L) { m_first = new Pool(numItems); + m_capacity += numItems; m_current = m_first; } @@ -139,7 +152,13 @@ void TPoolAllocator::release() { return; } - m_current->m_currentIdx = 0; + Pool *current(m_first); + while(nullptr != current ) { + current->m_currentIdx = 0; + current = current->m_next; + } + m_freeList = m_first->m_next; + m_current = m_first; } template @@ -170,22 +189,19 @@ void TPoolAllocator::clear() { delete current; } m_current = nullptr; + m_freeList = nullptr; } template inline size_t TPoolAllocator::capacity() const { - if (nullptr == m_current) { - return 0L; - } - - return m_current->m_poolsize; + return m_capacity; } template inline size_t TPoolAllocator::reservedMem() const { - return m_capacity; + return m_capacity * sizeof(T); } template @@ -219,11 +235,16 @@ void TPoolAllocator::resize(size_t growSize) { if (nullptr == m_first) { m_first = new Pool(growSize, nullptr); m_current = m_first; + m_capacity += m_current->m_poolsize; } else { - m_current->m_next = new Pool(growSize, nullptr); + Pool *pool = getFreePool(); + if (nullptr == pool) { + pool = new Pool(growSize, nullptr); + m_capacity += growSize; + } + m_current->m_next = pool; m_current = m_current->m_next; } - m_capacity += m_current->m_poolsize; } } // Namespace CPPCore diff --git a/test/container/TArrayTest.cpp b/test/container/TArrayTest.cpp index 468012c..e45a6c8 100644 --- a/test/container/TArrayTest.cpp +++ b/test/container/TArrayTest.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------------------------------------- The MIT License (MIT) -Copyright (c) 2014-2016 Kim Kulling +Copyright (c) 2014-2019 Kim Kulling Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -158,12 +158,12 @@ TEST_F( TArrayTest, removeTest) { TEST_F( TArrayTest, removeItTest) { TArray arrayInstance; arrayInstance.add( 1.0f ); - EXPECT_EQ( 1, arrayInstance.size() ); + EXPECT_EQ( 1u, arrayInstance.size() ); TArray::Iterator it = arrayInstance.find( 1.0f ); EXPECT_NE( arrayInstance.end(), it ); arrayInstance.remove( it ); - EXPECT_EQ( 0, arrayInstance.size() ); + EXPECT_EQ( 0u, arrayInstance.size() ); } TEST_F( TArrayTest, removeBackTest) { @@ -171,16 +171,16 @@ TEST_F( TArrayTest, removeBackTest) { createArray( ArrayData, ArraySize, arrayInstance ); arrayInstance.removeBack(); - EXPECT_EQ( 3, arrayInstance.size() ); + EXPECT_EQ( 3u, arrayInstance.size() ); EXPECT_EQ( 2.0f, arrayInstance[ 2 ] ); } TEST_F( TArrayTest, resizeTest ) { TArray arrayInstance; - EXPECT_EQ( 0, arrayInstance.size() ); + EXPECT_EQ( 0u, arrayInstance.size() ); arrayInstance.resize( 5 ); - EXPECT_EQ( 5, arrayInstance.size() ); + EXPECT_EQ( 5u, arrayInstance.size() ); } TEST_F( TArrayTest, moveTest ) { @@ -193,22 +193,23 @@ TEST_F( TArrayTest, moveTest ) { TEST_F( TArrayTest, reserveTest ) { TArray arrayInstance; - EXPECT_EQ( 0, arrayInstance.capacity() ); + EXPECT_EQ( 0u, arrayInstance.capacity() ); arrayInstance.reserve( 5 ); - EXPECT_EQ( 5, arrayInstance.capacity() ); + EXPECT_EQ( 5u, arrayInstance.capacity() ); - arrayInstance.reserve( 2000 ); - EXPECT_EQ( 2000, arrayInstance.capacity() ); + static const size_t NewSize = 2000; + arrayInstance.reserve(NewSize); + EXPECT_EQ( NewSize, arrayInstance.capacity() ); } TEST_F( TArrayTest, resize_with_init_Test ) { TArray arrayInstance; - EXPECT_EQ( 0, arrayInstance.capacity() ); + EXPECT_EQ( 0u, arrayInstance.capacity() ); arrayInstance.resize( 10, 1.0f ); - EXPECT_EQ( 10, arrayInstance.size() ); - for ( size_t i = 0; i < 10; i++ ) { + EXPECT_EQ( 10u, arrayInstance.size() ); + for ( size_t i = 0; i < 10; ++i ) { EXPECT_FLOAT_EQ( 1.0f, arrayInstance[ i ] ); } } @@ -230,7 +231,7 @@ TEST_F( TArrayTest, preIncIterateTest ) { bool ok = true; try { - size_t i=0; + size_t i( 0 ); for( TArray::Iterator it = arrayInstance.begin( ); it != arrayInstance.end( ); ++it ) { float tmp = *it; EXPECT_EQ( tmp, ArrayData[ i ] ); @@ -248,7 +249,7 @@ TEST_F( TArrayTest, postIncIterateTest ) { bool ok = true; try { - size_t i=0; + size_t i(0); for( TArray::Iterator it = arrayInstance.begin( ); it != arrayInstance.end( ); it++ ) { float tmp = *it; EXPECT_EQ( tmp, ArrayData[ i ] ); @@ -266,7 +267,7 @@ TEST_F( TArrayTest, findTest ) { arrayInstance.add( 1.0f ); arrayInstance.add( 2.0f ); arrayInstance.add( 3.0f ); - EXPECT_EQ( 4, arrayInstance.size() ); + EXPECT_EQ( 4u, arrayInstance.size() ); TArray::Iterator it = arrayInstance.find( 1.0f ); EXPECT_NE( it, arrayInstance.end() ); @@ -311,4 +312,3 @@ TEST_F( TArrayTest, bug_AddHeapCorruptTest ) { arrayInstance.add( ( float ) i ); } } - diff --git a/test/container/TListTest.cpp b/test/container/TListTest.cpp index d8d6440..5848207 100644 --- a/test/container/TListTest.cpp +++ b/test/container/TListTest.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------------------------------------- The MIT License (MIT) -Copyright (c) 2014-2016 Kim Kulling +Copyright (c) 2014-2019 Kim Kulling Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -40,25 +40,23 @@ using namespace CPPCore; //------------------------------------------------------------------------------------------------- class TListTest : public testing::Test { protected: - void createList( size_t numEntries, TList &rDataList, std::vector &rValues ) { - rValues.resize( 0 ); - rDataList.clear(); + void createList( size_t numEntries, TList &dataList, std::vector &values ) { + values.resize( 0 ); + dataList.clear(); for( size_t i = 0; i listTest; EXPECT_TRUE( listTest.isEmpty() ); EXPECT_EQ( 0u, listTest.size() ); } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, addBackTest) { TList listTest; listTest.addBack( 1.0f ); @@ -69,7 +67,6 @@ TEST_F( TListTest, addBackTest) { EXPECT_TRUE( !listTest.isEmpty() ); } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, addFrontTest) { TList listTest; listTest.addFront( 1.0f ); @@ -80,7 +77,6 @@ TEST_F( TListTest, addFrontTest) { EXPECT_TRUE( !listTest.isEmpty() ); } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, copyTest ) { TList listTest; TList copyTest1( listTest ); @@ -94,7 +90,6 @@ TEST_F( TListTest, copyTest ) { EXPECT_EQ( 2u, copyTest2.size() ); } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, accessTest ) { const size_t numEntries = 10; TList listTest; @@ -113,21 +108,19 @@ TEST_F( TListTest, accessTest ) { } } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, clearTest ) { - const size_t numEntries = 10; + static const size_t numEntries = 10; TList listTest; std::vector values; createList( numEntries, listTest, values ); listTest.clear(); - EXPECT_EQ( listTest.size(), 0 ); + EXPECT_EQ( listTest.size(), 0u ); EXPECT_TRUE( listTest.isEmpty() ); } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, removeTest ) { - const size_t numEntries = 10; + static const size_t numEntries = 10; TList listTest; std::vector values; @@ -140,7 +133,6 @@ TEST_F( TListTest, removeTest ) { } } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, isEmptyTest ) { TList listTest; EXPECT_TRUE( listTest.isEmpty() ); @@ -151,7 +143,6 @@ TEST_F( TListTest, isEmptyTest ) { EXPECT_TRUE( listTest.isEmpty() ); } -//--------------------------------------------------------------------------------------------- TEST_F( TListTest, bug_IterateEmptyListTest ) { TList listTest; bool ok = true; @@ -162,5 +153,3 @@ TEST_F( TListTest, bug_IterateEmptyListTest ) { } EXPECT_TRUE( ok ); } - -//--------------------------------------------------------------------------------------------- diff --git a/test/memory/TPoolAllocatorTest.cpp b/test/memory/TPoolAllocatorTest.cpp index f1597d3..5419839 100644 --- a/test/memory/TPoolAllocatorTest.cpp +++ b/test/memory/TPoolAllocatorTest.cpp @@ -92,10 +92,24 @@ TEST_F(TPoolAllocatorTest, clearTest ) { TEST_F(TPoolAllocatorTest, resizeTest) { TPoolAllocator allocator; allocator.resize(100); - //allocator.resize(100); for (size_t i = 0; i < 200; ++i) { EXPECT_NE(nullptr, allocator.alloc()); } - EXPECT_EQ(200u, allocator.reservedMem()); + EXPECT_EQ(200u, allocator.capacity()); +} + +TEST_F(TPoolAllocatorTest, releaseTest) { + TPoolAllocator allocator; + allocator.resize(100); + for (size_t i = 0; i < 200; ++i) { + EXPECT_NE(nullptr, allocator.alloc()); + } + + allocator.release(); + for (size_t i = 0; i < 200; ++i) { + EXPECT_NE(nullptr, allocator.alloc()); + } + + EXPECT_EQ(200u, allocator.capacity()); }