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