From cf2d86a4f62d6aa2658303335f23c7138ec56596 Mon Sep 17 00:00:00 2001 From: trivialfis Date: Sun, 19 Aug 2018 12:40:30 +0800 Subject: [PATCH] Add travis sanitizers tests. (#3557) * Add travis sanitizers tests. * Add gcc-7 in Travis. * Add SANITIZER_PATH for CMake. * Enable sanitizer tests in Travis. * Fix memory leaks in tests. * Fix all memory leaks reported by Address Sanitizer. * tests/cpp/helpers.h/CreateDMatrix now returns raw pointer. --- .travis.yml | 6 +++ CMakeLists.txt | 3 +- cmake/modules/FindASan.cmake | 4 +- cmake/modules/FindLSan.cmake | 2 +- cmake/modules/FindTSan.cmake | 2 +- doc/contribute.rst | 8 ++++ tests/cpp/c_api/test_c_api.cc | 19 +++++---- tests/cpp/common/test_column_matrix.cc | 39 ++++++++++--------- tests/cpp/common/test_gpu_hist_util.cu | 10 +++-- tests/cpp/data/test_metainfo.cc | 2 + tests/cpp/data/test_simple_csr_source.cc | 3 ++ tests/cpp/data/test_simple_dmatrix.cc | 6 +++ tests/cpp/data/test_sparse_page_dmatrix.cc | 6 +++ tests/cpp/helpers.cc | 6 +-- tests/cpp/helpers.h | 4 +- tests/cpp/linear/test_linear.cc | 26 +++++++------ tests/cpp/metric/test_elementwise_metric.cc | 5 +++ tests/cpp/metric/test_metric.cc | 11 ++++-- tests/cpp/metric/test_multiclass_metric.cc | 4 ++ tests/cpp/metric/test_rank_metric.cc | 11 ++++++ tests/cpp/objective/test_hinge.cc | 2 + tests/cpp/objective/test_objective.cc | 6 ++- tests/cpp/objective/test_ranking_obj.cc | 4 +- tests/cpp/objective/test_regression_obj.cc | 22 +++++++++++ .../cpp/objective/test_regression_obj_gpu.cu | 8 ++++ tests/cpp/predictor/test_cpu_predictor.cc | 12 +++--- tests/cpp/predictor/test_gpu_predictor.cu | 16 ++++---- tests/cpp/test_learner.cc | 8 +++- tests/cpp/tree/test_gpu_hist.cu | 12 ++++-- tests/travis/run_test.sh | 30 ++++++++++++++ 30 files changed, 221 insertions(+), 76 deletions(-) diff --git a/.travis.yml b/.travis.yml index e86cfd048..d6343a3e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,8 @@ env: - TASK=cpp_test # distributed test - TASK=distributed_test + # address sanitizer test + - TASK=sanitizer_test matrix: exclude: @@ -43,6 +45,8 @@ matrix: env: TASK=cpp_test - os: osx env: TASK=distributed_test + - os: osx + env: TASK=sanitizer_test # dependent apt packages addons: @@ -62,6 +66,8 @@ addons: - graphviz - gcc-4.8 - g++-4.8 + - gcc-7 + - g++-7 before_install: - source dmlc-core/scripts/travis/travis_setup_env.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index e8676176c..945dc6c0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,10 @@ option(USE_NCCL "Build using NCCL for multi-GPU. Also requires USE_CUDA") option(JVM_BINDINGS "Build JVM bindings" OFF) option(GOOGLE_TEST "Build google tests" OFF) option(R_LIB "Build shared library for R package" OFF) -option(USE_SANITIZER "Use santizer flags" OFF) set(GPU_COMPUTE_VER "" CACHE STRING "Space separated list of compute versions to be built against, e.g. '35 61'") +option(USE_SANITIZER "Use santizer flags" OFF) +option(SANITIZER_PATH "Path to sanitizes.") set(ENABLED_SANITIZERS "address" "leak" CACHE STRING "Semicolon separated list of sanitizer names. E.g 'address;leak'. Supported sanitizers are address, leak and thread.") diff --git a/cmake/modules/FindASan.cmake b/cmake/modules/FindASan.cmake index 139072fbd..dbfafe2ac 100644 --- a/cmake/modules/FindASan.cmake +++ b/cmake/modules/FindASan.cmake @@ -1,8 +1,8 @@ set(ASan_LIB_NAME ASan) find_library(ASan_LIBRARY - NAMES libasan.so libasan.so.4 - PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib) + NAMES libasan.so libasan.so.4 libasan.so.3 libasan.so.2 libasan.so.1 libasan.so.0 + PATHS ${SANITIZER_PATH} /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib ${CMAKE_PREFIX_PATH}/lib) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(ASan DEFAULT_MSG diff --git a/cmake/modules/FindLSan.cmake b/cmake/modules/FindLSan.cmake index 20e169e29..3f68fb05b 100644 --- a/cmake/modules/FindLSan.cmake +++ b/cmake/modules/FindLSan.cmake @@ -2,7 +2,7 @@ set(LSan_LIB_NAME lsan) find_library(LSan_LIBRARY NAMES liblsan.so liblsan.so.0 liblsan.so.0.0.0 - PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib) + PATHS ${SANITIZER_PATH} /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib ${CMAKE_PREFIX_PATH}/lib) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LSan DEFAULT_MSG diff --git a/cmake/modules/FindTSan.cmake b/cmake/modules/FindTSan.cmake index 5c74b6fd1..aa01802f8 100644 --- a/cmake/modules/FindTSan.cmake +++ b/cmake/modules/FindTSan.cmake @@ -2,7 +2,7 @@ set(TSan_LIB_NAME tsan) find_library(TSan_LIBRARY NAMES libtsan.so libtsan.so.0 libtsan.so.0.0.0 - PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib) + PATHS ${SANITIZER_PATH} /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib ${CMAKE_PREFIX_PATH}/lib) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(TSan DEFAULT_MSG diff --git a/doc/contribute.rst b/doc/contribute.rst index 697359266..6335a6498 100644 --- a/doc/contribute.rst +++ b/doc/contribute.rst @@ -149,6 +149,14 @@ sanitizer is not compatible with the other two sanitizers. cmake -DUSE_SANITIZER=ON -DENABLED_SANITIZERS="address;leak" /path/to/xgboost +By default, CMake will search regular system paths for sanitizers, you can also +supply a specified SANITIZER_PATH. + + .. code-block:: bash + + cmake -DUSE_SANITIZER=ON -DENABLED_SANITIZERS="address;leak" \ + -DSANITIZER_PATH=/path/to/sanitizers /path/to/xgboost + How to use sanitizers with CUDA support ======================================= Runing XGBoost on CUDA with address sanitizer (asan) will raise memory error. diff --git a/tests/cpp/c_api/test_c_api.cc b/tests/cpp/c_api/test_c_api.cc index e779deaa0..05ef93195 100644 --- a/tests/cpp/c_api/test_c_api.cc +++ b/tests/cpp/c_api/test_c_api.cc @@ -13,14 +13,14 @@ TEST(c_api, XGDMatrixCreateFromMatDT) { DMatrixHandle handle; XGDMatrixCreateFromDT(data.data(), types.data(), 3, 2, &handle, 0); - std::shared_ptr dmat = - *static_cast *>(handle); - xgboost::MetaInfo &info = dmat->Info(); + std::shared_ptr *dmat = + static_cast *>(handle); + xgboost::MetaInfo &info = (*dmat)->Info(); ASSERT_EQ(info.num_col_, 2); ASSERT_EQ(info.num_row_, 3); ASSERT_EQ(info.num_nonzero_, 6); - auto iter = dmat->RowIterator(); + auto iter = (*dmat)->RowIterator(); iter->BeforeFirst(); while (iter->Next()) { auto batch = iter->Value(); @@ -29,6 +29,8 @@ TEST(c_api, XGDMatrixCreateFromMatDT) { ASSERT_EQ(batch[2][0].fvalue, 3.0f); ASSERT_EQ(batch[2][1].fvalue, 0.0f); } + + delete dmat; } TEST(c_api, XGDMatrixCreateFromMat_omp) { @@ -46,14 +48,14 @@ TEST(c_api, XGDMatrixCreateFromMat_omp) { std::numeric_limits::quiet_NaN(), &handle, 0); - std::shared_ptr dmat = - *static_cast *>(handle); - xgboost::MetaInfo &info = dmat->Info(); + std::shared_ptr *dmat = + static_cast *>(handle); + xgboost::MetaInfo &info = (*dmat)->Info(); ASSERT_EQ(info.num_col_, num_cols); ASSERT_EQ(info.num_row_, row); ASSERT_EQ(info.num_nonzero_, num_cols * row - num_missing); - auto iter = dmat->RowIterator(); + auto iter = (*dmat)->RowIterator(); iter->BeforeFirst(); while (iter->Next()) { auto batch = iter->Value(); @@ -64,5 +66,6 @@ TEST(c_api, XGDMatrixCreateFromMat_omp) { } } } + delete dmat; } } diff --git a/tests/cpp/common/test_column_matrix.cc b/tests/cpp/common/test_column_matrix.cc index 741672fbe..9afd10c2a 100644 --- a/tests/cpp/common/test_column_matrix.cc +++ b/tests/cpp/common/test_column_matrix.cc @@ -7,45 +7,48 @@ namespace common { TEST(DenseColumn, Test) { auto dmat = CreateDMatrix(100, 10, 0.0); GHistIndexMatrix gmat; - gmat.Init(dmat.get(), 256); + gmat.Init((*dmat).get(), 256); ColumnMatrix column_matrix; column_matrix.Init(gmat, 0.2); - for (auto i = 0ull; i < dmat->Info().num_row_; i++) { - for (auto j = 0ull; j < dmat->Info().num_col_; j++) { + for (auto i = 0ull; i < (*dmat)->Info().num_row_; i++) { + for (auto j = 0ull; j < (*dmat)->Info().num_col_; j++) { auto col = column_matrix.GetColumn(j); - EXPECT_EQ(gmat.index[i * dmat->Info().num_col_ + j], + EXPECT_EQ(gmat.index[i * (*dmat)->Info().num_col_ + j], col.GetGlobalBinIdx(i)); } } + delete dmat; } TEST(SparseColumn, Test) { auto dmat = CreateDMatrix(100, 1, 0.85); GHistIndexMatrix gmat; - gmat.Init(dmat.get(), 256); + gmat.Init((*dmat).get(), 256); ColumnMatrix column_matrix; column_matrix.Init(gmat, 0.5); - auto col = column_matrix.GetColumn(0); - ASSERT_EQ(col.Size(), gmat.index.size()); - for (auto i = 0ull; i < col.Size(); i++) { - EXPECT_EQ(gmat.index[gmat.row_ptr[col.GetRowIdx(i)]], - col.GetGlobalBinIdx(i)); - } + auto col = column_matrix.GetColumn(0); + ASSERT_EQ(col.Size(), gmat.index.size()); + for (auto i = 0ull; i < col.Size(); i++) { + EXPECT_EQ(gmat.index[gmat.row_ptr[col.GetRowIdx(i)]], + col.GetGlobalBinIdx(i)); + } + delete dmat; } TEST(DenseColumnWithMissing, Test) { auto dmat = CreateDMatrix(100, 1, 0.5); GHistIndexMatrix gmat; - gmat.Init(dmat.get(), 256); + gmat.Init((*dmat).get(), 256); ColumnMatrix column_matrix; column_matrix.Init(gmat, 0.2); - auto col = column_matrix.GetColumn(0); - for (auto i = 0ull; i < col.Size(); i++) { - if (col.IsMissing(i)) continue; - EXPECT_EQ(gmat.index[gmat.row_ptr[col.GetRowIdx(i)]], - col.GetGlobalBinIdx(i)); - } + auto col = column_matrix.GetColumn(0); + for (auto i = 0ull; i < col.Size(); i++) { + if (col.IsMissing(i)) continue; + EXPECT_EQ(gmat.index[gmat.row_ptr[col.GetRowIdx(i)]], + col.GetGlobalBinIdx(i)); + } + delete dmat; } } // namespace common } // namespace xgboost diff --git a/tests/cpp/common/test_gpu_hist_util.cu b/tests/cpp/common/test_gpu_hist_util.cu index 8d0117e72..81f931612 100644 --- a/tests/cpp/common/test_gpu_hist_util.cu +++ b/tests/cpp/common/test_gpu_hist_util.cu @@ -22,7 +22,7 @@ TEST(gpu_hist_util, TestDeviceSketch) { DMatrixHandle dmat_handle; XGDMatrixCreateFromMat(test_data.data(), nrows, 1, -1, &dmat_handle); - auto dmat = *static_cast *>(dmat_handle); + auto dmat = static_cast *>(dmat_handle); // parameters for finding quantiles tree::TrainParam p; @@ -34,15 +34,15 @@ TEST(gpu_hist_util, TestDeviceSketch) { // find quantiles on the CPU HistCutMatrix hmat_cpu; - hmat_cpu.Init(dmat.get(), p.max_bin); + hmat_cpu.Init((*dmat).get(), p.max_bin); // find the cuts on the GPU - dmlc::DataIter* iter = dmat->RowIterator(); + dmlc::DataIter* iter = (*dmat)->RowIterator(); iter->BeforeFirst(); CHECK(iter->Next()); const SparsePage& batch = iter->Value(); HistCutMatrix hmat_gpu; - DeviceSketch(batch, dmat->Info(), p, &hmat_gpu); + DeviceSketch(batch, (*dmat)->Info(), p, &hmat_gpu); CHECK(!iter->Next()); // compare the cuts @@ -54,6 +54,8 @@ TEST(gpu_hist_util, TestDeviceSketch) { for (int i = 0; i < hmat_gpu.cut.size(); ++i) { ASSERT_LT(fabs(hmat_cpu.cut[i] - hmat_gpu.cut[i]), eps * nrows); } + + delete dmat; } } // namespace common diff --git a/tests/cpp/data/test_metainfo.cc b/tests/cpp/data/test_metainfo.cc index d10fe36d9..4ba1f4eaf 100644 --- a/tests/cpp/data/test_metainfo.cc +++ b/tests/cpp/data/test_metainfo.cc @@ -64,6 +64,8 @@ TEST(MetaInfo, SaveLoadBinary) { EXPECT_EQ(inforead.num_row_, info.num_row_); std::remove(tmp_file.c_str()); + + delete fs; } TEST(MetaInfo, LoadQid) { diff --git a/tests/cpp/data/test_simple_csr_source.cc b/tests/cpp/data/test_simple_csr_source.cc index 8da8a9730..aba08b893 100644 --- a/tests/cpp/data/test_simple_csr_source.cc +++ b/tests/cpp/data/test_simple_csr_source.cc @@ -29,4 +29,7 @@ TEST(SimpleCSRSource, SaveLoadBinary) { EXPECT_EQ(first_row[2].index, first_row_read[2].index); EXPECT_EQ(first_row[2].fvalue, first_row_read[2].fvalue); row_iter = nullptr; row_iter_read = nullptr; + + delete dmat; + delete dmat_read; } diff --git a/tests/cpp/data/test_simple_dmatrix.cc b/tests/cpp/data/test_simple_dmatrix.cc index 10ded726e..f88a0295c 100644 --- a/tests/cpp/data/test_simple_dmatrix.cc +++ b/tests/cpp/data/test_simple_dmatrix.cc @@ -14,6 +14,8 @@ TEST(SimpleDMatrix, MetaInfo) { EXPECT_EQ(dmat->Info().num_col_, 5); EXPECT_EQ(dmat->Info().num_nonzero_, 6); EXPECT_EQ(dmat->Info().labels_.size(), dmat->Info().num_row_); + + delete dmat; } TEST(SimpleDMatrix, RowAccess) { @@ -35,6 +37,8 @@ TEST(SimpleDMatrix, RowAccess) { EXPECT_EQ(first_row[2].index, 2); EXPECT_EQ(first_row[2].fvalue, 20); row_iter = nullptr; + + delete dmat; } TEST(SimpleDMatrix, ColAccessWithoutBatches) { @@ -76,4 +80,6 @@ TEST(SimpleDMatrix, ColAccessWithoutBatches) { } EXPECT_EQ(num_col_batch, 1) << "Expected number of batches to be 1"; col_iter = nullptr; + + delete dmat; } diff --git a/tests/cpp/data/test_sparse_page_dmatrix.cc b/tests/cpp/data/test_sparse_page_dmatrix.cc index 572279c8c..9a5db8a89 100644 --- a/tests/cpp/data/test_sparse_page_dmatrix.cc +++ b/tests/cpp/data/test_sparse_page_dmatrix.cc @@ -21,6 +21,8 @@ TEST(SparsePageDMatrix, MetaInfo) { // Clean up of external memory files std::remove((tmp_file + ".cache").c_str()); std::remove((tmp_file + ".cache.row.page").c_str()); + + delete dmat; } TEST(SparsePageDMatrix, RowAccess) { @@ -48,6 +50,8 @@ TEST(SparsePageDMatrix, RowAccess) { // Clean up of external memory files std::remove((tmp_file + ".cache").c_str()); std::remove((tmp_file + ".cache.row.page").c_str()); + + delete dmat; } TEST(SparsePageDMatrix, ColAcess) { @@ -84,4 +88,6 @@ TEST(SparsePageDMatrix, ColAcess) { std::remove((tmp_file + ".cache").c_str()); std::remove((tmp_file + ".cache.col.page").c_str()); std::remove((tmp_file + ".cache.row.page").c_str()); + + delete dmat; } diff --git a/tests/cpp/helpers.cc b/tests/cpp/helpers.cc index 2c8526c1c..cb9b12f49 100644 --- a/tests/cpp/helpers.cc +++ b/tests/cpp/helpers.cc @@ -107,8 +107,8 @@ xgboost::bst_float GetMetricEval(xgboost::Metric * metric, return metric->Eval(preds, info, false); } -std::shared_ptr CreateDMatrix(int rows, int columns, - float sparsity, int seed) { +std::shared_ptr* CreateDMatrix(int rows, int columns, + float sparsity, int seed) { const float missing_value = -1; std::vector test_data(rows * columns); std::mt19937 gen(seed); @@ -124,5 +124,5 @@ std::shared_ptr CreateDMatrix(int rows, int columns, DMatrixHandle handle; XGDMatrixCreateFromMat(test_data.data(), rows, columns, missing_value, &handle); - return *static_cast *>(handle); + return static_cast *>(handle); } diff --git a/tests/cpp/helpers.h b/tests/cpp/helpers.h index 411b916de..998249a53 100644 --- a/tests/cpp/helpers.h +++ b/tests/cpp/helpers.h @@ -59,6 +59,6 @@ xgboost::bst_float GetMetricEval( * \return The new d matrix. */ -std::shared_ptr CreateDMatrix(int rows, int columns, - float sparsity, int seed = 0); +std::shared_ptr *CreateDMatrix(int rows, int columns, + float sparsity, int seed = 0); #endif diff --git a/tests/cpp/linear/test_linear.cc b/tests/cpp/linear/test_linear.cc index af5fa6085..de5f0f2fb 100644 --- a/tests/cpp/linear/test_linear.cc +++ b/tests/cpp/linear/test_linear.cc @@ -8,37 +8,41 @@ typedef std::pair arg; TEST(Linear, shotgun) { typedef std::pair arg; auto mat = CreateDMatrix(10, 10, 0); - std::vector enabled(mat->Info().num_col_, true); - mat->InitColAccess(1 << 16, false); + std::vector enabled((*mat)->Info().num_col_, true); + (*mat)->InitColAccess(1 << 16, false); auto updater = std::unique_ptr( xgboost::LinearUpdater::Create("shotgun")); updater->Init({{"eta", "1."}}); xgboost::HostDeviceVector gpair( - mat->Info().num_row_, xgboost::GradientPair(-5, 1.0)); + (*mat)->Info().num_row_, xgboost::GradientPair(-5, 1.0)); xgboost::gbm::GBLinearModel model; - model.param.num_feature = mat->Info().num_col_; + model.param.num_feature = (*mat)->Info().num_col_; model.param.num_output_group = 1; model.LazyInitModel(); - updater->Update(&gpair, mat.get(), &model, gpair.Size()); + updater->Update(&gpair, (*mat).get(), &model, gpair.Size()); ASSERT_EQ(model.bias()[0], 5.0f); + + delete mat; } TEST(Linear, coordinate) { typedef std::pair arg; auto mat = CreateDMatrix(10, 10, 0); - std::vector enabled(mat->Info().num_col_, true); - mat->InitColAccess(1 << 16, false); + std::vector enabled((*mat)->Info().num_col_, true); + (*mat)->InitColAccess(1 << 16, false); auto updater = std::unique_ptr( xgboost::LinearUpdater::Create("coord_descent")); updater->Init({{"eta", "1."}}); xgboost::HostDeviceVector gpair( - mat->Info().num_row_, xgboost::GradientPair(-5, 1.0)); + (*mat)->Info().num_row_, xgboost::GradientPair(-5, 1.0)); xgboost::gbm::GBLinearModel model; - model.param.num_feature = mat->Info().num_col_; + model.param.num_feature = (*mat)->Info().num_col_; model.param.num_output_group = 1; model.LazyInitModel(); - updater->Update(&gpair, mat.get(), &model, gpair.Size()); + updater->Update(&gpair, (*mat).get(), &model, gpair.Size()); ASSERT_EQ(model.bias()[0], 5.0f); -} \ No newline at end of file + + delete mat; +} diff --git a/tests/cpp/metric/test_elementwise_metric.cc b/tests/cpp/metric/test_elementwise_metric.cc index 70e6e05e6..3e0cb4c43 100644 --- a/tests/cpp/metric/test_elementwise_metric.cc +++ b/tests/cpp/metric/test_elementwise_metric.cc @@ -11,6 +11,7 @@ TEST(Metric, RMSE) { {0.1f, 0.9f, 0.1f, 0.9f}, { 0, 0, 1, 1}), 0.6403f, 0.001f); + delete metric; } TEST(Metric, MAE) { @@ -21,6 +22,7 @@ TEST(Metric, MAE) { {0.1f, 0.9f, 0.1f, 0.9f}, { 0, 0, 1, 1}), 0.5f, 0.001f); + delete metric; } TEST(Metric, LogLoss) { @@ -31,6 +33,7 @@ TEST(Metric, LogLoss) { {0.1f, 0.9f, 0.1f, 0.9f}, { 0, 0, 1, 1}), 1.2039f, 0.001f); + delete metric; } TEST(Metric, Error) { @@ -56,6 +59,7 @@ TEST(Metric, Error) { {0.1f, 0.2f, 0.1f, 0.2f}, { 0, 0, 1, 1}), 0.5f, 0.001f); + delete metric; } TEST(Metric, PoissionNegLogLik) { @@ -66,4 +70,5 @@ TEST(Metric, PoissionNegLogLik) { {0.1f, 0.2f, 0.1f, 0.2f}, { 0, 0, 1, 1}), 1.1280f, 0.001f); + delete metric; } diff --git a/tests/cpp/metric/test_metric.cc b/tests/cpp/metric/test_metric.cc index d0c774902..e073a76f1 100644 --- a/tests/cpp/metric/test_metric.cc +++ b/tests/cpp/metric/test_metric.cc @@ -4,8 +4,11 @@ #include "../helpers.h" TEST(Metric, UnknownMetric) { - EXPECT_ANY_THROW(xgboost::Metric::Create("unknown_name")); - EXPECT_NO_THROW(xgboost::Metric::Create("rmse")); - EXPECT_ANY_THROW(xgboost::Metric::Create("unknown_name@1")); - EXPECT_NO_THROW(xgboost::Metric::Create("error@0.5f")); + xgboost::Metric * metric; + EXPECT_ANY_THROW(metric = xgboost::Metric::Create("unknown_name")); + EXPECT_NO_THROW(metric = xgboost::Metric::Create("rmse")); + delete metric; + EXPECT_ANY_THROW(metric = xgboost::Metric::Create("unknown_name@1")); + EXPECT_NO_THROW(metric = xgboost::Metric::Create("error@0.5f")); + delete metric; } diff --git a/tests/cpp/metric/test_multiclass_metric.cc b/tests/cpp/metric/test_multiclass_metric.cc index c785e67d9..fe5a3788d 100644 --- a/tests/cpp/metric/test_multiclass_metric.cc +++ b/tests/cpp/metric/test_multiclass_metric.cc @@ -13,6 +13,8 @@ TEST(Metric, MultiClassError) { {0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f}, {0, 1, 2}), 0.666f, 0.001f); + + delete metric; } TEST(Metric, MultiClassLogLoss) { @@ -25,4 +27,6 @@ TEST(Metric, MultiClassLogLoss) { {0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f}, {0, 1, 2}), 2.302f, 0.001f); + + delete metric; } diff --git a/tests/cpp/metric/test_rank_metric.cc b/tests/cpp/metric/test_rank_metric.cc index 1d271521b..5a235b110 100644 --- a/tests/cpp/metric/test_rank_metric.cc +++ b/tests/cpp/metric/test_rank_metric.cc @@ -17,6 +17,8 @@ TEST(Metric, AMS) { metric = xgboost::Metric::Create("ams@0"); ASSERT_STREQ(metric->Name(), "ams@0"); EXPECT_NEAR(GetMetricEval(metric, {0, 1}, {0, 1}), 0.311f, 0.001f); + + delete metric; } TEST(Metric, AUC) { @@ -29,6 +31,8 @@ TEST(Metric, AUC) { 0.5f, 0.001f); EXPECT_ANY_THROW(GetMetricEval(metric, {0, 1}, {})); EXPECT_ANY_THROW(GetMetricEval(metric, {0, 0}, {0, 0})); + + delete metric; } TEST(Metric, AUCPR) { @@ -50,6 +54,8 @@ TEST(Metric, AUCPR) { 0.2769199f, 0.001f); EXPECT_ANY_THROW(GetMetricEval(metric, {0, 1}, {})); EXPECT_ANY_THROW(GetMetricEval(metric, {0, 0}, {0, 0})); + + delete metric; } TEST(Metric, Precision) { @@ -74,6 +80,8 @@ TEST(Metric, Precision) { 0.5f, 0.001f); EXPECT_ANY_THROW(GetMetricEval(metric, {0, 1}, {})); + + delete metric; } TEST(Metric, NDCG) { @@ -114,6 +122,8 @@ TEST(Metric, NDCG) { {0.1f, 0.9f, 0.1f, 0.9f}, { 0, 0, 1, 1}), 0.3868f, 0.001f); + + delete metric; } TEST(Metric, MAP) { @@ -139,4 +149,5 @@ TEST(Metric, MAP) { {0.1f, 0.9f, 0.1f, 0.9f}, { 0, 0, 1, 1}), 0.25f, 0.001f); + delete metric; } diff --git a/tests/cpp/objective/test_hinge.cc b/tests/cpp/objective/test_hinge.cc index fe3005bca..5986ca620 100644 --- a/tests/cpp/objective/test_hinge.cc +++ b/tests/cpp/objective/test_hinge.cc @@ -17,4 +17,6 @@ TEST(Objective, HingeObj) { { eps, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, eps }); ASSERT_NO_THROW(obj->DefaultEvalMetric()); + + delete obj; } diff --git a/tests/cpp/objective/test_objective.cc b/tests/cpp/objective/test_objective.cc index 28a01f622..213f7d47e 100644 --- a/tests/cpp/objective/test_objective.cc +++ b/tests/cpp/objective/test_objective.cc @@ -4,6 +4,8 @@ #include "../helpers.h" TEST(Objective, UnknownFunction) { - EXPECT_ANY_THROW(xgboost::ObjFunction::Create("unknown_name")); - EXPECT_NO_THROW(xgboost::ObjFunction::Create("reg:linear")); + xgboost::ObjFunction* obj; + EXPECT_ANY_THROW(obj = xgboost::ObjFunction::Create("unknown_name")); + EXPECT_NO_THROW(obj = xgboost::ObjFunction::Create("reg:linear")); + delete obj; } diff --git a/tests/cpp/objective/test_ranking_obj.cc b/tests/cpp/objective/test_ranking_obj.cc index 8dc136648..633739f7c 100644 --- a/tests/cpp/objective/test_ranking_obj.cc +++ b/tests/cpp/objective/test_ranking_obj.cc @@ -25,4 +25,6 @@ TEST(Objective, PairwiseRankingGPair) { {0.9975f, 0.9975f, 0.9975f, 0.9975f}); ASSERT_NO_THROW(obj->DefaultEvalMetric()); -} \ No newline at end of file + + delete obj; +} diff --git a/tests/cpp/objective/test_regression_obj.cc b/tests/cpp/objective/test_regression_obj.cc index 27820f9df..fc31d4f96 100644 --- a/tests/cpp/objective/test_regression_obj.cc +++ b/tests/cpp/objective/test_regression_obj.cc @@ -15,6 +15,8 @@ TEST(Objective, LinearRegressionGPair) { {1, 1, 1, 1, 1, 1, 1, 1}); ASSERT_NO_THROW(obj->DefaultEvalMetric()); + + delete obj; } TEST(Objective, LogisticRegressionGPair) { @@ -27,6 +29,8 @@ TEST(Objective, LogisticRegressionGPair) { { 1, 1, 1, 1, 1, 1, 1, 1}, { 0.5f, 0.52f, 0.71f, 0.73f, -0.5f, -0.47f, -0.28f, -0.26f}, {0.25f, 0.24f, 0.20f, 0.19f, 0.25f, 0.24f, 0.20f, 0.19f}); + + delete obj; } TEST(Objective, LogisticRegressionBasic) { @@ -53,6 +57,8 @@ TEST(Objective, LogisticRegressionBasic) { for (int i = 0; i < static_cast(io_preds.Size()); ++i) { EXPECT_NEAR(preds[i], out_preds[i], 0.01f); } + + delete obj; } TEST(Objective, LogisticRawGPair) { @@ -65,6 +71,8 @@ TEST(Objective, LogisticRawGPair) { { 1, 1, 1, 1, 1, 1, 1, 1}, { 0.5f, 0.52f, 0.71f, 0.73f, -0.5f, -0.47f, -0.28f, -0.26f}, {0.25f, 0.24f, 0.20f, 0.19f, 0.25f, 0.24f, 0.20f, 0.19f}); + + delete obj; } TEST(Objective, PoissonRegressionGPair) { @@ -78,6 +86,8 @@ TEST(Objective, PoissonRegressionGPair) { { 1, 1, 1, 1, 1, 1, 1, 1}, { 1, 1.10f, 2.45f, 2.71f, 0, 0.10f, 1.45f, 1.71f}, {1.10f, 1.22f, 2.71f, 3.00f, 1.10f, 1.22f, 2.71f, 3.00f}); + + delete obj; } TEST(Objective, PoissonRegressionBasic) { @@ -102,6 +112,8 @@ TEST(Objective, PoissonRegressionBasic) { for (int i = 0; i < static_cast(io_preds.Size()); ++i) { EXPECT_NEAR(preds[i], out_preds[i], 0.01f); } + + delete obj; } TEST(Objective, GammaRegressionGPair) { @@ -114,6 +126,8 @@ TEST(Objective, GammaRegressionGPair) { {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 0.09f, 0.59f, 0.63f}, {0, 0, 0, 0, 1, 0.90f, 0.40f, 0.36f}); + + delete obj; } TEST(Objective, GammaRegressionBasic) { @@ -138,6 +152,8 @@ TEST(Objective, GammaRegressionBasic) { for (int i = 0; i < static_cast(io_preds.Size()); ++i) { EXPECT_NEAR(preds[i], out_preds[i], 0.01f); } + + delete obj; } TEST(Objective, TweedieRegressionGPair) { @@ -151,6 +167,8 @@ TEST(Objective, TweedieRegressionGPair) { { 1, 1, 1, 1, 1, 1, 1, 1}, { 1, 1.09f, 2.24f, 2.45f, 0, 0.10f, 1.33f, 1.55f}, {0.89f, 0.98f, 2.02f, 2.21f, 1, 1.08f, 2.11f, 2.30f}); + + delete obj; } TEST(Objective, TweedieRegressionBasic) { @@ -175,6 +193,8 @@ TEST(Objective, TweedieRegressionBasic) { for (int i = 0; i < static_cast(io_preds.Size()); ++i) { EXPECT_NEAR(preds[i], out_preds[i], 0.01f); } + + delete obj; } TEST(Objective, CoxRegressionGPair) { @@ -187,4 +207,6 @@ TEST(Objective, CoxRegressionGPair) { { 1, 1, 1, 1, 1, 1, 1, 1}, { 0, 0, 0, -0.799f, -0.788f, -0.590f, 0.910f, 1.006f}, { 0, 0, 0, 0.160f, 0.186f, 0.348f, 0.610f, 0.639f}); + + delete obj; } diff --git a/tests/cpp/objective/test_regression_obj_gpu.cu b/tests/cpp/objective/test_regression_obj_gpu.cu index ac9a0bd2d..6bcede361 100644 --- a/tests/cpp/objective/test_regression_obj_gpu.cu +++ b/tests/cpp/objective/test_regression_obj_gpu.cu @@ -17,6 +17,8 @@ TEST(Objective, GPULinearRegressionGPair) { {1, 1, 1, 1, 1, 1, 1, 1}); ASSERT_NO_THROW(obj->DefaultEvalMetric()); + + delete obj; } TEST(Objective, GPULogisticRegressionGPair) { @@ -29,6 +31,8 @@ TEST(Objective, GPULogisticRegressionGPair) { { 1, 1, 1, 1, 1, 1, 1, 1}, { 0.5f, 0.52f, 0.71f, 0.73f, -0.5f, -0.47f, -0.28f, -0.26f}, {0.25f, 0.24f, 0.20f, 0.19f, 0.25f, 0.24f, 0.20f, 0.19f}); + + delete obj; } TEST(Objective, GPULogisticRegressionBasic) { @@ -55,6 +59,8 @@ TEST(Objective, GPULogisticRegressionBasic) { for (int i = 0; i < static_cast(io_preds.Size()); ++i) { EXPECT_NEAR(preds[i], out_preds[i], 0.01f); } + + delete obj; } TEST(Objective, GPULogisticRawGPair) { @@ -67,4 +73,6 @@ TEST(Objective, GPULogisticRawGPair) { { 1, 1, 1, 1, 1, 1, 1, 1}, { 0.5f, 0.52f, 0.71f, 0.73f, -0.5f, -0.47f, -0.28f, -0.26f}, {0.25f, 0.24f, 0.20f, 0.19f, 0.25f, 0.24f, 0.20f, 0.19f}); + + delete obj; } diff --git a/tests/cpp/predictor/test_cpu_predictor.cc b/tests/cpp/predictor/test_cpu_predictor.cc index 796c6bf4f..784c0dfa9 100644 --- a/tests/cpp/predictor/test_cpu_predictor.cc +++ b/tests/cpp/predictor/test_cpu_predictor.cc @@ -25,14 +25,14 @@ TEST(cpu_predictor, Test) { // Test predict batch HostDeviceVector out_predictions; - cpu_predictor->PredictBatch(dmat.get(), &out_predictions, model, 0); + cpu_predictor->PredictBatch((*dmat).get(), &out_predictions, model, 0); std::vector& out_predictions_h = out_predictions.HostVector(); for (int i = 0; i < out_predictions.Size(); i++) { ASSERT_EQ(out_predictions_h[i], 1.5); } // Test predict instance - auto batch = dmat->RowIterator()->Value(); + auto batch = (*dmat)->RowIterator()->Value(); for (int i = 0; i < batch.Size(); i++) { std::vector instance_out_predictions; cpu_predictor->PredictInstance(batch[i], &instance_out_predictions, model); @@ -41,22 +41,24 @@ TEST(cpu_predictor, Test) { // Test predict leaf std::vector leaf_out_predictions; - cpu_predictor->PredictLeaf(dmat.get(), &leaf_out_predictions, model); + cpu_predictor->PredictLeaf((*dmat).get(), &leaf_out_predictions, model); for (int i = 0; i < leaf_out_predictions.size(); i++) { ASSERT_EQ(leaf_out_predictions[i], 0); } // Test predict contribution std::vector out_contribution; - cpu_predictor->PredictContribution(dmat.get(), &out_contribution, model); + cpu_predictor->PredictContribution((*dmat).get(), &out_contribution, model); for (int i = 0; i < out_contribution.size(); i++) { ASSERT_EQ(out_contribution[i], 1.5); } // Test predict contribution (approximate method) - cpu_predictor->PredictContribution(dmat.get(), &out_contribution, model, true); + cpu_predictor->PredictContribution((*dmat).get(), &out_contribution, model, true); for (int i = 0; i < out_contribution.size(); i++) { ASSERT_EQ(out_contribution[i], 1.5); } + + delete dmat; } } // namespace xgboost diff --git a/tests/cpp/predictor/test_gpu_predictor.cu b/tests/cpp/predictor/test_gpu_predictor.cu index 6a3d578e8..2967da226 100644 --- a/tests/cpp/predictor/test_gpu_predictor.cu +++ b/tests/cpp/predictor/test_gpu_predictor.cu @@ -35,8 +35,8 @@ TEST(gpu_predictor, Test) { // Test predict batch HostDeviceVector gpu_out_predictions; HostDeviceVector cpu_out_predictions; - gpu_predictor->PredictBatch(dmat.get(), &gpu_out_predictions, model, 0); - cpu_predictor->PredictBatch(dmat.get(), &cpu_out_predictions, model, 0); + gpu_predictor->PredictBatch((*dmat).get(), &gpu_out_predictions, model, 0); + cpu_predictor->PredictBatch((*dmat).get(), &cpu_out_predictions, model, 0); std::vector& gpu_out_predictions_h = gpu_out_predictions.HostVector(); std::vector& cpu_out_predictions_h = cpu_out_predictions.HostVector(); float abs_tolerance = 0.001; @@ -45,7 +45,7 @@ TEST(gpu_predictor, Test) { abs_tolerance); } // Test predict instance - auto batch = dmat->RowIterator()->Value(); + auto batch = (*dmat)->RowIterator()->Value(); for (int i = 0; i < batch.Size(); i++) { std::vector gpu_instance_out_predictions; std::vector cpu_instance_out_predictions; @@ -59,8 +59,8 @@ TEST(gpu_predictor, Test) { // Test predict leaf std::vector gpu_leaf_out_predictions; std::vector cpu_leaf_out_predictions; - cpu_predictor->PredictLeaf(dmat.get(), &cpu_leaf_out_predictions, model); - gpu_predictor->PredictLeaf(dmat.get(), &gpu_leaf_out_predictions, model); + cpu_predictor->PredictLeaf((*dmat).get(), &cpu_leaf_out_predictions, model); + gpu_predictor->PredictLeaf((*dmat).get(), &gpu_leaf_out_predictions, model); for (int i = 0; i < gpu_leaf_out_predictions.size(); i++) { ASSERT_EQ(gpu_leaf_out_predictions[i], cpu_leaf_out_predictions[i]); } @@ -68,11 +68,13 @@ TEST(gpu_predictor, Test) { // Test predict contribution std::vector gpu_out_contribution; std::vector cpu_out_contribution; - cpu_predictor->PredictContribution(dmat.get(), &cpu_out_contribution, model); - gpu_predictor->PredictContribution(dmat.get(), &gpu_out_contribution, model); + cpu_predictor->PredictContribution((*dmat).get(), &cpu_out_contribution, model); + gpu_predictor->PredictContribution((*dmat).get(), &gpu_out_contribution, model); for (int i = 0; i < gpu_out_contribution.size(); i++) { ASSERT_EQ(gpu_out_contribution[i], cpu_out_contribution[i]); } + + delete dmat; } } // namespace predictor } // namespace xgboost diff --git a/tests/cpp/test_learner.cc b/tests/cpp/test_learner.cc index 25d10432d..0a6448764 100644 --- a/tests/cpp/test_learner.cc +++ b/tests/cpp/test_learner.cc @@ -1,5 +1,6 @@ // Copyright by Contributors #include +#include #include "helpers.h" #include "xgboost/learner.h" @@ -7,8 +8,11 @@ namespace xgboost { TEST(learner, Test) { typedef std::pair arg; auto args = {arg("tree_method", "exact")}; - auto mat = {CreateDMatrix(10, 10, 0)}; + auto mat_ptr = CreateDMatrix(10, 10, 0); + std::vector> mat = {*mat_ptr}; auto learner = std::unique_ptr(Learner::Create(mat)); learner->Configure(args); + + delete mat_ptr; } -} // namespace xgboost \ No newline at end of file +} // namespace xgboost diff --git a/tests/cpp/tree/test_gpu_hist.cu b/tests/cpp/tree/test_gpu_hist.cu index a1766558c..83ff87da0 100644 --- a/tests/cpp/tree/test_gpu_hist.cu +++ b/tests/cpp/tree/test_gpu_hist.cu @@ -19,11 +19,11 @@ TEST(gpu_hist_experimental, TestSparseShard) { int max_bins = 4; auto dmat = CreateDMatrix(rows, columns, 0.9f); common::GHistIndexMatrix gmat; - gmat.Init(dmat.get(),max_bins); + gmat.Init((*dmat).get(),max_bins); TrainParam p; p.max_depth = 6; - dmlc::DataIter* iter = dmat->RowIterator(); + dmlc::DataIter* iter = (*dmat)->RowIterator(); iter->BeforeFirst(); CHECK(iter->Next()); const SparsePage& batch = iter->Value(); @@ -50,6 +50,8 @@ TEST(gpu_hist_experimental, TestSparseShard) { ASSERT_EQ(gidx[i * shard.row_stride + row_offset], shard.null_gidx_value); } } + + delete dmat; } TEST(gpu_hist_experimental, TestDenseShard) { @@ -58,11 +60,11 @@ TEST(gpu_hist_experimental, TestDenseShard) { int max_bins = 4; auto dmat = CreateDMatrix(rows, columns, 0); common::GHistIndexMatrix gmat; - gmat.Init(dmat.get(),max_bins); + gmat.Init((*dmat).get(),max_bins); TrainParam p; p.max_depth = 6; - dmlc::DataIter* iter = dmat->RowIterator(); + dmlc::DataIter* iter = (*dmat)->RowIterator(); iter->BeforeFirst(); CHECK(iter->Next()); const SparsePage& batch = iter->Value(); @@ -82,6 +84,8 @@ TEST(gpu_hist_experimental, TestDenseShard) { for (int i = 0; i < gmat.index.size(); i++) { ASSERT_EQ(gidx[i], gmat.index[i]); } + + delete dmat; } } // namespace tree diff --git a/tests/travis/run_test.sh b/tests/travis/run_test.sh index 01278dcab..b15a43fff 100755 --- a/tests/travis/run_test.sh +++ b/tests/travis/run_test.sh @@ -149,9 +149,39 @@ if [ ${TASK} == "cpp_test" ]; then make cover fi + if [ ${TASK} == "distributed_test" ]; then set -e make all || exit -1 cd tests/distributed ./runtests.sh fi + +if [ ${TASK} == "sanitizer_test" ]; then + set -e + # Build gtest via cmake + wget -nc https://github.com/google/googletest/archive/release-1.7.0.zip + unzip -n release-1.7.0.zip + mv googletest-release-1.7.0 gtest && cd gtest + CC=gcc-7 CXX=g++-7 cmake -DCMAKE_CXX_FLAGS="-fuse-ld=gold" \ + -DCMAKE_C_FLAGS="-fuse-ld=gold" + make + mkdir lib && mv libgtest.a lib + cd .. + rm -rf release-1.7.0.zip + + mkdir build && cd build + CC=gcc-7 CXX=g++-7 cmake .. -DGOOGLE_TEST=ON -DGTEST_ROOT=$PWD/../gtest/ \ + -DUSE_SANITIZER=ON -DENABLED_SANITIZERS="address" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DSANITIZER_PATH=/usr/lib/x86_64-linux-gnu/ \ + -DCMAKE_CXX_FLAGS="-fuse-ld=gold" \ + -DCMAKE_C_FLAGS="-fuse-ld=gold" + make + cd .. + + export ASAN_SYMBOLIZER_PATH=$(which llvm-symbolizer) + ASAN_OPTIONS=symbolize=1 ./testxgboost + rm -rf build + exit 0 +fi