LCOV - code coverage report
Current view: top level - tests - catch_resources.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 539 725 74.3 %
Date: 2023-07-29 22:00:24 Functions: 11 12 91.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/as2js
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : 
      19             : // as2js
      20             : //
      21             : // the resources.h is private hence the use of "..."
      22             : //
      23             : #include    "as2js/file/resources.h"
      24             : 
      25             : #include    <as2js/exception.h>
      26             : #include    <as2js/message.h>
      27             : 
      28             : 
      29             : 
      30             : // self
      31             : //
      32             : #include    "catch_main.h"
      33             : 
      34             : 
      35             : // snapdev
      36             : //
      37             : #include    <snapdev/mkdir_p.h>
      38             : #include    <snapdev/safe_setenv.h>
      39             : 
      40             : 
      41             : // C++
      42             : //
      43             : #include    <cstring>
      44             : 
      45             : 
      46             : // C
      47             : //
      48             : #include    <sys/stat.h>
      49             : #include    <unistd.h>
      50             : 
      51             : 
      52             : // last include
      53             : //
      54             : #include    <snapdev/poison.h>
      55             : 
      56             : 
      57             : 
      58             : 
      59             : namespace
      60             : {
      61             : 
      62             : 
      63             : class test_callback
      64             :     : public as2js::message_callback
      65             : {
      66             : public:
      67           4 :     test_callback()
      68           4 :     {
      69           4 :         as2js::set_message_callback(this);
      70           4 :         g_warning_count = as2js::warning_count();
      71           4 :         g_error_count = as2js::error_count();
      72           4 :     }
      73             : 
      74           4 :     ~test_callback()
      75           4 :     {
      76             :         // make sure the pointer gets reset!
      77           4 :         as2js::set_message_callback(nullptr);
      78           4 :     }
      79             : 
      80             :     // implementation of the output
      81          10 :     virtual void output(as2js::message_level_t message_level, as2js::err_code_t error_code, as2js::position const& pos, std::string const& message)
      82             :     {
      83          10 :         if(f_expected.empty())
      84             :         {
      85           0 :             std::cerr << "\nfilename = " << pos.get_filename() << "\n";
      86           0 :             std::cerr << "msg = " << message << "\n";
      87           0 :             std::cerr << "page = " << pos.get_page() << "\n";
      88           0 :             std::cerr << "line = " << pos.get_line() << "\n";
      89           0 :             std::cerr << "error_code = " << static_cast<int>(error_code) << "\n";
      90             :         }
      91             : 
      92          10 :         CATCH_REQUIRE(!f_expected.empty());
      93             : 
      94             : //std::cerr << "filename = " << pos.get_filename() << " / " << f_expected[0].f_pos.get_filename() << "\n";
      95             : //std::cerr << "msg = " << message << " / " << f_expected[0].f_message << "\n";
      96             : //std::cerr << "page = " << pos.get_page() << " / " << f_expected[0].f_pos.get_page() << "\n";
      97             : //std::cerr << "line = " << pos.get_line() << " / " << f_expected[0].f_pos.get_line() << "\n";
      98             : //std::cerr << "error_code = " << static_cast<int>(error_code) << " / " << static_cast<int>(f_expected[0].f_error_code) << "\n";
      99             : 
     100          10 :         CATCH_REQUIRE(f_expected[0].f_call);
     101          10 :         CATCH_REQUIRE(message_level == f_expected[0].f_message_level);
     102          10 :         CATCH_REQUIRE(error_code == f_expected[0].f_error_code);
     103          10 :         CATCH_REQUIRE(pos.get_filename() == f_expected[0].f_pos.get_filename());
     104          10 :         CATCH_REQUIRE(pos.get_function() == f_expected[0].f_pos.get_function());
     105          10 :         CATCH_REQUIRE(pos.get_page() == f_expected[0].f_pos.get_page());
     106          10 :         CATCH_REQUIRE(pos.get_page_line() == f_expected[0].f_pos.get_page_line());
     107          10 :         CATCH_REQUIRE(pos.get_paragraph() == f_expected[0].f_pos.get_paragraph());
     108          10 :         CATCH_REQUIRE(pos.get_line() == f_expected[0].f_pos.get_line());
     109          10 :         CATCH_REQUIRE(message == f_expected[0].f_message);
     110             : 
     111          10 :         if(message_level == as2js::message_level_t::MESSAGE_LEVEL_WARNING)
     112             :         {
     113           0 :             ++g_warning_count;
     114           0 :             CATCH_REQUIRE(g_warning_count == as2js::warning_count());
     115             :         }
     116             : 
     117          10 :         if(message_level == as2js::message_level_t::MESSAGE_LEVEL_FATAL
     118           0 :         || message_level == as2js::message_level_t::MESSAGE_LEVEL_ERROR)
     119             :         {
     120          10 :             ++g_error_count;
     121             : //std::cerr << "error: " << g_error_count << " / " << as2js::error_count() << "\n";
     122          10 :             CATCH_REQUIRE(g_error_count == as2js::error_count());
     123             :         }
     124             : 
     125          10 :         f_expected.erase(f_expected.begin());
     126          10 :     }
     127             : 
     128          10 :     void got_called()
     129             :     {
     130          10 :         if(!f_expected.empty())
     131             :         {
     132           0 :             std::cerr << "\n*** STILL EXPECTED: ***\n";
     133           0 :             std::cerr << "filename = " << f_expected[0].f_pos.get_filename() << "\n";
     134           0 :             std::cerr << "msg = " << f_expected[0].f_message << "\n";
     135           0 :             std::cerr << "page = " << f_expected[0].f_pos.get_page() << "\n";
     136           0 :             std::cerr << "error_code = " << static_cast<int>(f_expected[0].f_error_code) << "\n";
     137             :         }
     138          10 :         CATCH_REQUIRE(f_expected.empty());
     139          10 :     }
     140             : 
     141             :     struct expected_t
     142             :     {
     143             :         bool                        f_call = true;
     144             :         as2js::message_level_t      f_message_level = as2js::message_level_t::MESSAGE_LEVEL_OFF;
     145             :         as2js::err_code_t           f_error_code = as2js::err_code_t::AS_ERR_NONE;
     146             :         as2js::position             f_pos = as2js::position();
     147             :         std::string                 f_message = std::string(); // UTF-8 string
     148             :     };
     149             : 
     150             :     std::vector<expected_t>     f_expected = std::vector<expected_t>();
     151             : 
     152             :     static int32_t              g_warning_count;
     153             :     static int32_t              g_error_count;
     154             : };
     155             : 
     156             : int32_t   test_callback::g_warning_count = 0;
     157             : int32_t   test_callback::g_error_count = 0;
     158             : 
     159             : int32_t   g_empty_home_too_late = 0;
     160             : 
     161             : }
     162             : // no name namespace
     163             : 
     164             : 
     165             : 
     166             : 
     167             : namespace SNAP_CATCH2_NAMESPACE
     168             : {
     169             : 
     170             : 
     171             : 
     172           1 : int catch_rc_init()
     173             : {
     174             :     // verify that this user does not have existing rc files because
     175             :     // that can interfer with the tests! (and we do not want to delete
     176             :     // those under their feet)
     177             : 
     178             :     // AS2JS_RC variable must not exist
     179             :     //
     180           1 :     if(getenv("AS2JS_RC") != nullptr)
     181             :     {
     182           0 :         std::cerr << "error: the \"AS2JS_RC\" environment variable is defined; please make sure you want to run this test on this system and unset that variable before doing so.\n";
     183           0 :         return 1;
     184             :     }
     185             : 
     186             :     // local file
     187             :     //
     188           1 :     struct stat st;
     189           1 :     if(stat("as2js/as2js.rc", &st) != -1)
     190             :     {
     191           0 :         std::cerr << "error: file \"as2js/as2js.rc\" already exists; please check it out to make sure you can delete it and try running the test again.\n";
     192           0 :         return 1;
     193             :     }
     194             : 
     195             :     // user defined .config file
     196             :     //
     197           1 :     if(getenv("HOME") == nullptr)
     198             :     {
     199           0 :         std::cerr << "error: the \"HOME\" environment variable is expected to be defined.\n";
     200           0 :         return 1;
     201             :     }
     202           2 :     std::string const home(getenv("HOME"));
     203           1 :     std::string config(home);
     204           1 :     config += "/.config/as2js/as2js.rc";
     205           1 :     if(stat(config.c_str(), &st) != -1)
     206             :     {
     207             :         std::cerr << "error: file \""
     208             :             << config
     209           0 :             << "\" already exists; please check it out to make sure you can delete it and try running the test again.\n";
     210           0 :         return 1;
     211             :     }
     212             : 
     213             :     // system defined configuration file
     214             :     //
     215           1 :     if(stat("/etc/as2js/as2js.rc", &st) != -1)
     216             :     {
     217             :         std::cerr << "error: file \""
     218             :             << "/etc/as2js/as2js.rc"
     219           0 :             << "\" already exists; please check it out to make sure you can delete it and try running the test again.\n";
     220           0 :         return 1;
     221             :     }
     222             : 
     223             :     // create the local as2js directory now
     224             :     //
     225           1 :     if(mkdir("as2js", 0700) != 0)
     226             :     {
     227           0 :         int const e(errno);
     228             :         std::cerr << "error: could not create directory \""
     229             :             << home
     230             :             << "as2js"
     231           0 :             << "\". (errno: "
     232             :             << e
     233             :             << ", "
     234           0 :             << strerror(e)
     235           0 :             << ")\n";
     236           0 :         return 1;
     237             :     }
     238             : 
     239           1 :     return 0;
     240           1 : }
     241             : 
     242             : 
     243             : 
     244             : } // namespace SNAP_CATCH2_NAMESPACE
     245             : 
     246             : 
     247           1 : CATCH_TEST_CASE("resources_basics", "[resources][file]")
     248             : {
     249           1 :     CATCH_START_SECTION("resources_basics: check paths & filenames")
     250             :     {
     251             :         // this test is not going to work if the get_home() function was
     252             :         // already called with an empty HOME variable...
     253             :         //
     254           1 :         if(g_empty_home_too_late == 2)
     255             :         {
     256           0 :             std::cout << " --- test_empty_home() not run, the other rc unit tests are not compatible with this test --- ";
     257           0 :             return;
     258             :         }
     259             : 
     260           1 :         g_empty_home_too_late = 1;
     261             : 
     262             :         {
     263             :             // test the get_home()
     264             :             //
     265           2 :             std::string const home(getenv("HOME"));
     266           1 :             std::string rc_home(as2js::resources::get_home());
     267           1 :             CATCH_REQUIRE(rc_home == home);
     268             : 
     269             :             // verify that changing the variable after the first call returns
     270             :             // the first value...
     271             :             //
     272           5 :             snapdev::transparent_setenv safe_home("HOME", "/got/changed/now");
     273           1 :             rc_home = as2js::resources::get_home();
     274           1 :             CATCH_REQUIRE(rc_home == home);
     275           1 :         } // restore original HOME
     276             : 
     277             :         // without the as2js/scripts sub-directory, we get nothing
     278             :         {
     279           1 :             as2js::resources rc;
     280           1 :             as2js::resources::script_paths_t paths(rc.get_scripts());
     281           1 :             CATCH_REQUIRE(paths.empty());
     282           1 :             CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     283           1 :             CATCH_REQUIRE(rc.get_temporary_variable_name() == "@temp");
     284           1 :         }
     285             : 
     286             :         {
     287             :             //std::string const home(getenv("HOME"));
     288             :             //CATCH_REQUIRE(snapdev::mkdir_p(home + "/as2js/scripts", false, 0700) == 0);
     289           1 :             CATCH_REQUIRE(snapdev::mkdir_p("as2js/scripts", false, 0700) == 0);
     290           1 :             char * cwd(get_current_dir_name());
     291           1 :             as2js::resources rc;
     292           1 :             as2js::resources::script_paths_t paths(rc.get_scripts());
     293           1 :             CATCH_REQUIRE(paths.size() == 1);
     294           1 :             CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     295           1 :             CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     296           1 :             CATCH_REQUIRE(rc.get_temporary_variable_name() == "@temp");
     297           1 :             free(cwd);
     298           1 :         }
     299             : 
     300             :         {
     301           1 :             as2js::resources rc;
     302             : 
     303           1 :             test_callback tc;
     304             : 
     305           1 :             test_callback::expected_t expected1;
     306           1 :             expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     307           1 :             expected1.f_error_code = as2js::err_code_t::AS_ERR_INSTALLATION;
     308           1 :             expected1.f_pos.set_filename("unknown-file");
     309           1 :             expected1.f_pos.set_function("unknown-func");
     310           1 :             expected1.f_message = "cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\".";
     311           1 :             tc.f_expected.push_back(expected1);
     312             : 
     313           1 :             CATCH_REQUIRE_THROWS_MATCHES(
     314             :                   rc.init(false)
     315             :                 , as2js::as2js_exit
     316             :                 , Catch::Matchers::ExceptionMessage(
     317             :                           "as2js_exception: cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\"."));
     318           1 :             tc.got_called();
     319             : 
     320           1 :             rc.init(true);
     321             : 
     322           1 :             as2js::resources::script_paths_t paths(rc.get_scripts());
     323           1 :             CATCH_REQUIRE(paths.size() == 1);
     324           1 :             char * cwd(get_current_dir_name());
     325           1 :             CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     326           1 :             free(cwd);
     327           1 :             CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     328           1 :         }
     329             :     }
     330           1 :     CATCH_END_SECTION()
     331             : }
     332             : 
     333             : 
     334           1 : CATCH_TEST_CASE("resources_load_from_var", "[resources][config][file][variable]")
     335             : {
     336           1 :     CATCH_START_SECTION("resources_load_from_var: NULL value")
     337             :     {
     338             :         // this test is not going to work if the get_home() function was
     339             :         // already called with an empty HOME variable...
     340           1 :         if(g_empty_home_too_late == 2)
     341             :         {
     342           0 :             std::cout << " --- test_empty_home() not run, the other rc unit tests are not compatible with this test --- ";
     343           0 :             return;
     344             :         }
     345             : 
     346           1 :         g_empty_home_too_late = 1;
     347             : 
     348             :         // just in case it failed before...
     349             :         //
     350           1 :         unlink("as2js.rc");
     351             : 
     352             :         {
     353           1 :             setenv("AS2JS_RC", ".", 1);
     354             : 
     355           1 :             test_callback tc;
     356             : 
     357           1 :             test_callback::expected_t expected1;
     358           1 :             expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     359           1 :             expected1.f_error_code = as2js::err_code_t::AS_ERR_INSTALLATION;
     360           1 :             expected1.f_pos.set_filename("unknown-file");
     361           1 :             expected1.f_pos.set_function("unknown-func");
     362           1 :             expected1.f_message = "cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\".";
     363           1 :             tc.f_expected.push_back(expected1);
     364             : 
     365           1 :             as2js::resources rc;
     366           1 :             CATCH_REQUIRE_THROWS_MATCHES(
     367             :                   rc.init(false)
     368             :                 , as2js::as2js_exit
     369             :                 , Catch::Matchers::ExceptionMessage(
     370             :                           "as2js_exception: cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\"."));
     371           1 :             tc.got_called();
     372             : 
     373             :             {
     374             :                 // create an .rc file
     375           1 :                 CATCH_REQUIRE(snapdev::mkdir_p("the/script", false, 0700) == 0);
     376             :                 {
     377           1 :                     std::ofstream rc_file;
     378           1 :                     rc_file.open("as2js.rc");
     379           1 :                     CATCH_REQUIRE(rc_file.is_open());
     380             :                     rc_file << "// rc file\n"
     381             :                             << "{\n"
     382             :                             << "  'scripts': 'the/script',\n"
     383             :                             << "  'db': 'that/db',\n"
     384             :                             << "  'temporary_variable_name': '@temp$'\n"
     385           1 :                             << "}\n";
     386           1 :                 }
     387             : 
     388           1 :                 rc.init(true);
     389           1 :                 unlink("as2js.rc");
     390             : 
     391           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     392           1 :                 CATCH_REQUIRE(paths.size() == 1);
     393           1 :                 char * cwd(get_current_dir_name());
     394           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/the/script");
     395           1 :                 free(cwd);
     396           1 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
     397           1 :                 CATCH_REQUIRE(rc.get_temporary_variable_name() == "@temp$");
     398           1 :             }
     399             : 
     400             :             {
     401             :                 // create an .rc file, without scripts
     402             :                 {
     403           1 :                     std::ofstream rc_file;
     404           1 :                     rc_file.open("as2js.rc");
     405           1 :                     CATCH_REQUIRE(rc_file.is_open());
     406             :                     rc_file << "// rc file\n"
     407             :                             << "{\n"
     408             :                             << "  'db': 'that/db'\n"
     409           1 :                             << "}\n";
     410           1 :                 }
     411             : 
     412           1 :                 rc.init(true);
     413           1 :                 unlink("as2js.rc");
     414             : 
     415           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     416           1 :                 CATCH_REQUIRE(paths.size() == 1);
     417           1 :                 char * cwd(get_current_dir_name());
     418           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     419           1 :                 free(cwd);
     420           1 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
     421           1 :                 CATCH_REQUIRE(rc.get_temporary_variable_name() == "@temp");
     422           1 :             }
     423             : 
     424             :             {
     425             :                 // create an .rc file, without scripts
     426           1 :                 CATCH_REQUIRE(snapdev::mkdir_p("the/script", false, 0700) == 0);
     427             :                 {
     428           1 :                     std::ofstream rc_file;
     429           1 :                     rc_file.open("as2js.rc");
     430           1 :                     CATCH_REQUIRE(rc_file.is_open());
     431             :                     rc_file << "// rc file\n"
     432             :                             << "{\n"
     433             :                             << "  'scripts': 'the/script'\n"
     434           1 :                             << "}\n";
     435           1 :                 }
     436             : 
     437           1 :                 rc.init(true);
     438           1 :                 unlink("as2js.rc");
     439             : 
     440           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     441           1 :                 CATCH_REQUIRE(paths.size() == 1);
     442           1 :                 char * cwd(get_current_dir_name());
     443           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/the/script");
     444           1 :                 free(cwd);
     445           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     446           1 :                 CATCH_REQUIRE(rc.get_temporary_variable_name() == "@temp");
     447           1 :             }
     448             : 
     449             :             {
     450             :                 // create an .rc file, with just the temporary variable name
     451             :                 {
     452           1 :                     std::ofstream rc_file;
     453           1 :                     rc_file.open("as2js.rc");
     454           1 :                     CATCH_REQUIRE(rc_file.is_open());
     455             :                     rc_file << "// rc file\n"
     456             :                             << "{\n"
     457             :                             << "  \"temporary_variable_name\": \"what about validity of the value? -- we on purpose use @ because it is not valid in identifiers\"\n"
     458           1 :                             << "}\n";
     459           1 :                 }
     460             : 
     461           1 :                 rc.init(true);
     462           1 :                 unlink("as2js.rc");
     463             : 
     464           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     465           1 :                 CATCH_REQUIRE(paths.size() == 1);
     466           1 :                 char * cwd(get_current_dir_name());
     467           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     468           1 :                 free(cwd);
     469           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     470           1 :                 CATCH_REQUIRE(rc.get_temporary_variable_name() == "what about validity of the value? -- we on purpose use @ because it is not valid in identifiers");
     471           1 :             }
     472             : 
     473             :             {
     474             :                 // create an .rc file, without scripts
     475             :                 {
     476           1 :                     std::ofstream rc_file;
     477           1 :                     rc_file.open("as2js.rc");
     478           1 :                     CATCH_REQUIRE(rc_file.is_open());
     479             :                     rc_file << "// rc file\n"
     480             :                             << "{\n"
     481             :                             << "  'scripts': 123\n"
     482           1 :                             << "}\n";
     483           1 :                 }
     484             : 
     485           1 :                 test_callback::expected_t expected2;
     486           1 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     487           1 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
     488           1 :                 expected2.f_pos.set_filename("./as2js.rc");
     489           1 :                 expected2.f_pos.set_function("unknown-func");
     490           1 :                 expected2.f_pos.new_line();
     491           1 :                 expected2.f_pos.new_line();
     492           1 :                 expected2.f_pos.new_line();
     493           1 :                 expected2.f_message = "a resource file is expected to be an object of string elements.";
     494           1 :                 tc.f_expected.push_back(expected2);
     495             : 
     496           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
     497             :                       rc.init(true)
     498             :                     , as2js::as2js_exit
     499             :                     , Catch::Matchers::ExceptionMessage(
     500             :                               "as2js_exception: a resource file is expected to be an object of string elements."));
     501           1 :                 tc.got_called();
     502           1 :                 unlink("as2js.rc");
     503             : 
     504           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     505           1 :                 CATCH_REQUIRE(paths.size() == 1);
     506           1 :                 char * cwd(get_current_dir_name());
     507           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     508           1 :                 free(cwd);
     509           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     510           1 :             }
     511             : 
     512             :             {
     513             :                 // create a null .rc file
     514             :                 {
     515           1 :                     std::ofstream rc_file;
     516           1 :                     rc_file.open("as2js.rc");
     517           1 :                     CATCH_REQUIRE(rc_file.is_open());
     518             :                     rc_file << "// rc file\n"
     519           1 :                             << "null\n";
     520           1 :                 }
     521             : 
     522           1 :                 rc.init(false);
     523           1 :                 unlink("as2js.rc");
     524             : 
     525           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     526           1 :                 CATCH_REQUIRE(paths.size() == 1);
     527           1 :                 char * cwd(get_current_dir_name());
     528           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     529           1 :                 free(cwd);
     530           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     531           1 :             }
     532             : 
     533             :             {
     534             :                 // create an .rc file, without an object nor null
     535             :                 {
     536           1 :                     std::ofstream rc_file;
     537           1 :                     rc_file.open("as2js.rc");
     538           1 :                     CATCH_REQUIRE(rc_file.is_open());
     539             :                     rc_file << "// rc file\n"
     540           1 :                             << "['scripts', 123]\n";
     541           1 :                 }
     542             : 
     543           1 :                 test_callback::expected_t expected2;
     544           1 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     545           1 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
     546           1 :                 expected2.f_pos.set_filename("./as2js.rc");
     547           1 :                 expected2.f_pos.set_function("unknown-func");
     548           1 :                 expected2.f_pos.new_line();
     549           1 :                 expected2.f_message = "./as2js.rc: a resource file (.rc) must be defined as a JSON object, or set to \"null\".";
     550           1 :                 tc.f_expected.push_back(expected2);
     551             : 
     552           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
     553             :                       rc.init(true)
     554             :                     , as2js::as2js_exit
     555             :                     , Catch::Matchers::ExceptionMessage(
     556             :                               "as2js_exception: ./as2js.rc: a resource file (.rc) must be defined as a JSON object, or set to \"null\"."));
     557           1 :                 tc.got_called();
     558           1 :                 unlink("as2js.rc");
     559             : 
     560           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     561           1 :                 CATCH_REQUIRE(paths.size() == 1);
     562           1 :                 char * cwd(get_current_dir_name());
     563           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     564           1 :                 free(cwd);
     565           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     566           1 :             }
     567             : 
     568             :             // test some other directory too
     569           1 :             setenv("AS2JS_RC", "/tmp", 1);
     570             : 
     571             :             {
     572             :                 // create an .rc file
     573           1 :                 CATCH_REQUIRE(snapdev::mkdir_p("the/script", false, 0700) == 0);
     574             :                 {
     575           1 :                     std::ofstream rc_file;
     576           1 :                     rc_file.open("/tmp/as2js.rc");
     577           1 :                     CATCH_REQUIRE(rc_file.is_open());
     578             :                     rc_file << "// rc file\n"
     579             :                             << "{\n"
     580             :                             << "  'scripts': 'the/script',\n"
     581             :                             << "  'db': 'that/db'\n"
     582           1 :                             << "}\n";
     583           1 :                 }
     584             : 
     585           1 :                 rc.init(true);
     586           1 :                 unlink("/tmp/as2js.rc");
     587             : 
     588           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     589           1 :                 CATCH_REQUIRE(paths.size() == 1);
     590           1 :                 char * cwd(get_current_dir_name());
     591           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/the/script");
     592           1 :                 free(cwd);
     593           1 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
     594           1 :             }
     595             : 
     596             :             // make sure to delete that before exiting
     597             :             //
     598           1 :             unsetenv("AS2JS_RC");
     599           1 :         }
     600             :     }
     601           1 :     CATCH_END_SECTION()
     602             : }
     603             : 
     604             : 
     605           1 : CATCH_TEST_CASE("resources_load_from_local_config", "[resources][config][file]")
     606             : {
     607           1 :     CATCH_START_SECTION("resources_load_from_local_config: check that the local as2js.rc gets picked up")
     608             :     {
     609             :         // this test is not going to work if the get_home() function was
     610             :         // already called with an empty HOME variable...
     611           1 :         if(g_empty_home_too_late == 2)
     612             :         {
     613           0 :             std::cout << "--- test_empty_home() not run, the other rc unit tests are not compatible with this test ---\n";
     614           0 :             return;
     615             :         }
     616             : 
     617           1 :         g_empty_home_too_late = 1;
     618             : 
     619             :         // just in case it failed before...
     620             :         //
     621           1 :         static_cast<void>(unlink(".config/as2js.rc"));
     622           1 :         static_cast<void>(rmdir(".config"));
     623             : 
     624           1 :         CATCH_REQUIRE(mkdir(".config", 0700) == 0);
     625             : 
     626             :         {
     627           1 :             test_callback tc;
     628             : 
     629           1 :             test_callback::expected_t expected1;
     630           1 :             expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     631           1 :             expected1.f_error_code = as2js::err_code_t::AS_ERR_INSTALLATION;
     632           1 :             expected1.f_pos.set_filename("unknown-file");
     633           1 :             expected1.f_pos.set_function("unknown-func");
     634           1 :             expected1.f_message = "cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\".";
     635           1 :             tc.f_expected.push_back(expected1);
     636             : 
     637           1 :             as2js::resources rc;
     638           1 :             CATCH_REQUIRE_THROWS_MATCHES(
     639             :                   rc.init(false)
     640             :                 , as2js::as2js_exit
     641             :                 , Catch::Matchers::ExceptionMessage(
     642             :                           "as2js_exception: cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\"."));
     643           1 :             tc.got_called();
     644             : 
     645             :             {
     646             :                 // create an .rc file
     647             :                 {
     648           1 :                     std::ofstream rc_file;
     649           1 :                     rc_file.open("as2js/as2js.rc");
     650           1 :                     CATCH_REQUIRE(rc_file.is_open());
     651             :                     rc_file << "// rc file\n"
     652             :                             << "{\n"
     653             :                             << "  'scripts': 'the/script',\n"
     654             :                             << "  'db': 'that/db'\n"
     655           1 :                             << "}\n";
     656           1 :                 }
     657             : 
     658           1 :                 rc.init(true);
     659           1 :                 unlink("as2js/as2js.rc");
     660             : 
     661           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     662           1 :                 CATCH_REQUIRE(paths.size() == 1);
     663           1 :                 char * cwd(get_current_dir_name());
     664           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/the/script");
     665           1 :                 free(cwd);
     666           1 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
     667           1 :             }
     668             : 
     669             :             {
     670             :                 // create an .rc file, without scripts
     671             :                 {
     672           1 :                     std::ofstream rc_file;
     673           1 :                     rc_file.open("as2js/as2js.rc");
     674           1 :                     CATCH_REQUIRE(rc_file.is_open());
     675             :                     rc_file << "// rc file\n"
     676             :                             << "{\n"
     677             :                             << "  'db': 'that/db'\n"
     678           1 :                             << "}\n";
     679           1 :                 }
     680             : 
     681           1 :                 rc.init(true);
     682           1 :                 unlink("as2js/as2js.rc");
     683             : 
     684           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     685           1 :                 CATCH_REQUIRE(paths.size() == 1);
     686           1 :                 char * cwd(get_current_dir_name());
     687           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     688           1 :                 free(cwd);
     689           1 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
     690           1 :             }
     691             : 
     692             :             {
     693             :                 // create an .rc file, without scripts
     694             :                 {
     695           1 :                     std::ofstream rc_file;
     696           1 :                     rc_file.open("as2js/as2js.rc");
     697           1 :                     CATCH_REQUIRE(rc_file.is_open());
     698             :                     rc_file << "// rc file\n"
     699             :                             << "{\n"
     700             :                             << "  'scripts': 'the/script'\n"
     701           1 :                             << "}\n";
     702           1 :                 }
     703             : 
     704           1 :                 rc.init(true);
     705           1 :                 unlink("as2js/as2js.rc");
     706             : 
     707           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     708           1 :                 CATCH_REQUIRE(paths.size() == 1);
     709           1 :                 char * cwd(get_current_dir_name());
     710           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/the/script");
     711           1 :                 free(cwd);
     712           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     713           1 :             }
     714             : 
     715             :             {
     716             :                 // create an .rc file, without scripts
     717             :                 {
     718           1 :                     std::ofstream rc_file;
     719           1 :                     rc_file.open("as2js/as2js.rc");
     720           1 :                     CATCH_REQUIRE(rc_file.is_open());
     721             :                     rc_file << "// rc file\n"
     722             :                             << "{\n"
     723             :                             << "  'scripts': 123\n"
     724           1 :                             << "}\n";
     725           1 :                 }
     726             : 
     727           1 :                 test_callback::expected_t expected2;
     728           1 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     729           1 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
     730           1 :                 expected2.f_pos.set_filename("as2js/as2js.rc");
     731           1 :                 expected2.f_pos.set_function("unknown-func");
     732           1 :                 expected2.f_pos.new_line();
     733           1 :                 expected2.f_pos.new_line();
     734           1 :                 expected2.f_pos.new_line();
     735           1 :                 expected2.f_message = "a resource file is expected to be an object of string elements.";
     736           1 :                 tc.f_expected.push_back(expected2);
     737             : 
     738           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
     739             :                       rc.init(true)
     740             :                     , as2js::as2js_exit
     741             :                     , Catch::Matchers::ExceptionMessage(
     742             :                               "as2js_exception: a resource file is expected to be an object of string elements."));
     743           1 :                 tc.got_called();
     744           1 :                 unlink("as2js/as2js.rc");
     745             : 
     746           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     747           1 :                 CATCH_REQUIRE(paths.size() == 1);
     748           1 :                 char * cwd(get_current_dir_name());
     749           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     750           1 :                 free(cwd);
     751           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     752           1 :             }
     753             : 
     754             :             {
     755             :                 // create a null .rc file
     756             :                 {
     757           1 :                     std::ofstream rc_file;
     758           1 :                     rc_file.open("as2js/as2js.rc");
     759           1 :                     CATCH_REQUIRE(rc_file.is_open());
     760             :                     rc_file << "// rc file\n"
     761           1 :                             << "null\n";
     762           1 :                 }
     763             : 
     764           1 :                 rc.init(false);
     765           1 :                 unlink("as2js/as2js.rc");
     766             : 
     767           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     768           1 :                 CATCH_REQUIRE(paths.size() == 1);
     769           1 :                 char * cwd(get_current_dir_name());
     770           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     771           1 :                 free(cwd);
     772           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     773           1 :             }
     774             : 
     775             :             {
     776             :                 // create an .rc file, without an object nor null
     777             :                 {
     778           1 :                     std::ofstream rc_file;
     779           1 :                     rc_file.open("as2js/as2js.rc");
     780           1 :                     CATCH_REQUIRE(rc_file.is_open());
     781             :                     rc_file << "// rc file\n"
     782           1 :                             << "['scripts', 123]\n";
     783           1 :                 }
     784             : 
     785           1 :                 test_callback::expected_t expected2;
     786           1 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     787           1 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
     788           1 :                 expected2.f_pos.set_filename("as2js/as2js.rc");
     789           1 :                 expected2.f_pos.set_function("unknown-func");
     790           1 :                 expected2.f_pos.new_line();
     791           1 :                 expected2.f_message = "as2js/as2js.rc: a resource file (.rc) must be defined as a JSON object, or set to \"null\".";
     792           1 :                 tc.f_expected.push_back(expected2);
     793             : 
     794           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
     795             :                       rc.init(true)
     796             :                     , as2js::as2js_exit
     797             :                     , Catch::Matchers::ExceptionMessage(
     798             :                               "as2js_exception: as2js/as2js.rc: a resource file (.rc) must be defined as a JSON object, or set to \"null\"."));
     799           1 :                 tc.got_called();
     800           1 :                 unlink("as2js/as2js.rc");
     801             : 
     802           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     803           1 :                 CATCH_REQUIRE(paths.size() == 1);
     804           1 :                 char * cwd(get_current_dir_name());
     805           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     806           1 :                 free(cwd);
     807           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     808           1 :             }
     809           1 :         }
     810             : 
     811             :         // delete our temporary .rc file (should already have been deleted)
     812           1 :         unlink("as2js/as2js.rc");
     813             : 
     814             :         // if possible get rid of the directory (don't check for errors)
     815           1 :         rmdir("as2js");
     816             :     }
     817           1 :     CATCH_END_SECTION()
     818             : }
     819             : 
     820             : 
     821           1 : CATCH_TEST_CASE("resources_load_from_user_config", "[resources][config][file]")
     822             : {
     823           1 :     CATCH_START_SECTION("resources_load_from_user_config: NULL value")
     824             :     {
     825             :         // this test is not going to work if the get_home() function was
     826             :         // already called with an empty HOME variable...
     827           1 :         if(g_empty_home_too_late == 2)
     828             :         {
     829           0 :             std::cout << "--- test_empty_home() not run, the other rc unit tests are not compatible with this test ---\n";
     830           0 :             return;
     831             :         }
     832             : 
     833           1 :         g_empty_home_too_late = 1;
     834             : 
     835           2 :         std::string const home(getenv("HOME"));
     836             : 
     837             :         // create the folders and make sure we clean up any existing .rc file
     838             :         // (although it was checked in the setUp() function and thus we should
     839             :         // not reach here if the .rc already existed!)
     840             :         //
     841           1 :         std::string config(home);
     842           1 :         config += "/.config";
     843           1 :         std::cout << "--- config path \"" << config << "\" ---\n";
     844           1 :         bool del_config(true);
     845           1 :         if(mkdir(config.c_str(), 0700) != 0) // usually this is 0755, but for security we cannot take that risk...
     846             :         {
     847             :             // if this mkdir() fails, it is because it exists?
     848             :             //
     849           0 :             CATCH_REQUIRE(errno == EEXIST);
     850           0 :             del_config = false;
     851             :         }
     852           1 :         std::string as2js_conf(config);
     853           1 :         as2js_conf += "/as2js";
     854           1 :         CATCH_REQUIRE(snapdev::mkdir_p(as2js_conf.c_str(), false, 0700) == 0);
     855           1 :         std::string as2js_rc(as2js_conf);
     856           1 :         as2js_rc += "/as2js.rc";
     857           1 :         unlink(as2js_rc.c_str()); // delete that, just in case (the setup verifies that it does not exist)
     858             : //system(("ls -lR " + config).c_str());
     859             : 
     860             :         {
     861           1 :             test_callback tc;
     862             : 
     863           1 :             test_callback::expected_t expected1;
     864           1 :             expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     865           1 :             expected1.f_error_code = as2js::err_code_t::AS_ERR_INSTALLATION;
     866           1 :             expected1.f_pos.set_filename("unknown-file");
     867           1 :             expected1.f_pos.set_function("unknown-func");
     868           1 :             expected1.f_message = "cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\".";
     869           1 :             tc.f_expected.push_back(expected1);
     870             : 
     871           1 :             as2js::resources rc;
     872           1 :             CATCH_REQUIRE_THROWS_MATCHES(
     873             :                   rc.init(false)
     874             :                 , as2js::as2js_exit
     875             :                 , Catch::Matchers::ExceptionMessage(
     876             :                           "as2js_exception: cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\"."));
     877           1 :             tc.got_called();
     878             : 
     879             :             {
     880             :                 // create an .rc file
     881           1 :                 CATCH_REQUIRE(snapdev::mkdir_p("the/script", false, 0700) == 0);
     882           1 :                 CATCH_REQUIRE(snapdev::mkdir_p("another/script", false, 0700) == 0);
     883           1 :                 CATCH_REQUIRE(snapdev::mkdir_p("here/script", false, 0700) == 0);
     884             :                 {
     885           1 :                     std::ofstream rc_file;
     886           1 :                     rc_file.open(as2js_rc.c_str());
     887           1 :                     CATCH_REQUIRE(rc_file.is_open());
     888             :                     rc_file << "// rc file\n"
     889             :                             << "{\n"
     890             :                             << "  'scripts': 'the/script:another/script:here/script',\n"
     891             :                             << "  'db': 'that/db'\n"
     892           1 :                             << "}\n";
     893           1 :                 }
     894             : 
     895           1 :                 rc.init(true);
     896           1 :                 unlink(as2js_rc.c_str());
     897             : 
     898           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     899           1 :                 CATCH_REQUIRE(paths.size() == 3);
     900           1 :                 auto it(paths.begin());
     901           1 :                 char * cwd(get_current_dir_name());
     902           1 :                 CATCH_REQUIRE(*it == std::string(cwd) + "/the/script");
     903           1 :                 ++it;
     904           1 :                 CATCH_REQUIRE(*it == std::string(cwd) + "/another/script");
     905           1 :                 ++it;
     906           1 :                 CATCH_REQUIRE(*it == std::string(cwd) + "/here/script");
     907           1 :                 free(cwd);
     908           1 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
     909           1 :             }
     910             : 
     911             :             {
     912             :                 // create an .rc file, without scripts
     913             :                 {
     914           1 :                     std::ofstream rc_file;
     915           1 :                     rc_file.open(as2js_rc.c_str());
     916           1 :                     CATCH_REQUIRE(rc_file.is_open());
     917             :                     rc_file << "// rc file\n"
     918             :                             << "{\n"
     919             :                             << "  'db': 'that/db'\n"
     920           1 :                             << "}\n";
     921           1 :                 }
     922             : 
     923           1 :                 rc.init(true);
     924           1 :                 unlink(as2js_rc.c_str());
     925             : 
     926           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     927           1 :                 CATCH_REQUIRE(paths.size() == 1);
     928           1 :                 char * cwd(get_current_dir_name());
     929           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     930           1 :                 free(cwd);
     931           1 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
     932           1 :             }
     933             : 
     934             :             {
     935             :                 // create an .rc file, without scripts
     936             :                 {
     937           1 :                     std::ofstream rc_file;
     938           1 :                     rc_file.open(as2js_rc.c_str());
     939           1 :                     CATCH_REQUIRE(rc_file.is_open());
     940             :                     rc_file << "// rc file\n"
     941             :                             << "{\n"
     942             :                             << "  'scripts': 'the/script'\n"
     943           1 :                             << "}\n";
     944           1 :                 }
     945             : 
     946           1 :                 rc.init(true);
     947           1 :                 unlink(as2js_rc.c_str());
     948             : 
     949           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     950           1 :                 CATCH_REQUIRE(paths.size() == 1);
     951           1 :                 char * cwd(get_current_dir_name());
     952           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/the/script");
     953           1 :                 free(cwd);
     954           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     955           1 :             }
     956             : 
     957             :             {
     958             :                 // create an .rc file, without scripts
     959             :                 {
     960           1 :                     std::ofstream rc_file;
     961           1 :                     rc_file.open(as2js_rc.c_str());
     962           1 :                     CATCH_REQUIRE(rc_file.is_open());
     963             :                     rc_file << "// rc file\n"
     964             :                             << "{\n"
     965             :                             << "  'scripts': 123\n"
     966           1 :                             << "}\n";
     967           1 :                 }
     968             : 
     969           1 :                 test_callback::expected_t expected2;
     970           1 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
     971           1 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
     972           1 :                 expected2.f_pos.set_filename(as2js_rc.c_str());
     973           1 :                 expected2.f_pos.set_function("unknown-func");
     974           1 :                 expected2.f_pos.new_line();
     975           1 :                 expected2.f_pos.new_line();
     976           1 :                 expected2.f_pos.new_line();
     977           1 :                 expected2.f_message = "a resource file is expected to be an object of string elements.";
     978           1 :                 tc.f_expected.push_back(expected2);
     979             : 
     980           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
     981             :                       rc.init(true)
     982             :                     , as2js::as2js_exit
     983             :                     , Catch::Matchers::ExceptionMessage(
     984             :                               "as2js_exception: a resource file is expected to be an object of string elements."));
     985           1 :                 tc.got_called();
     986           1 :                 unlink(as2js_rc.c_str());
     987             : 
     988           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
     989           1 :                 CATCH_REQUIRE(paths.size() == 1);
     990           1 :                 char * cwd(get_current_dir_name());
     991           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
     992           1 :                 free(cwd);
     993           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
     994           1 :             }
     995             : 
     996             :             {
     997             :                 // create a null .rc file
     998             :                 {
     999           1 :                     std::ofstream rc_file;
    1000           1 :                     rc_file.open(as2js_rc.c_str());
    1001           1 :                     CATCH_REQUIRE(rc_file.is_open());
    1002             :                     rc_file << "// rc file\n"
    1003           1 :                             << "null\n";
    1004           1 :                 }
    1005             : 
    1006           1 :                 rc.init(false);
    1007           1 :                 unlink(as2js_rc.c_str());
    1008             : 
    1009           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1010           1 :                 CATCH_REQUIRE(paths.size() == 1);
    1011           1 :                 char * cwd(get_current_dir_name());
    1012           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
    1013           1 :                 free(cwd);
    1014           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
    1015           1 :             }
    1016             : 
    1017             :             {
    1018             :                 // create an .rc file, without an object nor null
    1019             :                 {
    1020           1 :                     std::ofstream rc_file;
    1021           1 :                     rc_file.open(as2js_rc.c_str());
    1022           1 :                     CATCH_REQUIRE(rc_file.is_open());
    1023             :                     rc_file << "// rc file\n"
    1024           1 :                             << "['scripts', 123]\n";
    1025           1 :                 }
    1026             : 
    1027           1 :                 char * cwd(get_current_dir_name());
    1028           1 :                 test_callback::expected_t expected2;
    1029           1 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1030           1 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
    1031           1 :                 expected2.f_pos.set_filename(as2js_rc.c_str());
    1032           1 :                 expected2.f_pos.set_function("unknown-func");
    1033           1 :                 expected2.f_pos.new_line();
    1034           1 :                 expected2.f_message = std::string(cwd) + "/home/.config/as2js/as2js.rc: a resource file (.rc) must be defined as a JSON object, or set to \"null\".";
    1035           1 :                 tc.f_expected.push_back(expected2);
    1036             : 
    1037           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
    1038             :                       rc.init(true)
    1039             :                     , as2js::as2js_exit
    1040             :                     , Catch::Matchers::ExceptionMessage(
    1041             :                               "as2js_exception: " + expected2.f_message));
    1042             :                               //"as2js_exception: a resource file (.rc) must be defined as a JSON object, or set to \"null\"."));
    1043           1 :                 tc.got_called();
    1044           1 :                 unlink(as2js_rc.c_str());
    1045             : 
    1046           1 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1047           1 :                 CATCH_REQUIRE(paths.size() == 1);
    1048           1 :                 CATCH_REQUIRE(*paths.begin() == std::string(cwd) + "/as2js/scripts");
    1049           1 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
    1050           1 :                 free(cwd);
    1051           1 :             }
    1052           1 :         }
    1053             : 
    1054             :         // delete our temporary .rc file (should already have been deleted)
    1055           1 :         unlink(as2js_rc.c_str());
    1056             : 
    1057             :         // if possible get rid of the directories (don't check for errors)
    1058           1 :         rmdir(as2js_conf.c_str());
    1059           1 :         if(del_config)
    1060             :         {
    1061           1 :             rmdir(config.c_str());
    1062             :         }
    1063           1 :     }
    1064           1 :     CATCH_END_SECTION()
    1065             : }
    1066             : 
    1067             : 
    1068             : //
    1069             : // WARNING: this test requires root permissions, it can generally be
    1070             : //          ignored though because it uses the same process as the
    1071             : //          user local file in "as2js/as2js.rc"; it is here for
    1072             : //          completeness in case you absolutely want to prove that
    1073             : //          works as expected
    1074             : //
    1075           1 : CATCH_TEST_CASE("resources_load_from_system_config", "[resources][config][file]")
    1076             : {
    1077           1 :     CATCH_START_SECTION("resources_load_from_system_config: NULL value")
    1078             :     {
    1079           1 :         if(getuid() != 0)
    1080             :         {
    1081           1 :             std::cout << "--- test_load_from_system_config() requires root access to modify the /etc/as2js directory ---\n";
    1082           1 :             CATCH_REQUIRE(getuid() != 0);
    1083           1 :             return;
    1084             :         }
    1085             : 
    1086             :         // this test is not going to work if the get_home() function was
    1087             :         // already called with an empty HOME variable...
    1088             :         //
    1089           0 :         if(g_empty_home_too_late == 2)
    1090             :         {
    1091           0 :             std::cout << "--- test_empty_home() not run, the other rc unit tests are not compatible with this test ---\n";
    1092           0 :             return;
    1093             :         }
    1094             : 
    1095           0 :         g_empty_home_too_late = 1;
    1096             : 
    1097             :         // create the folders and make sure we clean up any existing .rc file
    1098             :         // (although it was checked in the setUp() function and thus we should
    1099             :         // not reach here if the .rc already existed!)
    1100           0 :         std::string as2js_conf("/etc/as2js");
    1101           0 :         int const r(mkdir(as2js_conf.c_str(), 0700)); // usually this is 0755, but for security we cannot take that risk...
    1102           0 :         if(r != 0)
    1103             :         {
    1104             :             // if this mkdir() fails, it is because it exists?
    1105             :             //
    1106           0 :             CATCH_REQUIRE(errno == EEXIST);
    1107             :         }
    1108           0 :         std::string as2js_rc(as2js_conf);
    1109           0 :         as2js_rc += "/as2js.rc";
    1110           0 :         unlink(as2js_rc.c_str()); // delete that, just in case (the setup verifies that it does not exist)
    1111             : 
    1112             :         {
    1113           0 :             test_callback tc;
    1114             : 
    1115           0 :             test_callback::expected_t expected1;
    1116           0 :             expected1.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1117           0 :             expected1.f_error_code = as2js::err_code_t::AS_ERR_INSTALLATION;
    1118           0 :             expected1.f_pos.set_filename("unknown-file");
    1119           0 :             expected1.f_pos.set_function("unknown-func");
    1120           0 :             expected1.f_message = "cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\".";
    1121           0 :             tc.f_expected.push_back(expected1);
    1122             : 
    1123           0 :             as2js::resources rc;
    1124           0 :             CATCH_REQUIRE_THROWS_MATCHES(
    1125             :                   rc.init(false)
    1126             :                 , as2js::as2js_exit
    1127             :                 , Catch::Matchers::ExceptionMessage(
    1128             :                           "as2js_exception: cannot find the \"as2js.rc\" file; the system default is usually put in \"/etc/as2js/as2js.rc\"."));
    1129           0 :             tc.got_called();
    1130             : 
    1131             :             {
    1132             :                 // create an .rc file
    1133             :                 {
    1134           0 :                     std::ofstream rc_file;
    1135           0 :                     rc_file.open(as2js_rc.c_str());
    1136           0 :                     CATCH_REQUIRE(rc_file.is_open());
    1137             :                     rc_file << "// rc file\n"
    1138             :                             << "{\n"
    1139             :                             << "  'scripts': 'the/script',\n"
    1140             :                             << "  'db': 'that/db'\n"
    1141           0 :                             << "}\n";
    1142           0 :                 }
    1143             : 
    1144           0 :                 rc.init(true);
    1145           0 :                 unlink(as2js_rc.c_str());
    1146             : 
    1147           0 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1148           0 :                 CATCH_REQUIRE(paths.size() == 1);
    1149           0 :                 CATCH_REQUIRE(*paths.begin() == "the/script");
    1150           0 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
    1151           0 :             }
    1152             : 
    1153             :             {
    1154             :                 // create an .rc file, without scripts
    1155             :                 {
    1156           0 :                     std::ofstream rc_file;
    1157           0 :                     rc_file.open(as2js_rc.c_str());
    1158           0 :                     CATCH_REQUIRE(rc_file.is_open());
    1159             :                     rc_file << "// rc file\n"
    1160             :                             << "{\n"
    1161             :                             << "  'db': 'that/db'\n"
    1162           0 :                             << "}\n";
    1163           0 :                 }
    1164             : 
    1165           0 :                 rc.init(true);
    1166           0 :                 unlink(as2js_rc.c_str());
    1167             : 
    1168           0 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1169           0 :                 CATCH_REQUIRE(paths.size() == 1);
    1170           0 :                 CATCH_REQUIRE(*paths.begin() == "as2js/scripts");
    1171           0 :                 CATCH_REQUIRE(rc.get_db() == "that/db");
    1172           0 :             }
    1173             : 
    1174             :             {
    1175             :                 // create an .rc file, without scripts
    1176             :                 {
    1177           0 :                     std::ofstream rc_file;
    1178           0 :                     rc_file.open(as2js_rc.c_str());
    1179           0 :                     CATCH_REQUIRE(rc_file.is_open());
    1180             :                     rc_file << "// rc file\n"
    1181             :                             << "{\n"
    1182             :                             << "  'scripts': 'the/script'\n"
    1183           0 :                             << "}\n";
    1184           0 :                 }
    1185             : 
    1186           0 :                 rc.init(true);
    1187           0 :                 unlink(as2js_rc.c_str());
    1188             : 
    1189           0 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1190           0 :                 CATCH_REQUIRE(paths.size() == 1);
    1191           0 :                 CATCH_REQUIRE(*paths.begin() == "the/script");
    1192           0 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
    1193           0 :             }
    1194             : 
    1195             :             {
    1196             :                 // create an .rc file, without scripts
    1197             :                 {
    1198           0 :                     std::ofstream rc_file;
    1199           0 :                     rc_file.open(as2js_rc.c_str());
    1200           0 :                     CATCH_REQUIRE(rc_file.is_open());
    1201             :                     rc_file << "// rc file\n"
    1202             :                             << "{\n"
    1203             :                             << "  'scripts': 123\n"
    1204           0 :                             << "}\n";
    1205           0 :                 }
    1206             : 
    1207           0 :                 test_callback::expected_t expected2;
    1208           0 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1209           0 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
    1210           0 :                 expected2.f_pos.set_filename(as2js_rc.c_str());
    1211           0 :                 expected2.f_pos.set_function("unknown-func");
    1212           0 :                 expected2.f_pos.new_line();
    1213           0 :                 expected2.f_pos.new_line();
    1214           0 :                 expected2.f_pos.new_line();
    1215           0 :                 expected2.f_message = "a resource file is expected to be an object of string elements.";
    1216           0 :                 tc.f_expected.push_back(expected2);
    1217             : 
    1218           0 :                 CATCH_REQUIRE_THROWS_MATCHES(
    1219             :                       rc.init(true)
    1220             :                     , as2js::as2js_exit
    1221             :                     , Catch::Matchers::ExceptionMessage(
    1222             :                               "as2js_exception: a resource file is expected to be an object of string elements."));
    1223           0 :                 tc.got_called();
    1224           0 :                 unlink(as2js_rc.c_str());
    1225             : 
    1226           0 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1227           0 :                 CATCH_REQUIRE(paths.size() == 1);
    1228           0 :                 CATCH_REQUIRE(*paths.begin() == "as2js/scripts");
    1229           0 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
    1230           0 :             }
    1231             : 
    1232             :             {
    1233             :                 // create a null .rc file
    1234             :                 {
    1235           0 :                     std::ofstream rc_file;
    1236           0 :                     rc_file.open(as2js_rc.c_str());
    1237           0 :                     CATCH_REQUIRE(rc_file.is_open());
    1238             :                     rc_file << "// rc file\n"
    1239           0 :                             << "null\n";
    1240           0 :                 }
    1241             : 
    1242           0 :                 rc.init(false);
    1243           0 :                 unlink(as2js_rc.c_str());
    1244             : 
    1245           0 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1246           0 :                 CATCH_REQUIRE(paths.size() == 1);
    1247           0 :                 CATCH_REQUIRE(*paths.begin() == "as2js/scripts");
    1248           0 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
    1249           0 :             }
    1250             : 
    1251             :             {
    1252             :                 // create an .rc file, without an object nor null
    1253             :                 {
    1254           0 :                     std::ofstream rc_file;
    1255           0 :                     rc_file.open(as2js_rc.c_str());
    1256           0 :                     CATCH_REQUIRE(rc_file.is_open());
    1257             :                     rc_file << "// rc file\n"
    1258           0 :                             << "['scripts', 123]\n";
    1259           0 :                 }
    1260             : 
    1261           0 :                 test_callback::expected_t expected2;
    1262           0 :                 expected2.f_message_level = as2js::message_level_t::MESSAGE_LEVEL_FATAL;
    1263           0 :                 expected2.f_error_code = as2js::err_code_t::AS_ERR_UNEXPECTED_RC;
    1264           0 :                 expected2.f_pos.set_filename(as2js_rc.c_str());
    1265           0 :                 expected2.f_pos.set_function("unknown-func");
    1266           0 :                 expected2.f_pos.new_line();
    1267           0 :                 expected2.f_message = "a resource file (.rc) must be defined as a JSON object, or set to \"null\".";
    1268           0 :                 tc.f_expected.push_back(expected2);
    1269             : 
    1270           0 :                 CATCH_REQUIRE_THROWS_MATCHES(
    1271             :                       rc.init(true)
    1272             :                     , as2js::as2js_exit
    1273             :                     , Catch::Matchers::ExceptionMessage(
    1274             :                               "as2js_exception: a resource file (.rc) must be defined as a JSON object, or set to \"null\"."));
    1275           0 :                 tc.got_called();
    1276           0 :                 unlink(as2js_rc.c_str());
    1277             : 
    1278           0 :                 as2js::resources::script_paths_t paths(rc.get_scripts());
    1279           0 :                 CATCH_REQUIRE(paths.size() == 1);
    1280           0 :                 CATCH_REQUIRE(*paths.begin() == "as2js/scripts");
    1281           0 :                 CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
    1282           0 :             }
    1283           0 :         }
    1284             : 
    1285             :         // delete our temporary .rc file (should already have been deleted)
    1286           0 :         unlink(as2js_rc.c_str());
    1287             : 
    1288             :         // if possible get rid of the directories (don't check for errors)
    1289           0 :         rmdir(as2js_conf.c_str());
    1290           0 :     }
    1291           1 :     CATCH_END_SECTION()
    1292             : }
    1293             : 
    1294             : 
    1295           1 : CATCH_TEST_CASE("resources_empty_home", "[resources][config][file]")
    1296             : {
    1297           1 :     CATCH_START_SECTION("resources_empty_home: NULL value")
    1298             :     {
    1299             :         // this test is not going to work if the get_home() function was
    1300             :         // already called...
    1301           1 :         if(g_empty_home_too_late == 1)
    1302             :         {
    1303           1 :             std::cout << "--- test_empty_home() not run, the other rc unit tests are not compatible with this test ---\n";
    1304           1 :             CATCH_REQUIRE(g_empty_home_too_late == 1);
    1305           1 :             return;
    1306             :         }
    1307             : 
    1308           0 :         g_empty_home_too_late = 2;
    1309             : 
    1310             :         // create an .rc file in the user's config directory
    1311             :         //
    1312           0 :         std::string home(getenv("HOME"));
    1313             : 
    1314           0 :         std::string config(home);
    1315           0 :         config += "/.config";
    1316           0 :         std::cout << "--- config path \"" << config << "\" ---\n";
    1317           0 :         bool del_config(true);
    1318           0 :         if(mkdir(config.c_str(), 0700) != 0) // usually this is 0755, but for security we cannot take that risk...
    1319             :         {
    1320             :             // if this mkdir() fails, it is because it exists?
    1321             :             //
    1322           0 :             CATCH_REQUIRE(errno == EEXIST);
    1323           0 :             del_config = false;
    1324             :         }
    1325             : 
    1326           0 :         std::string rc_path(config);
    1327           0 :         rc_path += "/as2js";
    1328           0 :         CATCH_REQUIRE(mkdir(rc_path.c_str(), 0700) == 0);
    1329             : 
    1330           0 :         std::string rc_filename(rc_path);
    1331           0 :         rc_filename += "/as2js.rc";
    1332             : 
    1333           0 :         std::ofstream rc_file;
    1334           0 :         rc_file.open(rc_filename.c_str());
    1335           0 :         CATCH_REQUIRE(rc_file.is_open());
    1336             :         rc_file << "// rc file\n"
    1337             :                 << "{\n"
    1338             :                 << "  'scripts': 'cannot read this one',\n"
    1339             :                 << "  'db': 'because it is not accessible'\n"
    1340           0 :                 << "}\n";
    1341             : 
    1342             :         // remove the variable from the environment
    1343             :         //
    1344           0 :         snapdev::transparent_setenv safe("HOME", std::string());
    1345             : 
    1346             :         {
    1347           0 :             test_callback tc;
    1348             : 
    1349             :             // although we have an rc file under ~/.config/as2js/as2js.rc the
    1350             :             // rc class cannot find it because the $HOME variable was just deleted
    1351           0 :             as2js::resources rc;
    1352           0 :             rc.init(true);
    1353             : 
    1354           0 :             as2js::resources::script_paths_t paths(rc.get_scripts());
    1355           0 :             CATCH_REQUIRE(paths.size() == 1);
    1356           0 :             CATCH_REQUIRE(*paths.begin() == "as2js/scripts");
    1357           0 :             CATCH_REQUIRE(rc.get_db() == "/tmp/as2js_packages.db");
    1358           0 :         }
    1359             : 
    1360           0 :         unlink(rc_filename.c_str());
    1361           0 :         rmdir(rc_path.c_str());
    1362           0 :     }
    1363           1 :     CATCH_END_SECTION()
    1364             : }
    1365             : 
    1366             : 
    1367             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14