// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <sstream> #include <string> #include <cstdlib> #include <ctime> #include <dlib/config_reader.h> #include <dlib/cmd_line_parser.h> #include "tester.h" // This is called an unnamed-namespace and it has the effect of making everything inside this file "private" // so that everything you declare will have static linkage. Thus we won't have any multiply // defined symbol errors coming out of the linker when we try to compile the test suite. namespace { using namespace test; using namespace dlib; using namespace std; // Declare the logger we will use in this test. The name of the tester // should start with "test." logger dlog("test.config_reader"); template < typename config_reader > void do_the_tests ( config_reader& cr ) { DLIB_TEST(cr.is_key_defined("global")); DLIB_TEST(cr.is_block_defined("all")); DLIB_TEST(cr.is_key_defined("globalasfd") == false); DLIB_TEST(cr.is_block_defined("all!") == false); DLIB_TEST(cr["global"] == "hmm"); DLIB_TEST(cr["global2"] == "hmm2"); std_vector_c<string> blocks; cr.block("all").get_blocks(blocks); DLIB_TEST(blocks.size() == 4); cr.block("all").block("block1").get_blocks(blocks); DLIB_TEST(blocks.size() == 0); cr.block("all").block("block2").get_blocks(blocks); DLIB_TEST(blocks.size() == 0); cr.block("all").block("block3").get_blocks(blocks); DLIB_TEST(blocks.size() == 0); cr.block("all").block("block4").get_blocks(blocks); DLIB_TEST(blocks.size() == 0); DLIB_TEST(cr.block("all").block("block1").is_key_defined("name")); DLIB_TEST(cr.block("all").block("block2").is_key_defined("name")); DLIB_TEST(cr.block("all").block("block3").is_key_defined("name")); DLIB_TEST(cr.block("all").block("block4").is_key_defined("name")); DLIB_TEST(cr.block("all").block("block1").is_key_defined("age")); DLIB_TEST(cr.block("all").block("block2").is_key_defined("age")); DLIB_TEST(cr.block("all").block("block3").is_key_defined("age")); DLIB_TEST(cr.block("all").block("block4").is_key_defined("age")); DLIB_TEST(cr.block("all").block("block1")["name"] == "davis king"); DLIB_TEST(cr.block("all").block("block2")["name"] == "joel"); DLIB_TEST(cr.block("all").block("block3")["name"] == "john"); DLIB_TEST(cr.block("all").block("block4")["name"] == "dude"); DLIB_TEST(cr.block("all").block("block1")["age"] == "24"); DLIB_TEST(cr.block("all").block("block2")["age"] == "24"); DLIB_TEST(cr.block("all").block("block3")["age"] == "24"); DLIB_TEST(cr.block("all").block("block4")["age"] == "53"); int count2 = 0; cr.get_blocks(blocks); DLIB_TEST(blocks.size() == 1); DLIB_TEST(blocks[0] == "all"); DLIB_TEST(cr.block("all").is_key_defined("global") == false); DLIB_TEST(cr.block("all").is_key_defined("global2") == false); DLIB_TEST(cr.block("all").is_key_defined("name") == false); DLIB_TEST(cr.block("all").is_key_defined("age") == false); cr.block("all").get_blocks(blocks); DLIB_TEST(blocks.size() == 4); std::vector<string> temp_blocks; for (unsigned long i = 0; i < blocks.size(); ++i) { ++count2; ostringstream sout; sout << "block" << count2; DLIB_TEST(blocks[i] == sout.str()); cr.block("all").block(blocks[i]).get_blocks(temp_blocks); DLIB_TEST(temp_blocks.size() == 0); DLIB_TEST(cr.block("all").block(blocks[i]).is_key_defined("name")); DLIB_TEST(cr.block("all").block(blocks[i]).is_key_defined("age")); } bool found_error = false; try { cr.block("bogus_block"); } catch (typename config_reader::config_reader_access_error& e) { DLIB_TEST(e.block_name == "bogus_block"); DLIB_TEST(e.key_name == ""); found_error = true; } DLIB_TEST(found_error); found_error = false; try { cr["bogus_key"]; } catch (typename config_reader::config_reader_access_error& e) { DLIB_TEST(e.block_name == ""); DLIB_TEST(e.key_name == "bogus_key"); found_error = true; } DLIB_TEST(found_error); found_error = false; try { cr.block("all").block("block10"); } catch (typename config_reader::config_reader_access_error& e) { DLIB_TEST(e.block_name == "block10"); DLIB_TEST(e.key_name == ""); found_error = true; } DLIB_TEST(found_error); found_error = false; try { cr.block("all")["msdofg"]; } catch (typename config_reader::config_reader_access_error& e) { DLIB_TEST(e.block_name == ""); DLIB_TEST(e.key_name == "msdofg"); found_error = true; } DLIB_TEST(found_error); } template < typename config_reader > void config_reader_test ( ) /*! requires - config_reader is an implementation of config_reader/config_reader_kernel_abstract.h is instantiated with int ensures - runs tests on config_reader for compliance with the specs !*/ { ostringstream sout; sout << "all#comment { { } \n"; sout << "{ \n"; sout << " block1 \n"; sout << " { \n"; sout << " name = davis king \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " \n"; sout << " block2 \n"; sout << " { \n"; sout << " name= joel \n"; sout << " age =24 \n"; sout << " } \n"; sout << " \n"; sout << " block3 \n"; sout << " { \n"; sout << " name = john \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " #comment \n"; sout << "#comment \n"; sout << " block4{ # comment"; sout << " \n"; sout << " name = dude \n"; sout << " age = 53}\n"; sout << " \n"; sout << "} \n"; sout << " \n"; sout << " \n"; sout << "global=hmm#comment \n"; sout << "global2=hmm2 \n"; sout << " # comment \n"; string data = sout.str(); config_reader cr2; for (int i = 0; i < 3; ++i) { istringstream sin; sin.clear(); sin.str(data); config_reader cr(sin); sin.clear(); sin.str(data); cr2.load_from(sin); do_the_tests(cr); do_the_tests(cr2); cr.clear(); DLIB_TEST(cr.is_key_defined("global") == false); } sout.clear(); sout.str(""); { sout << "all#comment { { } \n"; sout << "{ \n"; sout << " block1 \n"; sout << " { \n"; sout << " name = davis king \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " \n"; sout << " block2 \n"; sout << " { \n"; sout << " name= joel \n"; sout << " age =24 \n"; sout << " } \n"; sout << " \n"; sout << " block3 \n"; sout << " {{ \n"; // error on this line sout << " name = john \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " #comment \n"; sout << "#comment \n"; sout << " block4{ # comment"; sout << " \n"; sout << " name = dude \n"; sout << " age = 53}\n"; sout << " \n"; sout << "} \n"; sout << " \n"; sout << " \n"; sout << "global=hmm#comment \n"; sout << "global2=hmm2 \n"; sout << " # comment \n"; istringstream sin(sout.str()); bool error_found = false; try { cr2.load_from(sin); } catch (typename config_reader::config_reader_error& e) { error_found = true; DLIB_TEST(e.line_number == 16); DLIB_TEST(e.redefinition == false); } DLIB_TEST(error_found); } { sout.str(""); sout.clear(); sout << "all#comment { { } \n"; sout << "{ \n"; sout << " block1 \n"; sout << " { \n"; sout << " name = davis king \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " \n"; sout << " block2 \n"; sout << " { \n"; sout << " name= joel \n"; sout << " age =24 \n"; sout << " } \n"; sout << " \n"; sout << " block3 \n"; sout << " { \n"; sout << " name = john \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " #comment \n"; sout << "#comment \n"; sout << " block4{ # comment"; sout << " \n"; sout << " name = dude \n"; sout << " age = 53}\n"; sout << " \n"; sout << "} \n"; sout << " \n"; sout << " \n"; sout << "global=hmm#comment \n"; sout << " \n"; sout << "global=hmm2 \n"; // error on this line sout << " # comment \n"; istringstream sin(sout.str()); bool error_found = false; try { cr2.load_from(sin); } catch (typename config_reader::config_reader_error& e) { error_found = true; DLIB_TEST_MSG(e.line_number == 31,e.line_number); DLIB_TEST(e.redefinition == true); } DLIB_TEST(error_found); } { sout.str(""); sout.clear(); sout << "all#comment { { } \n"; sout << "{ \n"; sout << " block1 \n"; sout << " { \n"; sout << " name = davis king \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " \n"; sout << " block2 \n"; sout << " { \n"; sout << " name= joel \n"; sout << " age =24 \n"; sout << " } block2{} \n"; // error on this line sout << " \n"; sout << " block3 \n"; sout << " { \n"; sout << " name = john \n"; sout << " age = 24 \n"; sout << " } \n"; sout << " #comment \n"; sout << "#comment \n"; sout << " block4{ # comment"; sout << " \n"; sout << " name = dude \n"; sout << " age = 53}\n"; sout << " \n"; sout << "} \n"; sout << " \n"; sout << " \n"; sout << "global=hmm#comment \n"; sout << " \n"; sout << " # comment \n"; istringstream sin(sout.str()); bool error_found = false; try { cr2.load_from(sin); } catch (typename config_reader::config_reader_error& e) { error_found = true; DLIB_TEST_MSG(e.line_number == 13,e.line_number); DLIB_TEST(e.redefinition == true); } DLIB_TEST(error_found); } } void test_get_option() { const char* argv[100]; int argc; // program --opt 4 -d dude argv[0] = "program"; argv[1] = "--opt"; argv[2] = "4"; argv[3] = "-d"; argv[4] = "dude"; argc = 5; std::ostringstream sout; sout << "block#comment { { } \n"; sout << "{ \n"; sout << " opt = 5 \n"; sout << " a = 6 \n"; sout << " d = joel \n"; sout << " subblock {} \n"; sout << "} \n"; sout << " \n"; sout << " \n"; sout << "opt = 8 \n"; sout << "d = davis \n"; sout << "a = 50 \n"; sout << " # comment \n"; std::istringstream sin(sout.str()); config_reader cr(sin); dlib::cmd_line_parser<char>::kernel_1a_c parser; parser.add_option("opt","",1); parser.add_option("d","",1); parser.add_option("a","",1); parser.add_option("b","",1); parser.parse(argc, argv); DLIB_TEST(get_option(cr, "d", "default") == "davis"); DLIB_TEST(get_option(cr, "opt", "default") == "8"); DLIB_TEST(get_option(cr, "opt", 1) == 8); DLIB_TEST(get_option(cr, "optasdf", 1) == 1); DLIB_TEST(get_option(cr, "optasdf", 1.1) == 1.1); DLIB_TEST(get_option(cr.block("block"), "d", "default") == "joel"); DLIB_TEST(get_option(cr.block("block"), "opt", "default") == "5"); DLIB_TEST(get_option(cr.block("block"), "opt", 1) == 5); DLIB_TEST(get_option(cr.block("block").block("subblock"), "d", "default") == "default"); DLIB_TEST(get_option(cr.block("block").block("subblock"), "opt", "default") == "default"); DLIB_TEST(get_option(cr.block("block").block("subblock"), "opt", 1) == 1); DLIB_TEST(get_option(cr, "block.d", "default") == "joel"); DLIB_TEST(get_option(cr, "block.opt", "default") == "5"); DLIB_TEST(get_option(cr, "block.opt", 1) == 5); DLIB_TEST(get_option(cr, "block.asdf.d", "default") == "default"); DLIB_TEST(get_option(cr, "block.asdf.opt", "default") == "default"); DLIB_TEST(get_option(cr, "block.asdf.opt", 2) == 2); DLIB_TEST(get_option(cr, "block.subblock.d", "default") == "default"); DLIB_TEST(get_option(cr, "block.subblock.opt", "default") == "default"); DLIB_TEST(get_option(cr, "block.subblock.opt", 2) == 2); DLIB_TEST(get_option(parser, "opt", 99) == 4); DLIB_TEST(get_option(parser, "d", "stuff") == "dude"); DLIB_TEST(get_option(parser, "a", "stuff") == "stuff"); DLIB_TEST(get_option(parser, "a", 99) == 99); DLIB_TEST(get_option(parser, cr, "d", "default") == "dude"); DLIB_TEST(get_option(cr, parser, "d", "default") == "dude"); DLIB_TEST(get_option(parser, cr, "a", 2) == 50); DLIB_TEST(get_option(cr, parser, "a", 2) == 50); DLIB_TEST(get_option(parser, cr, "opt", 2) == 4); DLIB_TEST(get_option(cr, parser, "opt", 2) == 4); DLIB_TEST(get_option(parser, cr, "b", 2) == 2); DLIB_TEST(get_option(cr, parser, "b", 2) == 2); DLIB_TEST(get_option(parser, cr.block("block"), "a", 2) == 6); DLIB_TEST(get_option(cr.block("block"), parser, "a", 2) == 6); } class config_reader_tester : public tester { /*! WHAT THIS OBJECT REPRESENTS This object represents a test for the config_reader object. When it is constructed it adds itself into the testing framework. The command line switch is specified as test_config_reader by passing that string to the tester constructor. !*/ public: config_reader_tester ( ) : tester ("test_config_reader", "Runs tests on the config_reader component.") {} void perform_test ( ) { dlog << LINFO << "testing config_reader"; print_spinner(); config_reader_test<config_reader>(); dlog << LINFO << "testing config_reader_thread_safe"; print_spinner(); config_reader_test<config_reader_thread_safe>(); dlog << LINFO << "testing get_option()"; print_spinner(); test_get_option(); } } a; }