// file : tests/progress/driver.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2019 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef _WIN32 # include <unistd.h> // write() #else # include <libbutl/win32-utility.hxx> # include <io.h> //_write() #endif #include <cassert> #ifndef __cpp_lib_modules_ts #include <string> #include <cstddef> // size_t #include <iostream> #ifndef _WIN32 # include <thread> // this_thread::sleep_for() #endif #endif // Other includes. #ifdef __cpp_modules_ts #ifdef __cpp_lib_modules_ts import std.core; import std.io; #ifndef _WIN32 import std.threading; #endif #endif import butl.process; import butl.fdstream; import butl.diagnostics; import butl.optional; // @@ MOD Clang should not be necessary. import butl.small_vector; // @@ MOD Clang should not be necessary. #else #include <libbutl/process.mxx> #include <libbutl/fdstream.mxx> // fdnull(), stderr_fd() #include <libbutl/diagnostics.mxx> #endif using namespace std; using namespace butl; // Usage: // // argv[0] [-n] [-c] // // -n // Do not run child process. By default the program runs itself with -c // option (see below). // // -c // Run as a child process that just prints lines with a small but varying // delay. // int main (int argc, const char* argv[]) { bool child (false); bool no_child (false); assert (argc > 0); for (int i (1); i != argc; ++i) { string v (argv[i]); if (v == "-c") child = true; else if (v == "-n") no_child = true; else assert (false); } auto sleep = [] (size_t ms = 100) { // MINGW GCC 4.9 doesn't implement this_thread so use Win32 Sleep(). // #ifndef _WIN32 this_thread::sleep_for (chrono::milliseconds (ms)); #else Sleep (static_cast<DWORD> (ms)); #endif }; if (child) { auto print = [] (const string& s) { #ifndef _WIN32 ssize_t r (write (stderr_fd(), s.c_str (), s.size ())); #else int r (_write (stderr_fd(), s.c_str (), static_cast<unsigned int> (s.size ()))); #endif assert (r != -1); }; for (size_t i (50); i != 0; --i) { print ("Child line " + to_string (i) + '\n'); sleep (200 - i); } return 0; } process pr (!no_child ? process_start (fdnull (), fdnull (), 2, argv[0], "-c") : process (process_exit (0))); // Exited normally. for (size_t i (100); i != 0; --i) { if (i % 10 == 0) diag_stream_lock () << "Line " << i / 10 << endl; { diag_progress_lock l; diag_progress = " " + to_string (i) + "%"; } sleep (); } sleep (1000); // Test that the progress line is restored by the diag_stream_lock. // diag_stream_lock () << "Printed to diag_stream" << endl; sleep (1000); // Test that the progress line is restored after printing to cerr. // { cerr << "Printed to std::cerr" << endl; diag_progress_lock (); } sleep (1000); assert (pr.wait ()); }