LCOV - code coverage report
Current view: top level - tests - catch_plugins.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 399 399 100.0 %
Date: 2021-08-21 09:27:22 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2006-2021  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/cppthread
       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 2 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 along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : 
      20             : // self
      21             : //
      22             : #include    "catch_main.h"
      23             : 
      24             : #include    "plugin_testme.h"
      25             : 
      26             : 
      27             : // cppthread lib
      28             : //
      29             : #include    <cppthread/plugins.h>
      30             : 
      31             : 
      32             : // snapdev lib
      33             : //
      34             : #include    <snapdev/not_reached.h>
      35             : 
      36             : 
      37             : // C++ lib
      38             : //
      39             : #include    <fstream>
      40             : 
      41             : 
      42             : // C lib
      43             : //
      44             : #include    <unistd.h>
      45             : #include    <sys/stat.h>
      46             : #include    <sys/types.h>
      47             : 
      48             : 
      49             : // last include
      50             : //
      51             : #include    <snapdev/poison.h>
      52             : 
      53             : 
      54             : 
      55             : 
      56             : 
      57          12 : CATCH_TEST_CASE("plugin_paths", "[plugins] [paths]")
      58             : {
      59          20 :     CATCH_START_SECTION("empty size/at when empty")
      60             :     {
      61           2 :         cppthread::plugin_paths p;
      62             : 
      63           1 :         CATCH_REQUIRE(p.size() == 0);
      64             : 
      65          22 :         for(int idx(-10); idx <= 10; ++idx)
      66             :         {
      67          21 :             CATCH_REQUIRE(p.at(idx) == std::string());
      68             :         }
      69             :     }
      70             :     CATCH_END_SECTION()
      71             : 
      72          20 :     CATCH_START_SECTION("canonicalize empty path")
      73             :     {
      74           2 :         cppthread::plugin_paths p;
      75             : 
      76           1 :         CATCH_REQUIRE_FALSE(p.get_allow_redirects());
      77           1 :         CATCH_REQUIRE_THROWS_MATCHES(
      78             :                   p.canonicalize(cppthread::plugin_paths::path_t())
      79             :                 , cppthread::cppthread_invalid_error
      80             :                 , Catch::Matchers::ExceptionMessage(
      81             :                           "cppthread_exception: path cannot be an empty string."));
      82             : 
      83           1 :         p.set_allow_redirects(true);
      84           1 :         CATCH_REQUIRE(p.get_allow_redirects());
      85           1 :         CATCH_REQUIRE_THROWS_MATCHES(
      86             :                   p.canonicalize(cppthread::plugin_paths::path_t())
      87             :                 , cppthread::cppthread_invalid_error
      88             :                 , Catch::Matchers::ExceptionMessage(
      89             :                           "cppthread_exception: path cannot be an empty string."));
      90             : 
      91           1 :         p.set_allow_redirects(false);
      92           1 :         CATCH_REQUIRE_FALSE(p.get_allow_redirects());
      93           1 :         CATCH_REQUIRE_THROWS_MATCHES(
      94             :                   p.canonicalize(cppthread::plugin_paths::path_t())
      95             :                 , cppthread::cppthread_invalid_error
      96             :                 , Catch::Matchers::ExceptionMessage(
      97             :                           "cppthread_exception: path cannot be an empty string."));
      98             :     }
      99             :     CATCH_END_SECTION()
     100             : 
     101          20 :     CATCH_START_SECTION("canonicalize base root path")
     102             :     {
     103          11 :         for(int idx(1); idx <= 10; ++idx)
     104             :         {
     105          20 :             cppthread::plugin_paths p;
     106             : 
     107          20 :             cppthread::plugin_paths::path_t root(idx, '/');
     108          10 :             CATCH_REQUIRE(p.canonicalize(root) == "/");
     109          10 :             p.set_allow_redirects(true);
     110          10 :             CATCH_REQUIRE(p.canonicalize(root) == "/");
     111          10 :             p.set_allow_redirects(false);
     112          10 :             CATCH_REQUIRE(p.canonicalize(root) == "/");
     113             :         }
     114             :     }
     115             :     CATCH_END_SECTION()
     116             : 
     117          20 :     CATCH_START_SECTION("canonicalize root path with one \"..\"")
     118             :     {
     119           1 :         std::vector<cppthread::plugin_paths::path_t> paths =
     120             :         {
     121             :             "this",
     122             :             "long",
     123             :             "..",
     124             :             "short",
     125             :             "root",
     126             :             "path",
     127           2 :         };
     128             : 
     129           6 :         for(cppthread::plugin_paths::path_t::size_type l(1); l < paths.size(); ++l)
     130             :         {
     131          10 :             cppthread::plugin_paths p;
     132          10 :             cppthread::plugin_paths::path_t expected;
     133           5 :             int count(rand() % 10 + 1);
     134          10 :             cppthread::plugin_paths::path_t path(count , '/');
     135          20 :             for(cppthread::plugin_paths::path_t::size_type c(0); c < l; ++c)
     136             :             {
     137          30 :                 if(paths[c] != ".."
     138          15 :                 && (c + 1 >= l || paths[c + 1] != ".."))
     139             :                 {
     140           9 :                     expected += '/';
     141           9 :                     expected += paths[c];
     142             :                 }
     143             : 
     144          15 :                 path += paths[c];
     145             : 
     146          15 :                 count = rand() % 10 + 1;
     147          30 :                 cppthread::plugin_paths::path_t sep(count , '/');
     148          15 :                 path += sep;
     149             :             }
     150             : 
     151             : //std::cerr << "+++ expected = [" << expected << "] and path [" << path << "]\n";
     152             : 
     153             :             // verify that we got expected as a canonicalize path
     154             :             //
     155           5 :             CATCH_CHECK(p.canonicalize(expected) == expected);
     156           5 :             CATCH_REQUIRE(p.canonicalize(path) == expected);
     157             : 
     158           5 :             p.set_allow_redirects(true);
     159           5 :             CATCH_CHECK(p.canonicalize(expected) == expected);
     160           5 :             CATCH_REQUIRE(p.canonicalize(path) == expected);
     161             : 
     162           5 :             p.set_allow_redirects(false);
     163           5 :             CATCH_CHECK(p.canonicalize(expected) == expected);
     164           5 :             CATCH_REQUIRE(p.canonicalize(path) == expected);
     165             :         }
     166             :     }
     167             :     CATCH_END_SECTION()
     168             : 
     169          20 :     CATCH_START_SECTION("canonicalize root path with too many \"..\"")
     170             :     {
     171           2 :         cppthread::plugin_paths p;
     172             : 
     173           1 :         p.set_allow_redirects(false);
     174           1 :         CATCH_REQUIRE(p.canonicalize("/this/long/../../../..//") == "/");
     175           1 :         p.set_allow_redirects(true);
     176           1 :         CATCH_REQUIRE(p.canonicalize("/this/long/../../../..//") == "/");
     177             : 
     178           1 :         p.set_allow_redirects(false);
     179           1 :         CATCH_REQUIRE(p.canonicalize("/this//long/../../../../root/home/path/") == "/root/home/path");
     180           1 :         p.set_allow_redirects(true);
     181           1 :         CATCH_REQUIRE(p.canonicalize("/this//long/../../../../root/home/path/") == "/root/home/path");
     182           1 :         p.set_allow_redirects(false);
     183           1 :         CATCH_REQUIRE(p.canonicalize("/this/long/../..//./../root/home/path/") == "/root/home/path");
     184           1 :         p.set_allow_redirects(true);
     185           1 :         CATCH_REQUIRE(p.canonicalize("/this/long/../..//./../root/home/path/") == "/root/home/path");
     186           1 :         p.set_allow_redirects(false);
     187           1 :         CATCH_REQUIRE(p.canonicalize("/this/long/.././../../root//home/path/") == "/root/home/path");
     188           1 :         p.set_allow_redirects(true);
     189           1 :         CATCH_REQUIRE(p.canonicalize("/this/long/.././../../root//home/path/") == "/root/home/path");
     190             :     }
     191             :     CATCH_END_SECTION()
     192             : 
     193          20 :     CATCH_START_SECTION("canonicalize relative path with \".\" and \"..\"")
     194             :     {
     195           2 :         cppthread::plugin_paths p;
     196             : 
     197           1 :         CATCH_REQUIRE(p.canonicalize("this/./relative/./angle/.././path//cleaned/up") == "this/relative/path/cleaned/up");
     198           1 :         p.set_allow_redirects(true);
     199           1 :         CATCH_REQUIRE(p.canonicalize("this/./relative/./angle/.././path//cleaned/up") == "this/relative/path/cleaned/up");
     200           1 :         p.set_allow_redirects(false);
     201           1 :         CATCH_REQUIRE(p.canonicalize("this/./relative/./angle/.././path//cleaned/up") == "this/relative/path/cleaned/up");
     202             :     }
     203             :     CATCH_END_SECTION()
     204             : 
     205          20 :     CATCH_START_SECTION("canonicalize relative path with too many \"..\"")
     206             :     {
     207           2 :         cppthread::plugin_paths p;
     208             : 
     209           1 :         p.set_allow_redirects(true);
     210           1 :         CATCH_REQUIRE(p.canonicalize("this/long/../../../..//") == "../..");
     211           1 :         p.set_allow_redirects(false);
     212           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     213             :                   p.canonicalize("this/long/../../../..//")
     214             :                 , cppthread::cppthread_invalid_error
     215             :                 , Catch::Matchers::ExceptionMessage(
     216             :                           "cppthread_exception: the path \"this/long/../../../..//\" going outside of the allowed range."));
     217             : 
     218           1 :         p.set_allow_redirects(true);
     219           1 :         CATCH_REQUIRE(p.canonicalize("this//long/../../../../root/home/path/") == "../../root/home/path");
     220           1 :         p.set_allow_redirects(false);
     221           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     222             :                   p.canonicalize("this//long/../../../../root/home/path/")
     223             :                 , cppthread::cppthread_invalid_error
     224             :                 , Catch::Matchers::ExceptionMessage(
     225             :                           "cppthread_exception: the path \"this//long/../../../../root/home/path/\" going outside of the allowed range."));
     226             : 
     227           1 :         p.set_allow_redirects(true);
     228           1 :         CATCH_REQUIRE(p.canonicalize("this/long/..//./../../root/home/path/") == "../root/home/path");
     229           1 :         p.set_allow_redirects(false);
     230           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     231             :                   p.canonicalize("this/long/..//./../../root/home/path/")
     232             :                 , cppthread::cppthread_invalid_error
     233             :                 , Catch::Matchers::ExceptionMessage(
     234             :                           "cppthread_exception: the path \"this/long/..//./../../root/home/path/\" going outside of the allowed range."));
     235             : 
     236           1 :         p.set_allow_redirects(true);
     237           1 :         CATCH_REQUIRE(p.canonicalize("this/long/../.././../root//home//path//") == "../root/home/path");
     238           1 :         p.set_allow_redirects(false);
     239           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     240             :                   p.canonicalize("this/long/../.././../root//home//path//")
     241             :                 , cppthread::cppthread_invalid_error
     242             :                 , Catch::Matchers::ExceptionMessage(
     243             :                           "cppthread_exception: the path \"this/long/../.././../root//home//path//\" going outside of the allowed range."));
     244             :     }
     245             :     CATCH_END_SECTION()
     246             : 
     247          20 :     CATCH_START_SECTION("push the same paths")
     248             :     {
     249           2 :         cppthread::plugin_paths p;
     250             : 
     251           1 :         p.push("path/one");
     252           1 :         p.push("path/two");
     253           1 :         p.push("path/three");
     254           1 :         p.push("path/two");
     255           1 :         p.push("path/one");
     256             : 
     257           1 :         CATCH_REQUIRE(p.size() == 3);
     258           1 :         CATCH_REQUIRE(p.at(0) == "path/one");
     259           1 :         CATCH_REQUIRE(p.at(1) == "path/two");
     260           1 :         CATCH_REQUIRE(p.at(2) == "path/three");
     261           1 :         CATCH_REQUIRE(p.at(3) == "");
     262             : 
     263           1 :         p.erase("path/four");
     264             : 
     265           1 :         CATCH_REQUIRE(p.size() == 3);
     266           1 :         CATCH_REQUIRE(p.at(0) == "path/one");
     267           1 :         CATCH_REQUIRE(p.at(1) == "path/two");
     268           1 :         CATCH_REQUIRE(p.at(2) == "path/three");
     269           1 :         CATCH_REQUIRE(p.at(3) == "");
     270             : 
     271           1 :         p.erase("path/two");
     272             : 
     273           1 :         CATCH_REQUIRE(p.size() == 2);
     274           1 :         CATCH_REQUIRE(p.at(0) == "path/one");
     275           1 :         CATCH_REQUIRE(p.at(1) == "path/three");
     276           1 :         CATCH_REQUIRE(p.at(2) == "");
     277           1 :         CATCH_REQUIRE(p.at(3) == "");
     278             : 
     279           1 :         p.erase("path/one");
     280             : 
     281           1 :         CATCH_REQUIRE(p.size() == 1);
     282           1 :         CATCH_REQUIRE(p.at(0) == "path/three");
     283           1 :         CATCH_REQUIRE(p.at(1) == "");
     284           1 :         CATCH_REQUIRE(p.at(2) == "");
     285           1 :         CATCH_REQUIRE(p.at(3) == "");
     286             : 
     287           1 :         p.erase("path/three");
     288             : 
     289           1 :         CATCH_REQUIRE(p.size() == 0);
     290           1 :         CATCH_REQUIRE(p.at(0) == "");
     291           1 :         CATCH_REQUIRE(p.at(1) == "");
     292           1 :         CATCH_REQUIRE(p.at(2) == "");
     293           1 :         CATCH_REQUIRE(p.at(3) == "");
     294             :     }
     295             :     CATCH_END_SECTION()
     296             : 
     297          20 :     CATCH_START_SECTION("push invalid path")
     298             :     {
     299           2 :         cppthread::plugin_paths p;
     300             : 
     301           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     302             :                   p.canonicalize("this/long/../.././../root//home//path//")
     303             :                 , cppthread::cppthread_invalid_error
     304             :                 , Catch::Matchers::ExceptionMessage(
     305             :                           "cppthread_exception: the path \"this/long/../.././../root//home//path//\" going outside of the allowed range."));
     306             :     }
     307             :     CATCH_END_SECTION()
     308             : 
     309          20 :     CATCH_START_SECTION("add paths")
     310             :     {
     311           2 :         cppthread::plugin_paths p;
     312             : 
     313           1 :         p.set_allow_redirects(true);
     314           1 :         p.add("this/long/../../../..//"
     315             :              ":this//long/../../../../root/home/path/"
     316             :              ":this/long/..//./../../root/home/path/"
     317             :              ":this/long/../.././..//home/user/path//");
     318           1 :         CATCH_REQUIRE(p.size() == 4);
     319           1 :         CATCH_REQUIRE(p.at(0) == "../..");
     320           1 :         CATCH_REQUIRE(p.at(1) == "../../root/home/path");
     321           1 :         CATCH_REQUIRE(p.at(2) == "../root/home/path");
     322           1 :         CATCH_REQUIRE(p.at(3) == "../home/user/path");
     323             :     }
     324             :     CATCH_END_SECTION()
     325          10 : }
     326             : 
     327             : 
     328             : 
     329          11 : CATCH_TEST_CASE("plugin_names", "[plugins] [names]")
     330             : {
     331          18 :     CATCH_START_SECTION("empty by default")
     332             :     {
     333           2 :         cppthread::plugin_paths p;
     334           1 :         p.add("/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     335             : 
     336           2 :         cppthread::plugin_names n(p);
     337             : 
     338           1 :         CATCH_REQUIRE(n.names().empty());
     339             :     }
     340             :     CATCH_END_SECTION()
     341             : 
     342          18 :     CATCH_START_SECTION("validate names")
     343             :     {
     344           2 :         cppthread::plugin_paths p;
     345           1 :         p.add("/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     346             : 
     347           2 :         cppthread::plugin_names n(p);
     348             : 
     349           1 :         CATCH_CHECK(n.validate("_"));
     350           1 :         CATCH_CHECK(n.validate("_valid"));
     351           1 :         CATCH_CHECK(n.validate("_identifier6"));
     352           1 :         CATCH_CHECK(n.validate("_9"));
     353             : 
     354           1 :         CATCH_CHECK_FALSE(n.validate(""));
     355           1 :         CATCH_CHECK_FALSE(n.validate(cppthread::plugin_names::name_t()));
     356           1 :         CATCH_CHECK_FALSE(n.validate("0"));
     357           1 :         CATCH_CHECK_FALSE(n.validate("9_"));
     358           1 :         CATCH_CHECK_FALSE(n.validate("dotted.word"));
     359           1 :         CATCH_CHECK_FALSE(n.validate(".dot"));
     360           1 :         CATCH_CHECK_FALSE(n.validate("dashed-word"));
     361           1 :         CATCH_CHECK_FALSE(n.validate("-dash"));
     362             : 
     363          27 :         for(int c('a'); c <= 'z'; ++c)
     364             :         {
     365          52 :             std::string word;
     366          26 :             word += c;
     367          26 :             CATCH_CHECK(n.validate(word));
     368             :         }
     369             : 
     370          27 :         for(int c('A'); c <= 'Z'; ++c)
     371             :         {
     372          52 :             std::string word;
     373          26 :             word += c;
     374          26 :             CATCH_CHECK(n.validate(word));
     375             :         }
     376             : 
     377          11 :         for(int c('0'); c <= '9'; ++c)
     378             :         {
     379          20 :             std::string word;
     380          10 :             word += '_';
     381          10 :             word += c;
     382          10 :             CATCH_CHECK(n.validate(word));
     383             :         }
     384             : 
     385         128 :         for(int c(1); c <= 0x7F; ++c)
     386             :         {
     387         190 :             if(c == '_'
     388         126 :             || (c >= 'a' && c <= 'z')
     389         100 :             || (c >= 'A' && c <= 'Z')
     390          74 :             || (c >= '0' && c <= '9'))
     391             :             {
     392          63 :                 continue;
     393             :             }
     394         128 :             std::string word;
     395          64 :             word += '_';
     396          64 :             word += c;
     397          64 :             CATCH_CHECK_FALSE(n.validate(word));
     398             :         }
     399             :     }
     400             :     CATCH_END_SECTION()
     401             : 
     402          18 :     CATCH_START_SECTION("validate non-script names")
     403             :     {
     404           2 :         cppthread::plugin_paths p;
     405           1 :         p.add("/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     406             : 
     407           2 :         cppthread::plugin_names n(p, true);
     408             : 
     409           1 :         CATCH_CHECK(n.validate("_"));
     410           1 :         CATCH_CHECK(n.validate("_valid"));
     411           1 :         CATCH_CHECK(n.validate("_identifier6"));
     412           1 :         CATCH_CHECK(n.validate("_9"));
     413             : 
     414           1 :         CATCH_CHECK_FALSE(n.validate(""));
     415           1 :         CATCH_CHECK_FALSE(n.validate(cppthread::plugin_names::name_t()));
     416           1 :         CATCH_CHECK_FALSE(n.validate("0"));
     417           1 :         CATCH_CHECK_FALSE(n.validate("9_"));
     418           1 :         CATCH_CHECK_FALSE(n.validate("dotted.word"));
     419           1 :         CATCH_CHECK_FALSE(n.validate(".dot"));
     420           1 :         CATCH_CHECK_FALSE(n.validate("dashed-word"));
     421           1 :         CATCH_CHECK_FALSE(n.validate("-dash"));
     422             : 
     423          27 :         for(int c('a'); c <= 'z'; ++c)
     424             :         {
     425          52 :             std::string word;
     426          26 :             word += c;
     427          26 :             CATCH_CHECK(n.validate(word));
     428             :         }
     429             : 
     430          27 :         for(int c('A'); c <= 'Z'; ++c)
     431             :         {
     432          52 :             std::string word;
     433          26 :             word += c;
     434          26 :             CATCH_CHECK(n.validate(word));
     435             :         }
     436             : 
     437          11 :         for(int c('0'); c <= '9'; ++c)
     438             :         {
     439          20 :             std::string word;
     440          10 :             word += '_';
     441          10 :             word += c;
     442          10 :             CATCH_CHECK(n.validate(word));
     443             :         }
     444             : 
     445         128 :         for(int c(1); c <= 0x7F; ++c)
     446             :         {
     447         190 :             if(c == '_'
     448         126 :             || (c >= 'a' && c <= 'z')
     449         100 :             || (c >= 'A' && c <= 'Z')
     450          74 :             || (c >= '0' && c <= '9'))
     451             :             {
     452          63 :                 continue;
     453             :             }
     454         128 :             std::string word;
     455          64 :             word += '_';
     456          64 :             word += c;
     457          64 :             CATCH_CHECK_FALSE(n.validate(word));
     458             :         }
     459             : 
     460           1 :         std::vector<std::string> const reserved_keywords = {
     461             :               "await"
     462             :             , "break"
     463             :             , "case"
     464             :             , "catch"
     465             :             , "class"
     466             :             , "const"
     467             :             , "continue"
     468             :             , "debugger"
     469             :             , "default"
     470             :             , "delete"
     471             :             , "do"
     472             :             , "else"
     473             :             , "enum"
     474             :             , "export"
     475             :             , "extends"
     476             :             , "false"
     477             :             , "finally"
     478             :             , "for"
     479             :             , "function"
     480             :             , "if"
     481             :             , "import"
     482             :             , "in"
     483             :             , "instanceof"
     484             :             , "new"
     485             :             , "null"
     486             :             , "return"
     487             :             , "super"
     488             :             , "switch"
     489             :             , "this"
     490             :             , "throw"
     491             :             , "true"
     492             :             , "try"
     493             :             , "typeof"
     494             :             , "var"
     495             :             , "void"
     496             :             , "while"
     497             :             , "with"
     498             :             , "yield"
     499           2 :         };
     500          39 :         for(auto k : reserved_keywords)
     501             :         {
     502          38 :             CATCH_CHECK_FALSE(n.validate(k));
     503             :         }
     504             :     }
     505             :     CATCH_END_SECTION()
     506             : 
     507          18 :     CATCH_START_SECTION("add one unknown and one known name")
     508             :     {
     509           2 :         cppthread::plugin_paths p;
     510           1 :         p.add(CMAKE_BINARY_DIR "/tests:/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     511             : 
     512           2 :         cppthread::plugin_names n(p, true);
     513             : 
     514             :         // test with an obviously unexistant plugin
     515             :         //
     516           2 :         cppthread::plugin_names::filename_t filename(n.to_filename("unknown"));
     517           1 :         CATCH_REQUIRE(filename.empty());
     518             : 
     519             :         // test with the real thing
     520             :         //
     521           1 :         filename = n.to_filename("testme");
     522           1 :         CATCH_REQUIRE(filename == CMAKE_BINARY_DIR "/tests/libtestme.so");
     523             : 
     524             :         // the following creates fake plugins so we can test all possible
     525             :         // cases (there are 4 of them)
     526             :         //
     527             :         {       // <name>.so
     528           2 :             std::string fake(CMAKE_BINARY_DIR "/tests/fake.so");
     529           1 :             unlink(fake.c_str());
     530             :             {
     531           2 :                 std::ofstream out(fake);
     532           1 :                 out << "fake plugin 1\n";
     533             :             }
     534           1 :             filename = n.to_filename("fake");
     535           1 :             CATCH_REQUIRE(filename.empty());
     536           1 :             chmod(fake.c_str(), 0755);
     537           1 :             filename = n.to_filename("fake");
     538           1 :             CATCH_REQUIRE(filename == fake);
     539           1 :             unlink(fake.c_str());
     540             :         }
     541             :         {       // lib<name>.so
     542           2 :             std::string fake(CMAKE_BINARY_DIR "/tests/libfake.so");
     543           1 :             unlink(fake.c_str());
     544             :             {
     545           2 :                 std::ofstream out(fake);
     546           1 :                 out << "fake plugin 2\n";
     547             :             }
     548           1 :             filename = n.to_filename("fake");
     549           1 :             CATCH_REQUIRE(filename.empty());
     550           1 :             chmod(fake.c_str(), 0755);
     551           1 :             filename = n.to_filename("fake");
     552           1 :             CATCH_REQUIRE(filename == fake);
     553           1 :             unlink(fake.c_str());
     554             :         }
     555             :         {       // <name>/<name>.so
     556           2 :             std::string subdir(CMAKE_BINARY_DIR "/tests/fake");
     557           1 :             mkdir(subdir.c_str(), 0750);
     558             :             {
     559           2 :                 std::string fake(CMAKE_BINARY_DIR "/tests/fake/fake.so");
     560           1 :                 unlink(fake.c_str());
     561             :                 {
     562           2 :                     std::ofstream out(fake);
     563           1 :                     out << "fake plugin 3\n";
     564             :                 }
     565           1 :                 filename = n.to_filename("fake");
     566           1 :                 CATCH_REQUIRE(filename.empty());
     567           1 :                 chmod(fake.c_str(), 0755);
     568           1 :                 filename = n.to_filename("fake");
     569           1 :                 CATCH_REQUIRE(filename == fake);
     570           1 :                 unlink(fake.c_str());
     571             :             }
     572             :             {
     573           2 :                 std::string fake(CMAKE_BINARY_DIR "/tests/fake/libfake.so");
     574           1 :                 unlink(fake.c_str());
     575             :                 {
     576           2 :                     std::ofstream out(fake);
     577           1 :                     out << "fake plugin 4\n";
     578             :                 }
     579           1 :                 filename = n.to_filename("fake");
     580           1 :                 CATCH_REQUIRE(filename.empty());
     581           1 :                 chmod(fake.c_str(), 0755);
     582           1 :                 filename = n.to_filename("fake");
     583           1 :                 CATCH_REQUIRE(filename == fake);
     584           1 :                 unlink(fake.c_str());
     585             :             }
     586           1 :             rmdir(subdir.c_str());
     587             :         }
     588             :     }
     589             :     CATCH_END_SECTION()
     590             : 
     591          18 :     CATCH_START_SECTION("test filename without any paths")
     592             :     {
     593           2 :         cppthread::plugin_paths p;
     594           2 :         cppthread::plugin_names n(p);
     595             : 
     596             :         // test with an obviously unexistant plugin
     597             :         //
     598           2 :         cppthread::plugin_names::filename_t filename(n.to_filename("unknown"));
     599           1 :         CATCH_REQUIRE(filename.empty());
     600             : 
     601             :         // test with the real thing
     602             :         //
     603           1 :         filename = n.to_filename("testme");
     604           1 :         CATCH_REQUIRE(filename.empty());
     605             : 
     606             :         // the following creates fake plugins so we can test all possible
     607             :         // cases (there are 4 of them)
     608             :         //
     609             :         {       // <name>.so
     610           2 :             std::string fake("fake.so");
     611           1 :             unlink(fake.c_str());
     612             :             {
     613           2 :                 std::ofstream out(fake);
     614           1 :                 out << "fake plugin 1\n";
     615             :             }
     616           1 :             filename = n.to_filename("fake");
     617           1 :             CATCH_REQUIRE(filename.empty());
     618           1 :             chmod(fake.c_str(), 0755);
     619           1 :             filename = n.to_filename("fake");
     620           1 :             CATCH_REQUIRE(filename == "./" + fake);
     621           1 :             unlink(fake.c_str());
     622             :         }
     623             :         {       // lib<name>.so
     624           2 :             std::string fake("libfake.so");
     625           1 :             unlink(fake.c_str());
     626             :             {
     627           2 :                 std::ofstream out(fake);
     628           1 :                 out << "fake plugin 2\n";
     629             :             }
     630           1 :             filename = n.to_filename("fake");
     631           1 :             CATCH_REQUIRE(filename.empty());
     632           1 :             chmod(fake.c_str(), 0755);
     633           1 :             filename = n.to_filename("fake");
     634           1 :             CATCH_REQUIRE(filename == "./" + fake);
     635           1 :             unlink(fake.c_str());
     636             :         }
     637             :         {       // <name>/<name>.so
     638           2 :             std::string subdir("fake");
     639           1 :             mkdir(subdir.c_str(), 0750);
     640             :             {
     641           2 :                 std::string fake("fake/fake.so");
     642           1 :                 unlink(fake.c_str());
     643             :                 {
     644           2 :                     std::ofstream out(fake);
     645           1 :                     out << "fake plugin 3\n";
     646             :                 }
     647           1 :                 filename = n.to_filename("fake");
     648           1 :                 CATCH_REQUIRE(filename.empty());
     649           1 :                 chmod(fake.c_str(), 0755);
     650           1 :                 filename = n.to_filename("fake");
     651           1 :                 CATCH_REQUIRE(filename == "./" + fake);
     652           1 :                 unlink(fake.c_str());
     653             :             }
     654             :             {
     655           2 :                 std::string fake("fake/libfake.so");
     656           1 :                 unlink(fake.c_str());
     657             :                 {
     658           2 :                     std::ofstream out(fake);
     659           1 :                     out << "fake plugin 4\n";
     660             :                 }
     661           1 :                 filename = n.to_filename("fake");
     662           1 :                 CATCH_REQUIRE(filename.empty());
     663           1 :                 chmod(fake.c_str(), 0755);
     664           1 :                 filename = n.to_filename("fake");
     665           1 :                 CATCH_REQUIRE(filename == "./" + fake);
     666           1 :                 unlink(fake.c_str());
     667             :             }
     668           1 :             rmdir(subdir.c_str());
     669             :         }
     670             :     }
     671             :     CATCH_END_SECTION()
     672             : 
     673          18 :     CATCH_START_SECTION("add a new names by hand (push)")
     674             :     {
     675           2 :         cppthread::plugin_paths p;
     676           1 :         p.add(CMAKE_BINARY_DIR "/tests:/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     677           2 :         cppthread::plugin_names n(p);
     678             : 
     679             :         // test with an obviously unexistant plugin
     680             :         //
     681           1 :         n.push("testme");
     682           1 :         CATCH_REQUIRE(n.names().size() == 1);
     683           1 :         CATCH_REQUIRE(n.names().begin()->second == CMAKE_BINARY_DIR "/tests/libtestme.so");
     684             :     }
     685             :     CATCH_END_SECTION()
     686             : 
     687          18 :     CATCH_START_SECTION("add a new names by hand (add)")
     688             :     {
     689           2 :         cppthread::plugin_paths p;
     690           1 :         p.add(CMAKE_BINARY_DIR "/tests:/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     691           2 :         cppthread::plugin_names n(p);
     692             : 
     693             :         // TODO: look into having multiple plugins because that would allow
     694             :         //       us to test ':'
     695             :         //
     696           1 :         n.add("testme");
     697           1 :         CATCH_REQUIRE(n.names().size() == 1);
     698           1 :         CATCH_REQUIRE(n.names().begin()->second == CMAKE_BINARY_DIR "/tests/libtestme.so");
     699             :     }
     700             :     CATCH_END_SECTION()
     701             : 
     702          18 :     CATCH_START_SECTION("add a names through the find_plugins() function")
     703             :     {
     704           2 :         cppthread::plugin_paths p;
     705           1 :         p.add(CMAKE_BINARY_DIR "/tests:/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     706           2 :         cppthread::plugin_names n(p);
     707           1 :         n.find_plugins();
     708           1 :         CATCH_REQUIRE(n.names().size() == 1);
     709           1 :         CATCH_REQUIRE(n.names().begin()->second == CMAKE_BINARY_DIR "/tests/libtestme.so");
     710             :     }
     711             :     CATCH_END_SECTION()
     712             : 
     713          18 :     CATCH_START_SECTION("add invalid names")
     714             :     {
     715           2 :         cppthread::plugin_paths p;
     716           1 :         p.add(CMAKE_BINARY_DIR "/tests:/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     717           2 :         cppthread::plugin_names n(p);
     718             : 
     719           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     720             :                   n.push("invalid-name")
     721             :                 , cppthread::cppthread_invalid_error
     722             :                 , Catch::Matchers::ExceptionMessage(
     723             :                           "cppthread_exception: invalid plugin name in \"invalid-name\"."));
     724             : 
     725           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     726             :                   n.push("non_existant")
     727             :                 , cppthread::cppthread_not_found
     728             :                 , Catch::Matchers::ExceptionMessage(
     729             :                           "cppthread_exception: plugin named \"non_existant\" not found in any of the specified paths."));
     730             : 
     731           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     732             :                   n.push("./libserver.so")
     733             :                 , cppthread::cppthread_invalid_error
     734             :                 , Catch::Matchers::ExceptionMessage(
     735             :                           "cppthread_exception: the name \"server\" is reserved for the main running process."));
     736             : 
     737           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     738             :                   n.push("./libjuju1.23.so")
     739             :                 , cppthread::cppthread_invalid_error
     740             :                 , Catch::Matchers::ExceptionMessage(
     741             :                           "cppthread_exception: invalid plugin name in \"juju1.23\" (from path \"./libjuju1.23.so\")."));
     742             :     }
     743             :     CATCH_END_SECTION()
     744           9 : }
     745             : 
     746             : 
     747           3 : CATCH_TEST_CASE("plugin_collection", "[plugins] [collection]")
     748             : {
     749           2 :     CATCH_START_SECTION("load the plugin")
     750             :     {
     751           2 :         cppthread::plugin_paths p;
     752           1 :         p.add(CMAKE_BINARY_DIR "/tests:/usr/local/lib/snaplogger/plugins:/usr/lib/snaplogger/plugins");
     753           2 :         cppthread::plugin_names n(p);
     754           1 :         n.find_plugins();
     755           2 :         cppthread::plugin_collection c(n);
     756           1 :         optional_namespace::data_t d;
     757           1 :         d.f_value = 0xA987;
     758           1 :         c.set_data(&d);
     759           1 :         CATCH_REQUIRE(c.load_plugins());
     760           2 :         optional_namespace::testme::pointer_t r(c.get_plugin_by_name<optional_namespace::testme>("testme"));
     761           1 :         CATCH_REQUIRE(r != nullptr);
     762             : 
     763           1 :         cppthread::version_t const v(r->version());
     764           1 :         CATCH_CHECK(v.f_major == 5);
     765           1 :         CATCH_CHECK(v.f_minor == 3);
     766           1 :         CATCH_CHECK(v.f_patch == 0);
     767             : 
     768             :         //time_t m(last_modification());
     769             : 
     770           1 :         CATCH_REQUIRE(r->name() == "testme");
     771           1 :         CATCH_REQUIRE(r->filename() == CMAKE_BINARY_DIR "/tests/libtestme.so");
     772           1 :         CATCH_REQUIRE(r->description() == "a test plugin to make sure it all works.");
     773           1 :         CATCH_REQUIRE(r->help_uri() == "https://snapwebsites.org/");
     774           1 :         CATCH_REQUIRE(r->icon() == "cute.ico");
     775             : 
     776           2 :         cppthread::string_set_t tags(r->categorization_tags());
     777           1 :         CATCH_REQUIRE(tags.size() == 3);
     778           1 :         CATCH_REQUIRE(tags.find("test") != tags.end());
     779           1 :         CATCH_REQUIRE(tags.find("powerful") != tags.end());
     780           1 :         CATCH_REQUIRE(tags.find("software") != tags.end());
     781           1 :         CATCH_REQUIRE(tags.find("undefined") == tags.end());
     782             : 
     783             :         // at this time we have a single plugins so not dependencies
     784             :         //
     785           2 :         cppthread::string_set_t dependencies(r->dependencies());
     786           1 :         CATCH_REQUIRE(dependencies.empty());
     787             : 
     788           2 :         cppthread::string_set_t conflicts(r->conflicts());
     789           1 :         CATCH_REQUIRE(conflicts.size() == 3);
     790           1 :         CATCH_REQUIRE(conflicts.find("other_test") != conflicts.end());
     791           1 :         CATCH_REQUIRE(conflicts.find("power_test") != conflicts.end());
     792           1 :         CATCH_REQUIRE(conflicts.find("unknown") != conflicts.end());
     793           1 :         CATCH_REQUIRE(conflicts.find("undefined") == conflicts.end());
     794             : 
     795           1 :         cppthread::string_set_t suggestions(r->suggestions());
     796             : 
     797             :         // TODO: this requires a signal...
     798             :         //std::string const msg(r->it_worked());
     799             :         //CATCH_CHECK(msg == "it worked, didn't it?");
     800             :     }
     801             :     CATCH_END_SECTION()
     802           7 : }
     803             : 
     804             : 
     805             : 
     806             : 
     807             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13