LCOV - code coverage report
Current view: top level - tests - catch_process.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 181 181 100.0 %
Date: 2021-09-19 09:06:58 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2021  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/eventdispatcher
       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 St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : 
      20             : // self
      21             : //
      22             : #include    "catch_main.h"
      23             : 
      24             : 
      25             : // cppprocess lib
      26             : //
      27             : #include    <cppprocess/process.h>
      28             : 
      29             : 
      30             : // snapdev lib
      31             : //
      32             : #include    <snapdev/file_contents.h>
      33             : 
      34             : 
      35             : // C++ lib
      36             : //
      37             : #include    <fstream>
      38             : 
      39             : 
      40             : // C lib
      41             : //
      42             : //#include    <sys/resource.h>
      43             : //#include    <sys/times.h>
      44             : 
      45             : 
      46             : // last include
      47             : //
      48             : #include    <snapdev/poison.h>
      49             : 
      50             : 
      51             : 
      52           8 : CATCH_TEST_CASE("Process", "[process]")
      53             : {
      54          12 :     CATCH_START_SECTION("simple cat")
      55             :     {
      56           2 :         cppprocess::process p("simple-cat");
      57             : 
      58           1 :         CATCH_REQUIRE(p.get_name() == "simple-cat");
      59             : 
      60           1 :         CATCH_REQUIRE_FALSE(p.get_forced_environment());
      61           1 :         p.set_forced_environment(true);
      62           1 :         CATCH_REQUIRE(p.get_forced_environment());
      63           1 :         p.set_forced_environment(false);
      64           1 :         CATCH_REQUIRE_FALSE(p.get_forced_environment());
      65             : 
      66           1 :         CATCH_REQUIRE(p.get_command() == std::string());
      67           1 :         p.set_command("cat");
      68           1 :         CATCH_REQUIRE(p.get_command() == "cat");
      69             : 
      70           1 :         CATCH_REQUIRE(p.get_arguments().empty());
      71           1 :         p.add_argument("/proc/self/comm");
      72           1 :         CATCH_REQUIRE(p.get_arguments().size() == 1);
      73             : 
      74           1 :         CATCH_REQUIRE(p.get_environ().empty());
      75             : 
      76           1 :         CATCH_REQUIRE(p.get_input().empty());
      77           1 :         CATCH_REQUIRE(p.get_binary_input().empty());
      78           1 :         CATCH_REQUIRE(p.get_input_pipe() == nullptr);
      79             : 
      80           1 :         CATCH_REQUIRE_FALSE(p.get_capture_output());
      81           1 :         p.set_capture_output();
      82           1 :         CATCH_REQUIRE(p.get_capture_output());
      83             : 
      84           1 :         CATCH_REQUIRE(p.get_output().empty());
      85           1 :         CATCH_REQUIRE(p.get_binary_output().empty());
      86           1 :         CATCH_REQUIRE(p.get_output_pipe() == nullptr);
      87           1 :         CATCH_REQUIRE(p.get_next_processes().empty());
      88             : 
      89           1 :         CATCH_REQUIRE(p.get_error().empty());
      90           1 :         CATCH_REQUIRE(p.get_binary_error().empty());
      91           1 :         CATCH_REQUIRE(p.get_error_pipe() == nullptr);
      92             : 
      93           1 :         CATCH_REQUIRE(p.start() == 0);
      94             : 
      95           1 :         int const code(p.wait());
      96           1 :         CATCH_REQUIRE(code == 0);
      97             : 
      98           1 :         CATCH_REQUIRE(p.get_input().empty());
      99           1 :         CATCH_REQUIRE(p.get_binary_input().empty());
     100           1 :         CATCH_REQUIRE(p.get_input_pipe() == nullptr);
     101             : 
     102           1 :         CATCH_REQUIRE(p.get_error().empty());
     103           1 :         CATCH_REQUIRE(p.get_binary_error().empty());
     104           1 :         CATCH_REQUIRE(p.get_error_pipe() == nullptr);
     105             : 
     106           1 :         CATCH_REQUIRE(p.get_output() == "cat\n");
     107           1 :         CATCH_REQUIRE(p.get_trimmed_output() == "cat");
     108             : 
     109           2 :         cppprocess::buffer_t const output(p.get_binary_output());
     110           1 :         CATCH_REQUIRE(output.size() == 4);
     111           1 :         CATCH_REQUIRE(output[0] == 'c');
     112           1 :         CATCH_REQUIRE(output[1] == 'a');
     113           1 :         CATCH_REQUIRE(output[2] == 't');
     114           1 :         CATCH_REQUIRE(output[3] == '\n');
     115             :     }
     116             :     CATCH_END_SECTION()
     117             : 
     118          12 :     CATCH_START_SECTION("simple logger, we pipe the input as the message")
     119             :     {
     120           2 :         cppprocess::process p("in-logger");
     121             : 
     122           1 :         CATCH_REQUIRE(p.get_name() == "in-logger");
     123             : 
     124           1 :         CATCH_REQUIRE(p.get_command() == std::string());
     125           1 :         p.set_command("logger");
     126           1 :         CATCH_REQUIRE(p.get_command() == "logger");
     127             : 
     128           1 :         CATCH_REQUIRE(p.get_arguments().empty());
     129             : 
     130           1 :         CATCH_REQUIRE(p.get_environ().empty());
     131             : 
     132           1 :         CATCH_REQUIRE(p.get_input().empty());
     133           1 :         CATCH_REQUIRE(p.get_binary_input().empty());
     134           1 :         CATCH_REQUIRE(p.get_input_pipe() == nullptr);
     135             : 
     136           1 :         p.add_input("Event Dispatcher Process Test\n");
     137             : 
     138           1 :         CATCH_REQUIRE(p.get_input() == std::string("Event Dispatcher Process Test\n"));
     139           1 :         CATCH_REQUIRE(p.get_binary_input().size() == 30);
     140           1 :         CATCH_REQUIRE(p.get_input_pipe() == nullptr);
     141             : 
     142           1 :         CATCH_REQUIRE_FALSE(p.get_capture_output());
     143           1 :         CATCH_REQUIRE(p.get_output().empty());
     144           1 :         CATCH_REQUIRE(p.get_binary_output().empty());
     145           1 :         CATCH_REQUIRE(p.get_output_pipe() == nullptr);
     146           1 :         CATCH_REQUIRE(p.get_next_processes().empty());
     147             : 
     148           1 :         CATCH_REQUIRE(p.get_error().empty());
     149           1 :         CATCH_REQUIRE(p.get_binary_error().empty());
     150           1 :         CATCH_REQUIRE(p.get_error_pipe() == nullptr);
     151             : 
     152           1 :         CATCH_REQUIRE(p.start() == 0);
     153             : 
     154           1 :         int const code(p.wait());
     155           1 :         CATCH_REQUIRE(code == 0);
     156             :     }
     157             :     CATCH_END_SECTION()
     158             : 
     159          12 :     CATCH_START_SECTION("in | sed | out")
     160             :     {
     161           2 :         cppprocess::process p("in-sed-out");
     162             : 
     163           1 :         CATCH_REQUIRE(p.get_name() == "in-sed-out");
     164             : 
     165           1 :         CATCH_REQUIRE_FALSE(p.get_forced_environment());
     166           1 :         p.set_forced_environment(true);
     167           1 :         CATCH_REQUIRE(p.get_forced_environment());
     168           1 :         p.set_forced_environment(false);
     169           1 :         CATCH_REQUIRE_FALSE(p.get_forced_environment());
     170             : 
     171           1 :         CATCH_REQUIRE(p.get_command() == std::string());
     172           1 :         p.set_command("sed");
     173           1 :         CATCH_REQUIRE(p.get_command() == "sed");
     174             : 
     175           1 :         CATCH_REQUIRE(p.get_arguments().empty());
     176           1 :         p.add_argument("-e");
     177           1 :         p.add_argument("s/Hello/Hi/");
     178           1 :         p.add_argument("-");
     179           1 :         CATCH_REQUIRE(p.get_arguments().size() == 3);
     180             : 
     181           1 :         CATCH_REQUIRE(p.get_environ().empty());
     182             : 
     183           1 :         CATCH_REQUIRE(p.get_input().empty());
     184           1 :         CATCH_REQUIRE(p.get_binary_input().empty());
     185           1 :         CATCH_REQUIRE(p.get_input_pipe() == nullptr);
     186             : 
     187           1 :         p.add_input("Hello  World!\n");
     188             : 
     189           1 :         CATCH_REQUIRE(p.get_input() == std::string("Hello  World!\n"));
     190           1 :         CATCH_REQUIRE(p.get_binary_input().size() == 14);
     191           1 :         CATCH_REQUIRE(p.get_input_pipe() == nullptr);
     192             : 
     193           1 :         CATCH_REQUIRE_FALSE(p.get_capture_output());
     194           1 :         p.set_capture_output();
     195           1 :         CATCH_REQUIRE(p.get_capture_output());
     196             : 
     197           1 :         CATCH_REQUIRE(p.get_output().empty());
     198           1 :         CATCH_REQUIRE(p.get_binary_output().empty());
     199           1 :         CATCH_REQUIRE(p.get_output_pipe() == nullptr);
     200           1 :         CATCH_REQUIRE(p.get_next_processes().empty());
     201             : 
     202           1 :         CATCH_REQUIRE(p.get_error().empty());
     203           1 :         CATCH_REQUIRE(p.get_binary_error().empty());
     204           1 :         CATCH_REQUIRE(p.get_error_pipe() == nullptr);
     205             : 
     206           1 :         CATCH_REQUIRE(p.start() == 0);
     207             : 
     208           1 :         int const code(p.wait());
     209           1 :         CATCH_REQUIRE(code == 0);
     210             : 
     211           1 :         CATCH_REQUIRE(p.get_output() == "Hi  World!\n");
     212           1 :         CATCH_REQUIRE(p.get_trimmed_output(true) == "Hi World!");
     213             : 
     214           2 :         cppprocess::buffer_t const output(p.get_binary_output());
     215           1 :         CATCH_REQUIRE(output.size() == 11);
     216           1 :         CATCH_REQUIRE(output[ 0] == 'H');
     217           1 :         CATCH_REQUIRE(output[ 1] == 'i');
     218           1 :         CATCH_REQUIRE(output[ 2] == ' ');
     219           1 :         CATCH_REQUIRE(output[ 3] == ' ');
     220           1 :         CATCH_REQUIRE(output[ 4] == 'W');
     221           1 :         CATCH_REQUIRE(output[ 5] == 'o');
     222           1 :         CATCH_REQUIRE(output[ 6] == 'r');
     223           1 :         CATCH_REQUIRE(output[ 7] == 'l');
     224           1 :         CATCH_REQUIRE(output[ 8] == 'd');
     225           1 :         CATCH_REQUIRE(output[ 9] == '!');
     226           1 :         CATCH_REQUIRE(output[10] == '\n');
     227             :     }
     228             :     CATCH_END_SECTION()
     229             : 
     230          12 :     CATCH_START_SECTION("ls unknown-file, expect an error")
     231             :     {
     232           2 :         cppprocess::process p("ls-unknown-file");
     233             : 
     234           1 :         CATCH_REQUIRE(p.get_name() == "ls-unknown-file");
     235             : 
     236           1 :         p.set_command("ls");
     237           1 :         CATCH_REQUIRE(p.get_command() == "ls");
     238             : 
     239           1 :         p.add_argument("unknown-file");
     240           1 :         CATCH_REQUIRE(p.get_arguments().size() == 1);
     241             : 
     242           1 :         CATCH_REQUIRE(p.get_environ().empty());
     243             : 
     244           1 :         CATCH_REQUIRE_FALSE(p.get_capture_error());
     245           1 :         p.set_capture_error();
     246           1 :         CATCH_REQUIRE(p.get_capture_error());
     247             : 
     248           1 :         CATCH_REQUIRE(p.get_error().empty());
     249           1 :         CATCH_REQUIRE(p.get_binary_error().empty());
     250           1 :         CATCH_REQUIRE(p.get_error_pipe() == nullptr);
     251             : 
     252           1 :         CATCH_REQUIRE(p.start() == 0);
     253             : 
     254           1 :         int const code(p.wait());
     255           1 :         CATCH_REQUIRE(code != 0);
     256             : 
     257           1 :         CATCH_REQUIRE(p.get_output().empty());
     258             : 
     259           1 :         CATCH_REQUIRE(!p.get_error().empty());
     260             :         // the error message can change under our feet so at this time I
     261             :         // don't compare anything
     262             :     }
     263             :     CATCH_END_SECTION()
     264             : 
     265          12 :     CATCH_START_SECTION("cat | tr")
     266             :     {
     267           2 :         cppprocess::process::pointer_t tr(std::make_shared<cppprocess::process>("tr"));
     268           1 :         tr->set_command("tr");
     269           1 :         tr->add_argument("TASP");
     270           1 :         tr->add_argument("tasp");
     271           1 :         tr->set_capture_output();
     272             : 
     273           2 :         cppprocess::process p("cat");
     274           1 :         p.set_command("cat");
     275           1 :         p.add_argument("-");
     276           1 :         p.add_input("Test A Simple Pipeline\n");
     277           1 :         p.add_next_process(tr);
     278             : 
     279           1 :         CATCH_REQUIRE(p.start() == 0);
     280             : 
     281           1 :         int const code(p.wait());
     282           1 :         CATCH_REQUIRE(code == 0);
     283             : 
     284           1 :         CATCH_REQUIRE(tr->get_output() == "test a simple pipeline\n");
     285             :     }
     286             :     CATCH_END_SECTION()
     287             : 
     288          12 :     CATCH_START_SECTION("file based: cat | tr")
     289             :     {
     290             :         // Equivalent to:
     291             :         //
     292             :         //    cat - < input.data | tr TASP tasp > output.data
     293             :         //
     294           1 :         std::string & tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     295           2 :         std::string const input_filename(tmpdir + "/input.data");
     296           2 :         std::string const output_filename(tmpdir + "/output.data");
     297             :         {
     298           2 :             std::ofstream input_data(input_filename);
     299           1 :             input_data << "Test A Simple Pipeline\n";
     300             :         }
     301             : 
     302           2 :         cppprocess::process::pointer_t tr(std::make_shared<cppprocess::process>("tr"));
     303           1 :         tr->set_command("tr");
     304           1 :         tr->add_argument("TASP");
     305           1 :         tr->add_argument("tasp");
     306           1 :         tr->set_output_filename(output_filename);
     307             : 
     308             :         // we could directly cat the file here, obviously but we want
     309             :         // to test the `< <filename>` functionality
     310             :         //
     311           2 :         cppprocess::process p("cat");
     312           1 :         p.set_command("cat");
     313           1 :         p.add_argument("-");
     314           1 :         p.set_input_filename(input_filename);
     315           1 :         p.add_next_process(tr);
     316             : 
     317           1 :         CATCH_REQUIRE(p.start() == 0);
     318             : 
     319           1 :         int const code(p.wait());
     320           1 :         CATCH_REQUIRE(code == 0);
     321             : 
     322           2 :         snap::file_contents output(output_filename);
     323           1 :         CATCH_REQUIRE(output.read_all());
     324           1 :         CATCH_REQUIRE(output.contents() == "test a simple pipeline\n");
     325             :     }
     326             :     CATCH_END_SECTION()
     327          12 : }
     328             : 
     329             : 
     330             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13