This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/master by this push:
     new c38a1c7  [Config] Support config validating when BE bootstrap and 
update BE's config by API (#5379)
c38a1c7 is described below

commit c38a1c799f90ec9497d966a1d7670f78edf9fca0
Author: Yingchun Lai <[email protected]>
AuthorDate: Thu Mar 4 22:21:49 2021 +0800

    [Config] Support config validating when BE bootstrap and update BE's config 
by API (#5379)
    
    Some invalid config value may cause BE work in an unexpected behavior,
    this patch aim to support config validating when BE bootstrap and update 
BE's config by API
    to reject invalid value.
    This is a work to accomplish PR #4423
---
 be/src/common/config.h                    |   6 ++
 be/src/common/configbase.cpp              | 141 +++++++++++++++++-------------
 be/src/common/configbase.h                |  48 ++++++++--
 be/test/common/CMakeLists.txt             |   1 +
 be/test/common/config_test.cpp            |   4 +-
 be/test/common/config_validator_test.cpp  |  59 +++++++++++++
 be/test/runtime/result_queue_mgr_test.cpp |   9 +-
 be/test/test_util/CMakeLists.txt          |   2 +-
 be/test/test_util/test_util.cpp           |  11 ++-
 be/test/test_util/test_util.h             |   3 +
 10 files changed, 204 insertions(+), 80 deletions(-)

diff --git a/be/src/common/config.h b/be/src/common/config.h
index 1c62a7e..8d2736b 100644
--- a/be/src/common/config.h
+++ b/be/src/common/config.h
@@ -248,17 +248,23 @@ CONF_mInt32(base_compaction_write_mbytes_per_sec, "5");
 // size_based policy, a optimization version of cumulative compaction, 
targeting the use cases requiring
 // lower write amplification, trading off read amplification and space 
amplification.
 CONF_String(cumulative_compaction_policy, "size_based");
+CONF_Validator(cumulative_compaction_policy, [](const std::string config) -> 
bool {
+  return config == "size_based" || config == "num_based";
+});
 
 // In size_based policy, output rowset of cumulative compaction total disk 
size exceed this config size,
 // this rowset will be given to base compaction, unit is m byte.
 CONF_mInt64(cumulative_size_based_promotion_size_mbytes, "1024");
+
 // In size_based policy, output rowset of cumulative compaction total disk 
size exceed this config ratio of
 // base rowset's total disk size, this rowset will be given to base 
compaction. The value must be between
 // 0 and 1.
 CONF_mDouble(cumulative_size_based_promotion_ratio, "0.05");
+
 // In size_based policy, the smallest size of rowset promotion. When the 
rowset is less than this config, this
 // rowset will be not given to base compaction. The unit is m byte.
 CONF_mInt64(cumulative_size_based_promotion_min_size_mbytes, "64");
+
 // The lower bound size to do cumulative compaction. When total disk size of 
candidate rowsets is less than
 // this size, size_based policy may not do to cumulative compaction. The unit 
is m byte.
 CONF_mInt64(cumulative_size_based_compaction_lower_size_mbytes, "64");
diff --git a/be/src/common/configbase.cpp b/be/src/common/configbase.cpp
index 1a8f97a..c2757b2 100644
--- a/be/src/common/configbase.cpp
+++ b/be/src/common/configbase.cpp
@@ -36,6 +36,7 @@ namespace doris {
 namespace config {
 
 std::map<std::string, Register::Field>* Register::_s_field_map = nullptr;
+std::map<std::string, std::function<bool()>>* 
RegisterConfValidator::_s_field_validator = nullptr;
 std::map<std::string, std::string>* full_conf_map = nullptr;
 
 std::mutex custom_conf_lock;
@@ -171,18 +172,28 @@ bool strtox(const std::string& valstr, std::string& 
retval) {
     return true;
 }
 
+template <typename T>
+bool convert(const std::string& value, T& retval) {
+    std::string valstr(value);
+    trim(valstr);
+    if (!replaceenv(valstr)) {
+        return false;
+    }
+    return strtox(valstr, retval);
+}
+
 // load conf file
-bool Properties::load(const char* filename, bool must_exist) {
-    // if filename is null, use the empty props
-    if (filename == nullptr) {
+bool Properties::load(const char* conf_file, bool must_exist) {
+    // if conf_file is null, use the empty props
+    if (conf_file == nullptr) {
         return true;
     }
 
     // open the conf file
-    std::ifstream input(filename);
+    std::ifstream input(conf_file);
     if (!input.is_open()) {
         if (must_exist) {
-            std::cerr << "config::load() failed to open the file:" << filename 
<< std::endl;
+            std::cerr << "config::load() failed to open the file:" << 
conf_file << std::endl;
             return false;
         }
         return true;
@@ -234,11 +245,7 @@ bool Properties::get_or_default(const char* key, const 
char* defstr, T& retval)
     } else {
         valstr = it->second;
     }
-    trim(valstr);
-    if (!replaceenv(valstr)) {
-        return false;
-    }
-    return strtox(valstr, retval);
+    return convert(valstr, retval);
 }
 
 void Properties::set(const std::string& key, const std::string& val) {
@@ -270,16 +277,6 @@ bool Properties::dump(const std::string& conffile) {
 }
 
 template <typename T>
-bool update(const std::string& value, T& retval) {
-    std::string valstr(value);
-    trim(valstr);
-    if (!replaceenv(valstr)) {
-        return false;
-    }
-    return strtox(valstr, retval);
-}
-
-template <typename T>
 std::ostream& operator<<(std::ostream& out, const std::vector<T>& v) {
     size_t last = v.size() - 1;
     for (size_t i = 0; i < v.size(); ++i) {
@@ -291,67 +288,87 @@ std::ostream& operator<<(std::ostream& out, const 
std::vector<T>& v) {
     return out;
 }
 
-#define SET_FIELD(FIELD, TYPE, FILL_CONFMAP, SET_TO_DEFAULT)                   
                \
-    if (strcmp((FIELD).type, #TYPE) == 0) {                                    
                \
-        if (!props.get_or_default((FIELD).name, ((SET_TO_DEFAULT) ? 
(FIELD).defval : nullptr), \
-                                  *reinterpret_cast<TYPE*>((FIELD).storage))) 
{                \
-            std::cerr << "config field error: " << (FIELD).name << std::endl;  
                \
-            return false;                                                      
                \
-        }                                                                      
                \
-        if (FILL_CONFMAP) {                                                    
                \
-            std::ostringstream oss;                                            
                \
-            oss << (*reinterpret_cast<TYPE*>((FIELD).storage));                
                \
-            (*full_conf_map)[(FIELD).name] = oss.str();                        
                \
-        }                                                                      
                \
-        continue;                                                              
                \
+#define SET_FIELD(FIELD, TYPE, FILL_CONF_MAP, SET_TO_DEFAULT)                  
                               \
+    if (strcmp((FIELD).type, #TYPE) == 0) {                                    
                               \
+        TYPE new_value;                                                        
                               \
+        if (!props.get_or_default((FIELD).name, ((SET_TO_DEFAULT) ? 
(FIELD).defval : nullptr), new_value)) {  \
+            std::cerr << "config field error: " << (FIELD).name << std::endl;  
                               \
+            return false;                                                      
                               \
+        }                                                                      
                               \
+        TYPE& ref_conf_value = *reinterpret_cast<TYPE*>((FIELD).storage);      
                               \
+        TYPE old_value = ref_conf_value;                                       
                               \
+        ref_conf_value = new_value;                                            
                               \
+        auto validator = 
RegisterConfValidator::_s_field_validator->find((FIELD).name);                  
     \
+        if (validator != RegisterConfValidator::_s_field_validator->end() && 
!(validator->second)()) {        \
+            ref_conf_value = old_value;                                        
                               \
+            std::cerr << "validate " << (FIELD).name << "=" << new_value << " 
failed" << std::endl;           \
+            return false;                                                      
                               \
+        }                                                                      
                               \
+        if (FILL_CONF_MAP) {                                                   
                               \
+            std::ostringstream oss;                                            
                               \
+            oss << ref_conf_value;                                             
                               \
+            (*full_conf_map)[(FIELD).name] = oss.str();                        
                               \
+        }                                                                      
                               \
+        continue;                                                              
                               \
     }
 
 // init conf fields
-bool init(const char* conf_file, bool fillconfmap, bool must_exist, bool 
set_to_default) {
+bool init(const char* conf_file, bool fill_conf_map, bool must_exist, bool 
set_to_default) {
     Properties props;
     // load properties file
     if (!props.load(conf_file, must_exist)) {
         return false;
     }
     // fill full_conf_map ?
-    if (fillconfmap && full_conf_map == nullptr) {
+    if (fill_conf_map && full_conf_map == nullptr) {
         full_conf_map = new std::map<std::string, std::string>();
     }
 
     // set conf fields
     for (const auto& it : *Register::_s_field_map) {
-        SET_FIELD(it.second, bool, fillconfmap, set_to_default);
-        SET_FIELD(it.second, int16_t, fillconfmap, set_to_default);
-        SET_FIELD(it.second, int32_t, fillconfmap, set_to_default);
-        SET_FIELD(it.second, int64_t, fillconfmap, set_to_default);
-        SET_FIELD(it.second, double, fillconfmap, set_to_default);
-        SET_FIELD(it.second, std::string, fillconfmap, set_to_default);
-        SET_FIELD(it.second, std::vector<bool>, fillconfmap, set_to_default);
-        SET_FIELD(it.second, std::vector<int16_t>, fillconfmap, 
set_to_default);
-        SET_FIELD(it.second, std::vector<int32_t>, fillconfmap, 
set_to_default);
-        SET_FIELD(it.second, std::vector<int64_t>, fillconfmap, 
set_to_default);
-        SET_FIELD(it.second, std::vector<double>, fillconfmap, set_to_default);
-        SET_FIELD(it.second, std::vector<std::string>, fillconfmap, 
set_to_default);
+        SET_FIELD(it.second, bool, fill_conf_map, set_to_default);
+        SET_FIELD(it.second, int16_t, fill_conf_map, set_to_default);
+        SET_FIELD(it.second, int32_t, fill_conf_map, set_to_default);
+        SET_FIELD(it.second, int64_t, fill_conf_map, set_to_default);
+        SET_FIELD(it.second, double, fill_conf_map, set_to_default);
+        SET_FIELD(it.second, std::string, fill_conf_map, set_to_default);
+        SET_FIELD(it.second, std::vector<bool>, fill_conf_map, set_to_default);
+        SET_FIELD(it.second, std::vector<int16_t>, fill_conf_map, 
set_to_default);
+        SET_FIELD(it.second, std::vector<int32_t>, fill_conf_map, 
set_to_default);
+        SET_FIELD(it.second, std::vector<int64_t>, fill_conf_map, 
set_to_default);
+        SET_FIELD(it.second, std::vector<double>, fill_conf_map, 
set_to_default);
+        SET_FIELD(it.second, std::vector<std::string>, fill_conf_map, 
set_to_default);
     }
 
     return true;
 }
 
-#define UPDATE_FIELD(FIELD, VALUE, TYPE, PERSIST)                              
      \
-    if (strcmp((FIELD).type, #TYPE) == 0) {                                    
      \
-        if (!update((VALUE), *reinterpret_cast<TYPE*>((FIELD).storage))) {     
      \
-            return Status::InvalidArgument(                                    
      \
-                    strings::Substitute("convert '$0' as $1 failed", VALUE, 
#TYPE)); \
-        }                                                                      
      \
-        if (full_conf_map != nullptr) {                                        
      \
-            std::ostringstream oss;                                            
      \
-            oss << (*reinterpret_cast<TYPE*>((FIELD).storage));                
      \
-            (*full_conf_map)[(FIELD).name] = oss.str();                        
      \
-        }                                                                      
      \
-        if (PERSIST) {                                                         
      \
-            persist_config(std::string(FIELD.name), VALUE);                    
      \
-        }                                                                      
      \
-        return Status::OK();                                                   
      \
+#define UPDATE_FIELD(FIELD, VALUE, TYPE, PERSIST)                              
                         \
+    if (strcmp((FIELD).type, #TYPE) == 0) {                                    
                         \
+        TYPE new_value;                                                        
                         \
+        if (!convert((VALUE), new_value)) {                                    
                         \
+            return Status::InvalidArgument(                                    
                         \
+                strings::Substitute("convert '$0' as $1 failed", VALUE, 
#TYPE));                        \
+        }                                                                      
                         \
+        TYPE& ref_conf_value = *reinterpret_cast<TYPE*>((FIELD).storage);      
                         \
+        TYPE old_value = ref_conf_value;                                       
                         \
+        ref_conf_value = new_value;                                            
                         \
+        auto validator = 
RegisterConfValidator::_s_field_validator->find((FIELD).name);                 \
+        if (validator != RegisterConfValidator::_s_field_validator->end() && 
!(validator->second)()) {  \
+            ref_conf_value = old_value;                                        
                         \
+            return Status::InvalidArgument(                                    
                         \
+                    strings::Substitute("validate $0=$1 failed", (FIELD).name, 
new_value));             \
+        }                                                                      
                         \
+        ref_conf_value = new_value;                                            
                         \
+        if (full_conf_map != nullptr) {                                        
                         \
+            std::ostringstream oss;                                            
                         \
+            oss << new_value;                                                  
                         \
+            (*full_conf_map)[(FIELD).name] = oss.str();                        
                         \
+        }                                                                      
                         \
+        if (PERSIST) {                                                         
                         \
+            persist_config(std::string((FIELD).name), VALUE);                  
                         \
+        }                                                                      
                         \
+        return Status::OK();                                                   
                         \
     }
 
 // write config to be_custom.conf
diff --git a/be/src/common/configbase.h b/be/src/common/configbase.h
index 80b690c..f6209b7 100644
--- a/be/src/common/configbase.h
+++ b/be/src/common/configbase.h
@@ -18,12 +18,13 @@
 #ifndef DORIS_BE_SRC_COMMON_CONFIGBASE_H
 #define DORIS_BE_SRC_COMMON_CONFIGBASE_H
 
-#include <stdint.h>
+#include <cstdint>
 
 #include <map>
 #include <mutex>
 #include <string>
 #include <vector>
+#include <functional>
 
 namespace doris {
 class Status;
@@ -59,15 +60,43 @@ public:
         Field field(ftype, fname, fstorage, fdefval, fvalmutable);
         _s_field_map->insert(std::make_pair(std::string(fname), field));
     }
+
 };
 
-#define DEFINE_FIELD(FIELD_TYPE, FIELD_NAME, FIELD_DEFAULT, VALMUTABLE)        
            \
-    FIELD_TYPE FIELD_NAME;                                                     
            \
-    static Register reg_##FIELD_NAME(#FIELD_TYPE, #FIELD_NAME, &FIELD_NAME, 
FIELD_DEFAULT, \
+// RegisterConfValidator class is used to store validator function of 
registered config fields in
+// Register::_s_field_map.
+// If any validator return false when BE bootstart, the bootstart will be 
terminated.
+// If validator return false when use http API to update some config, the 
config will not
+// be modified and the API will return failure.
+class RegisterConfValidator {
+public:
+    // Validator for each config name.
+    static std::map<std::string, std::function<bool()>>* _s_field_validator;
+
+public:
+    RegisterConfValidator(const char* fname, const std::function<bool()>& 
validator) {
+        if (_s_field_validator == nullptr) {
+            _s_field_validator = new std::map<std::string, 
std::function<bool()>>();
+        }
+        // register validator to _s_field_validator
+        _s_field_validator->insert(std::make_pair(std::string(fname), 
validator));
+    }
+};
+
+#define DEFINE_FIELD(FIELD_TYPE, FIELD_NAME, FIELD_DEFAULT, VALMUTABLE)        
              \
+    FIELD_TYPE FIELD_NAME;                                                     
              \
+    static Register reg_##FIELD_NAME(#FIELD_TYPE, #FIELD_NAME, &(FIELD_NAME), 
FIELD_DEFAULT, \
                                      VALMUTABLE);
 
 #define DECLARE_FIELD(FIELD_TYPE, FIELD_NAME) extern FIELD_TYPE FIELD_NAME;
 
+#define DEFINE_VALIDATOR(FIELD_NAME, VALIDATOR)                                
            \
+    static auto validator_##FIELD_NAME = VALIDATOR;                            
            \
+    static RegisterConfValidator reg_validator_##FIELD_NAME(#FIELD_NAME,       
            \
+            []() -> bool { return validator_##FIELD_NAME(FIELD_NAME); });
+
+#define DECLARE_VALIDATOR(FIELD_NAME) ;
+
 #ifdef __IN_CONFIGBASE_CPP__
 #define CONF_Bool(name, defaultstr) DEFINE_FIELD(bool, name, defaultstr, false)
 #define CONF_Int16(name, defaultstr) DEFINE_FIELD(int16_t, name, defaultstr, 
false)
@@ -87,6 +116,8 @@ public:
 #define CONF_mInt32(name, defaultstr) DEFINE_FIELD(int32_t, name, defaultstr, 
true)
 #define CONF_mInt64(name, defaultstr) DEFINE_FIELD(int64_t, name, defaultstr, 
true)
 #define CONF_mDouble(name, defaultstr) DEFINE_FIELD(double, name, defaultstr, 
true)
+#define CONF_Validator(name, validator) DEFINE_VALIDATOR(name, validator)
+
 #else
 #define CONF_Bool(name, defaultstr) DECLARE_FIELD(bool, name)
 #define CONF_Int16(name, defaultstr) DECLARE_FIELD(int16_t, name)
@@ -105,18 +136,19 @@ public:
 #define CONF_mInt32(name, defaultstr) DECLARE_FIELD(int32_t, name)
 #define CONF_mInt64(name, defaultstr) DECLARE_FIELD(int64_t, name)
 #define CONF_mDouble(name, defaultstr) DECLARE_FIELD(double, name)
+#define CONF_Validator(name, validator) DECLARE_VALIDATOR(name)
 #endif
 
 // configuration properties load from config file.
 class Properties {
 public:
     // load conf from file, if must_exist is true and file does not exist, 
return false
-    bool load(const char* filename, bool must_exist = true);
-    template <typename T>
+    bool load(const char* conf_file, bool must_exist = true);
 
     // Find the config value by key from `file_conf_map`.
     // If found, set `retval` to the config value,
     // or set `retval` to `defstr`
+    template <typename T>
     bool get_or_default(const char* key, const char* defstr, T& retval) const;
 
     void set(const std::string& key, const std::string& val);
@@ -134,10 +166,10 @@ extern std::map<std::string, std::string>* full_conf_map;
 extern std::mutex custom_conf_lock;
 
 // Init the config from `conf_file`.
-// If fillconfmap is true, the updated config will also update the 
`full_conf_map`.
+// If fill_conf_map is true, the updated config will also update the 
`full_conf_map`.
 // If must_exist is true and `conf_file` does not exist, this function will 
return false.
 // If set_to_default is true, the config value will be set to default value if 
not found in `conf_file`.
-bool init(const char* conf_file, bool fillconfmap = false, bool must_exist = 
true,
+bool init(const char* conf_file, bool fill_conf_map = false, bool must_exist = 
true,
           bool set_to_default = true);
 
 Status set_config(const std::string& field, const std::string& value, bool 
need_persist = false);
diff --git a/be/test/common/CMakeLists.txt b/be/test/common/CMakeLists.txt
index 6589632..1b2dda8 100644
--- a/be/test/common/CMakeLists.txt
+++ b/be/test/common/CMakeLists.txt
@@ -21,3 +21,4 @@ set(EXECUTABLE_OUTPUT_PATH "${BUILD_DIR}/test/common")
 ADD_BE_TEST(resource_tls_test)
 ADD_BE_TEST(status_test)
 ADD_BE_TEST(config_test)
+ADD_BE_TEST(config_validator_test)
diff --git a/be/test/common/config_test.cpp b/be/test/common/config_test.cpp
index 55bc2ce..7d6eb42 100644
--- a/be/test/common/config_test.cpp
+++ b/be/test/common/config_test.cpp
@@ -45,7 +45,7 @@ TEST_F(ConfigTest, DumpAllConfigs) {
     CONF_Int64s(cfg_std_vector_int64_t, 
"4294967296123,4294967296234,4294967296345");
     CONF_Strings(cfg_std_vector_std_string, "doris,config,test,string");
 
-    config::init(nullptr, true);
+    ASSERT_TRUE(config::init(nullptr, true));
     std::stringstream ss;
     for (const auto& it : *(config::full_conf_map)) {
         ss << it.first << "=" << it.second << std::endl;
@@ -69,7 +69,7 @@ TEST_F(ConfigTest, UpdateConfigs) {
     CONF_mInt64(cfg_int64_t, "4294967296123");
     CONF_String(cfg_std_string, "doris_config_test_string");
 
-    config::init(nullptr, true);
+    ASSERT_TRUE(config::init(nullptr, true));
 
     // bool
     ASSERT_FALSE(cfg_bool);
diff --git a/be/test/common/config_validator_test.cpp 
b/be/test/common/config_validator_test.cpp
new file mode 100644
index 0000000..605f7cb
--- /dev/null
+++ b/be/test/common/config_validator_test.cpp
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#define __IN_CONFIGBASE_CPP__
+#include "common/configbase.h"
+#undef __IN_CONFIGBASE_CPP__
+
+#include <gtest/gtest.h>
+
+#include "common/status.h"
+
+namespace doris {
+using namespace config;
+
+CONF_mInt16(cfg_validator_1, "15");
+CONF_Validator(cfg_validator_1, [](int16_t config) -> bool {
+    return 0 <= config && config <= 10;
+});
+
+CONF_mInt16(cfg_validator_2, "5");
+CONF_Validator(cfg_validator_2, [](int16_t config) -> bool {
+    return 0 <= config && config <= 10;
+});
+
+TEST(ConfigValidatorTest, Validator) {
+    ASSERT_FALSE(config::init(nullptr, true));
+    config::Register::_s_field_map->erase("cfg_validator_1");
+
+    ASSERT_TRUE(config::init(nullptr, true));
+
+    Status s = config::set_config("cfg_validator_2", "15");
+    ASSERT_FALSE(s.ok());
+    ASSERT_EQ(s.to_string(), "Invalid argument: validate cfg_validator_2=15 
failed");
+    ASSERT_EQ(cfg_validator_2, 5);
+
+    s = config::set_config("cfg_validator_2", "8");
+    ASSERT_TRUE(s.ok());
+    ASSERT_EQ(cfg_validator_2, 8);
+}
+} // namespace doris
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/be/test/runtime/result_queue_mgr_test.cpp 
b/be/test/runtime/result_queue_mgr_test.cpp
index b077858..d04040d 100644
--- a/be/test/runtime/result_queue_mgr_test.cpp
+++ b/be/test/runtime/result_queue_mgr_test.cpp
@@ -22,6 +22,7 @@
 #include <arrow/record_batch.h>
 #include <arrow/type.h>
 #include <gtest/gtest.h>
+#include <test_util/test_util.h>
 
 #include <memory>
 
@@ -138,12 +139,8 @@ TEST_F(ResultQueueMgrTest, cancel_no_block) {
 } // namespace doris
 
 int main(int argc, char** argv) {
-    std::string conffile = std::string(getenv("DORIS_HOME")) + "/conf/be.conf";
-    if (!doris::config::init(conffile.c_str(), false)) {
-        fprintf(stderr, "error read config file. \n");
-        return -1;
-    }
-    // doris::init_glog("be-test");
+    doris::InitConfig();
+
     ::testing::InitGoogleTest(&argc, argv);
     doris::CpuInfo::init();
     return RUN_ALL_TESTS();
diff --git a/be/test/test_util/CMakeLists.txt b/be/test/test_util/CMakeLists.txt
index b9f37ee..2d80269 100644
--- a/be/test/test_util/CMakeLists.txt
+++ b/be/test/test_util/CMakeLists.txt
@@ -26,4 +26,4 @@ add_library(Test_util STATIC
     ${TEST_UTIL_FILES}
 )
 
-target_link_libraries(Test_util Gutil glog gflags)
+target_link_libraries(Test_util Common Util Gutil ${Boost_LIBRARIES} glog 
gflags protobuf)
diff --git a/be/test/test_util/test_util.cpp b/be/test/test_util/test_util.cpp
index fb78e10..be118cd 100644
--- a/be/test/test_util/test_util.cpp
+++ b/be/test/test_util/test_util.cpp
@@ -17,9 +17,10 @@
 
 #include "test_util/test_util.h"
 
+#include <common/configbase.h>
 #include <libgen.h>
 #include <linux/limits.h>
-#include <stdlib.h>
+#include <cstdlib>
 #include <strings.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -65,4 +66,12 @@ std::string GetCurrentRunningDir() {
     return std::string(dir);
 }
 
+void InitConfig() {
+    std::string conf_file = std::string(getenv("DORIS_HOME")) + 
"/conf/be.conf";
+    if (!config::init(conf_file.c_str(), false)) {
+        fprintf(stderr, "Init config file failed, path %s\n", 
conf_file.c_str());
+        exit(-1);
+    }
+}
+
 } // namespace doris
diff --git a/be/test/test_util/test_util.h b/be/test/test_util/test_util.h
index ae4ff85..738adb5 100644
--- a/be/test/test_util/test_util.h
+++ b/be/test/test_util/test_util.h
@@ -33,4 +33,7 @@ bool AllowSlowTests();
 // Empty string if get errors.
 std::string GetCurrentRunningDir();
 
+// Initialize config file.
+void InitConfig();
+
 } // namespace doris


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to