getarg_tests.cpp
1 // Copyright (c) 2012-2022 The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <common/args.h> 6 #include <common/settings.h> 7 #include <logging.h> 8 #include <test/util/setup_common.h> 9 #include <univalue.h> 10 #include <util/strencodings.h> 11 12 #include <limits> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 17 #include <boost/test/unit_test.hpp> 18 19 using util::SplitString; 20 21 BOOST_FIXTURE_TEST_SUITE(getarg_tests, BasicTestingSetup) 22 23 void ResetArgs(ArgsManager& local_args, const std::string& strArg) 24 { 25 std::vector<std::string> vecArg; 26 if (strArg.size()) { 27 vecArg = SplitString(strArg, ' '); 28 } 29 30 // Insert dummy executable name: 31 vecArg.insert(vecArg.begin(), "testbitcoin"); 32 33 // Convert to char*: 34 std::vector<const char*> vecChar; 35 vecChar.reserve(vecArg.size()); 36 for (const std::string& s : vecArg) 37 vecChar.push_back(s.c_str()); 38 39 std::string error; 40 BOOST_CHECK(local_args.ParseParameters(vecChar.size(), vecChar.data(), error)); 41 } 42 43 void SetupArgs(ArgsManager& local_args, const std::vector<std::pair<std::string, unsigned int>>& args) 44 { 45 for (const auto& arg : args) { 46 local_args.AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS); 47 } 48 } 49 50 // Test behavior of GetArg functions when string, integer, and boolean types 51 // are specified in the settings.json file. GetArg functions are convenience 52 // functions. The GetSetting method can always be used instead of GetArg 53 // methods to retrieve original values, and there's not always an objective 54 // answer to what GetArg behavior is best in every case. This test makes sure 55 // there's test coverage for whatever the current behavior is, so it's not 56 // broken or changed unintentionally. 57 BOOST_AUTO_TEST_CASE(setting_args) 58 { 59 ArgsManager args; 60 SetupArgs(args, {{"-foo", ArgsManager::ALLOW_ANY}}); 61 62 auto set_foo = [&](const common::SettingsValue& value) { 63 args.LockSettings([&](common::Settings& settings) { 64 settings.rw_settings["foo"] = value; 65 }); 66 }; 67 68 set_foo("str"); 69 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"str\""); 70 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "str"); 71 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0); 72 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false); 73 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false); 74 75 set_foo("99"); 76 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"99\""); 77 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "99"); 78 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 99); 79 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true); 80 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true); 81 82 set_foo("3.25"); 83 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"3.25\""); 84 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "3.25"); 85 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 3); 86 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true); 87 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true); 88 89 set_foo("0"); 90 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"0\""); 91 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0"); 92 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0); 93 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false); 94 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false); 95 96 set_foo(""); 97 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"\""); 98 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), ""); 99 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0); 100 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true); 101 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true); 102 103 set_foo(99); 104 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "99"); 105 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "99"); 106 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 99); 107 BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); 108 BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); 109 110 set_foo(3.25); 111 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "3.25"); 112 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "3.25"); 113 BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error); 114 BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); 115 BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); 116 117 set_foo(0); 118 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "0"); 119 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0"); 120 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0); 121 BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); 122 BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); 123 124 set_foo(true); 125 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "true"); 126 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "1"); 127 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 1); 128 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true); 129 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true); 130 131 set_foo(false); 132 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "false"); 133 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0"); 134 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0); 135 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false); 136 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false); 137 138 set_foo(UniValue::VOBJ); 139 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "{}"); 140 BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error); 141 BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error); 142 BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); 143 BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); 144 145 set_foo(UniValue::VARR); 146 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "[]"); 147 BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error); 148 BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error); 149 BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); 150 BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); 151 152 set_foo(UniValue::VNULL); 153 BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "null"); 154 BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "default"); 155 BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 100); 156 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true); 157 BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false); 158 } 159 160 BOOST_AUTO_TEST_CASE(boolarg) 161 { 162 ArgsManager local_args; 163 164 const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY); 165 SetupArgs(local_args, {foo}); 166 ResetArgs(local_args, "-foo"); 167 BOOST_CHECK(local_args.GetBoolArg("-foo", false)); 168 BOOST_CHECK(local_args.GetBoolArg("-foo", true)); 169 170 BOOST_CHECK(!local_args.GetBoolArg("-fo", false)); 171 BOOST_CHECK(local_args.GetBoolArg("-fo", true)); 172 173 BOOST_CHECK(!local_args.GetBoolArg("-fooo", false)); 174 BOOST_CHECK(local_args.GetBoolArg("-fooo", true)); 175 176 ResetArgs(local_args, "-foo=0"); 177 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 178 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 179 180 ResetArgs(local_args, "-foo=1"); 181 BOOST_CHECK(local_args.GetBoolArg("-foo", false)); 182 BOOST_CHECK(local_args.GetBoolArg("-foo", true)); 183 184 // New 0.6 feature: auto-map -nosomething to !-something: 185 ResetArgs(local_args, "-nofoo"); 186 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 187 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 188 189 ResetArgs(local_args, "-nofoo=1"); 190 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 191 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 192 193 ResetArgs(local_args, "-foo -nofoo"); // -nofoo should win 194 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 195 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 196 197 ResetArgs(local_args, "-foo=1 -nofoo=1"); // -nofoo should win 198 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 199 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 200 201 ResetArgs(local_args, "-foo=0 -nofoo=0"); // -nofoo=0 should win 202 BOOST_CHECK(local_args.GetBoolArg("-foo", false)); 203 BOOST_CHECK(local_args.GetBoolArg("-foo", true)); 204 205 // New 0.6 feature: treat -- same as -: 206 ResetArgs(local_args, "--foo=1"); 207 BOOST_CHECK(local_args.GetBoolArg("-foo", false)); 208 BOOST_CHECK(local_args.GetBoolArg("-foo", true)); 209 210 ResetArgs(local_args, "--nofoo=1"); 211 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 212 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 213 } 214 215 BOOST_AUTO_TEST_CASE(stringarg) 216 { 217 ArgsManager local_args; 218 219 const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY); 220 const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY); 221 SetupArgs(local_args, {foo, bar}); 222 ResetArgs(local_args, ""); 223 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), ""); 224 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "eleven"); 225 226 ResetArgs(local_args, "-foo -bar"); 227 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), ""); 228 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), ""); 229 230 ResetArgs(local_args, "-foo="); 231 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), ""); 232 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), ""); 233 234 ResetArgs(local_args, "-foo=11"); 235 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "11"); 236 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "11"); 237 238 ResetArgs(local_args, "-foo=eleven"); 239 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "eleven"); 240 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "eleven"); 241 } 242 243 BOOST_AUTO_TEST_CASE(intarg) 244 { 245 ArgsManager local_args; 246 247 const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY); 248 const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY); 249 SetupArgs(local_args, {foo, bar}); 250 ResetArgs(local_args, ""); 251 BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 11), 11); 252 BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), 0); 253 254 ResetArgs(local_args, "-foo -bar"); 255 BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 11), 0); 256 BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 0); 257 258 // Check under-/overflow behavior. 259 ResetArgs(local_args, "-foo=-9223372036854775809 -bar=9223372036854775808"); 260 BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), std::numeric_limits<int64_t>::min()); 261 BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 0), std::numeric_limits<int64_t>::max()); 262 263 ResetArgs(local_args, "-foo=11 -bar=12"); 264 BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), 11); 265 BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 12); 266 267 ResetArgs(local_args, "-foo=NaN -bar=NotANumber"); 268 BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 1), 0); 269 BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 0); 270 } 271 272 BOOST_AUTO_TEST_CASE(patharg) 273 { 274 ArgsManager local_args; 275 276 const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY); 277 SetupArgs(local_args, {dir}); 278 ResetArgs(local_args, ""); 279 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), fs::path{}); 280 281 const fs::path root_path{"/"}; 282 ResetArgs(local_args, "-dir=/"); 283 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path); 284 285 ResetArgs(local_args, "-dir=/."); 286 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path); 287 288 ResetArgs(local_args, "-dir=/./"); 289 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path); 290 291 ResetArgs(local_args, "-dir=/.//"); 292 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path); 293 294 #ifdef WIN32 295 const fs::path win_root_path{"C:\\"}; 296 ResetArgs(local_args, "-dir=C:\\"); 297 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path); 298 299 ResetArgs(local_args, "-dir=C:/"); 300 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path); 301 302 ResetArgs(local_args, "-dir=C:\\\\"); 303 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path); 304 305 ResetArgs(local_args, "-dir=C:\\."); 306 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path); 307 308 ResetArgs(local_args, "-dir=C:\\.\\"); 309 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path); 310 311 ResetArgs(local_args, "-dir=C:\\.\\\\"); 312 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path); 313 #endif 314 315 const fs::path absolute_path{"/home/user/.bitcoin"}; 316 ResetArgs(local_args, "-dir=/home/user/.bitcoin"); 317 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 318 319 ResetArgs(local_args, "-dir=/root/../home/user/.bitcoin"); 320 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 321 322 ResetArgs(local_args, "-dir=/home/./user/.bitcoin"); 323 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 324 325 ResetArgs(local_args, "-dir=/home/user/.bitcoin/"); 326 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 327 328 ResetArgs(local_args, "-dir=/home/user/.bitcoin//"); 329 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 330 331 ResetArgs(local_args, "-dir=/home/user/.bitcoin/."); 332 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 333 334 ResetArgs(local_args, "-dir=/home/user/.bitcoin/./"); 335 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 336 337 ResetArgs(local_args, "-dir=/home/user/.bitcoin/.//"); 338 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path); 339 340 const fs::path relative_path{"user/.bitcoin"}; 341 ResetArgs(local_args, "-dir=user/.bitcoin"); 342 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 343 344 ResetArgs(local_args, "-dir=somewhere/../user/.bitcoin"); 345 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 346 347 ResetArgs(local_args, "-dir=user/./.bitcoin"); 348 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 349 350 ResetArgs(local_args, "-dir=user/.bitcoin/"); 351 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 352 353 ResetArgs(local_args, "-dir=user/.bitcoin//"); 354 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 355 356 ResetArgs(local_args, "-dir=user/.bitcoin/."); 357 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 358 359 ResetArgs(local_args, "-dir=user/.bitcoin/./"); 360 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 361 362 ResetArgs(local_args, "-dir=user/.bitcoin/.//"); 363 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path); 364 365 // Check negated and default argument handling. Specifying an empty argument 366 // is the same as not specifying the argument. This is convenient for 367 // scripting so later command line arguments can override earlier command 368 // line arguments or bitcoin.conf values. Currently the -dir= case cannot be 369 // distinguished from -dir case with no assignment, but #16545 would add the 370 // ability to distinguish these in the future (and treat the no-assign case 371 // like an imperative command or an error). 372 ResetArgs(local_args, ""); 373 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"}); 374 ResetArgs(local_args, "-dir=override"); 375 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"override"}); 376 ResetArgs(local_args, "-dir="); 377 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"}); 378 ResetArgs(local_args, "-dir"); 379 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"}); 380 ResetArgs(local_args, "-nodir"); 381 BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{""}); 382 } 383 384 BOOST_AUTO_TEST_CASE(doubledash) 385 { 386 ArgsManager local_args; 387 388 const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY); 389 const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY); 390 SetupArgs(local_args, {foo, bar}); 391 ResetArgs(local_args, "--foo"); 392 BOOST_CHECK_EQUAL(local_args.GetBoolArg("-foo", false), true); 393 394 ResetArgs(local_args, "--foo=verbose --bar=1"); 395 BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "verbose"); 396 BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 0), 1); 397 } 398 399 BOOST_AUTO_TEST_CASE(boolargno) 400 { 401 ArgsManager local_args; 402 403 const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY); 404 const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY); 405 SetupArgs(local_args, {foo, bar}); 406 ResetArgs(local_args, "-nofoo"); 407 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 408 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 409 410 ResetArgs(local_args, "-nofoo=1"); 411 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 412 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 413 414 ResetArgs(local_args, "-nofoo=0"); 415 BOOST_CHECK(local_args.GetBoolArg("-foo", true)); 416 BOOST_CHECK(local_args.GetBoolArg("-foo", false)); 417 418 ResetArgs(local_args, "-foo --nofoo"); // --nofoo should win 419 BOOST_CHECK(!local_args.GetBoolArg("-foo", true)); 420 BOOST_CHECK(!local_args.GetBoolArg("-foo", false)); 421 422 ResetArgs(local_args, "-nofoo -foo"); // foo always wins: 423 BOOST_CHECK(local_args.GetBoolArg("-foo", true)); 424 BOOST_CHECK(local_args.GetBoolArg("-foo", false)); 425 } 426 427 BOOST_AUTO_TEST_CASE(logargs) 428 { 429 ArgsManager local_args; 430 431 const auto okaylog_bool = std::make_pair("-okaylog-bool", ArgsManager::ALLOW_ANY); 432 const auto okaylog_negbool = std::make_pair("-okaylog-negbool", ArgsManager::ALLOW_ANY); 433 const auto okaylog = std::make_pair("-okaylog", ArgsManager::ALLOW_ANY); 434 const auto dontlog = std::make_pair("-dontlog", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE); 435 SetupArgs(local_args, {okaylog_bool, okaylog_negbool, okaylog, dontlog}); 436 ResetArgs(local_args, "-okaylog-bool -nookaylog-negbool -okaylog=public -dontlog=private42"); 437 438 // Everything logged to debug.log will also append to str 439 std::string str; 440 auto print_connection = LogInstance().PushBackCallback( 441 [&str](const std::string& s) { 442 str += s; 443 }); 444 445 // Log the arguments 446 local_args.LogArgs(); 447 448 LogInstance().DeleteCallback(print_connection); 449 // Check that what should appear does, and what shouldn't doesn't. 450 BOOST_CHECK(str.find("Command-line arg: okaylog-bool=\"\"") != std::string::npos); 451 BOOST_CHECK(str.find("Command-line arg: okaylog-negbool=false") != std::string::npos); 452 BOOST_CHECK(str.find("Command-line arg: okaylog=\"public\"") != std::string::npos); 453 BOOST_CHECK(str.find("dontlog=****") != std::string::npos); 454 BOOST_CHECK(str.find("private42") == std::string::npos); 455 } 456 457 BOOST_AUTO_TEST_SUITE_END()