From cc6280af7eca660c916dc652066216acd474979d Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 23 Jan 2019 21:47:38 +0300 Subject: Add testscript sleep builtin --- build2/test/script/builtin.cxx | 84 +++++++++++++++++++++++++++++++++++++++++- build2/test/script/runner.cxx | 4 +- 2 files changed, 84 insertions(+), 4 deletions(-) (limited to 'build2/test') diff --git a/build2/test/script/builtin.cxx b/build2/test/script/builtin.cxx index cf8f20d..657d8d4 100644 --- a/build2/test/script/builtin.cxx +++ b/build2/test/script/builtin.cxx @@ -4,15 +4,19 @@ #include +#include #include #include #include +#include // strtoull() #include #include // use default operator<< implementation #include // fdopen_mode, fdstream_mode #include +#include // sched + #include // Strictly speaking a builtin which reads/writes from/to standard streams @@ -1498,7 +1502,7 @@ namespace build2 } if (i != e) - error () << "unexpected argument"; + error () << "unexpected argument '" << *i << "'"; // If we edit file in place make sure that the file path is specified // and obtain a temporary file path. We will be writing to the @@ -1634,6 +1638,81 @@ namespace build2 return 1; } + // sleep + // + // Note: can be executed synchronously. + // + static uint8_t + sleep (scope&, + const strings& args, + auto_fd in, auto_fd out, auto_fd err) noexcept + try + { + uint8_t r (1); + ofdstream cerr (move (err)); + + auto error = [&cerr] (bool fail = true) + { + return error_record (cerr, fail, "sleep"); + }; + + try + { + in.close (); + out.close (); + + if (args.empty ()) + error () << "missing time interval"; + + if (args.size () > 1) + error () << "unexpected argument '" << args[1] << "'"; + + uint64_t n; + + for (;;) // Breakout loop. + { + const string& a (args[0]); + + // Note: strtoull() allows these. + // + if (!a.empty () && a[0] != '-' && a[0] != '+') + { + char* e (nullptr); + n = strtoull (a.c_str (), &e, 10); // Can't throw. + + if (errno != ERANGE && e == a.c_str () + a.size ()) + break; + } + + error () << "invalid time interval '" << a << "'"; + } + + // If/when required we could probably support the precise sleep mode + // (e.g., via an option). + // + sched.sleep (chrono::seconds (n)); + + r = 0; + } + // Can be thrown while closing in, out or writing to cerr. + // + catch (const io_error& e) + { + error (false) << e; + } + catch (const failed&) + { + // Diagnostics has already been issued. + } + + cerr.close (); + return r; + } + catch (const std::exception&) + { + return 1; + } + // test -f|-d // // Note: can be executed synchronously. @@ -1666,7 +1745,7 @@ namespace build2 error () << "invalid option"; if (args.size () > 2) - error () << "unexpected argument"; + error () << "unexpected argument '" << args[2] << "'"; path p (parse_path (args[1], sp.wd_path)); @@ -1890,6 +1969,7 @@ namespace build2 {"rm", &sync_impl<&rm>}, {"rmdir", &sync_impl<&rmdir>}, {"sed", &async_impl<&sed>}, + {"sleep", &sync_impl<&sleep>}, {"test", &sync_impl<&test>}, {"touch", &sync_impl<&touch>}, {"true", &true_} diff --git a/build2/test/script/runner.cxx b/build2/test/script/runner.cxx index 2f4b0a2..c881031 100644 --- a/build2/test/script/runner.cxx +++ b/build2/test/script/runner.cxx @@ -978,7 +978,7 @@ namespace build2 const string& s (*i++); if (i != e) - fail (ll) << "unexpected argument"; + fail (ll) << "unexpected argument '" << *i << "'"; error (ll) << s; throw exit_scope (false); @@ -1040,7 +1040,7 @@ namespace build2 const string& vname (i == e ? a : *i++); if (i != e) - fail (ll) << "unexpected argument"; + fail (ll) << "unexpected argument '" << *i << "'"; if (ats != nullptr && ats->empty ()) fail (ll) << "empty variable attributes"; -- cgit v1.1