diff options
author | David Kalnischkies <david@kalnischkies.de> | 2016-11-24 12:14:39 +0100 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2016-11-25 00:15:13 +0100 |
commit | e1ae0531bfad0fce8590c26d1e38825df22d812a (patch) | |
tree | 54b648fe14a8d64778f2fc01050543a31f6c45f8 /test/interactive-helper/teestream.h | |
parent | 0123ce7171b09ead5a07567fbd33c53f609f6560 (diff) |
optional write aptwebserver log to client specific files
The test test-handle-redirect-as-used-mirror-change serves multiple
clients at the same time, so the order of the output is undefined and
once in a while the two clients will intermix their lines causing the
grep we perform on it later to fail making our tests fail.
Solved by introducing client-specific logfiles which we all grep and
sort the result to have the results more stable.
Git-Dch: Ignore
Diffstat (limited to 'test/interactive-helper/teestream.h')
-rw-r--r-- | test/interactive-helper/teestream.h | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/test/interactive-helper/teestream.h b/test/interactive-helper/teestream.h new file mode 100644 index 000000000..728a1bae2 --- /dev/null +++ b/test/interactive-helper/teestream.h @@ -0,0 +1,62 @@ +#ifndef APT_HELPER_TEESTREAM_H +#define APT_HELPER_TEESTREAM_H + +/* 'basic' implementation of a streambuf which passes the output + to two 'real' streambufs emulating '| tee' on the shell + + The main use is streaming debug output to std::clog as well as + a logfile easily, so don't expect that to be a bulletproof + implementation. */ + +#include <iostream> +#include <apt-pkg/macros.h> + +template <typename CharT, typename Traits = std::char_traits<CharT> +> class basic_teebuf: public std::basic_streambuf<CharT, Traits> +{ +public: + basic_teebuf(std::basic_streambuf<CharT, Traits> * const sb1, + std::basic_streambuf<CharT, Traits> * const sb2) + : s1(sb1), s2(sb2) {} +protected: + virtual std::streamsize xsputn(const CharT* s, std::streamsize c) APT_OVERRIDE + { + return s2->sputn(s, s1->sputn(s, c)); + } + // overflow is the fallback of sputc which is non-virtual + typedef typename Traits::int_type int_type; + virtual int_type overflow(int_type ch = Traits::eof()) APT_OVERRIDE + { + auto const eof = Traits::eof(); + if (Traits::eq_int_type(ch, Traits::eof()) == true) + return eof; + + auto const r1 = s1->sputc(Traits::to_char_type(ch)); + auto const r2 = s2->sputc(Traits::to_char_type(ch)); + return Traits::eq_int_type(r1, eof) ? r1: r2; + } + virtual void imbue(const std::locale& loc) APT_OVERRIDE + { + s1->pubimbue(loc); + s2->pubimbue(loc); + } + virtual int sync() APT_OVERRIDE + { + auto const r1 = s1->pubsync(); + auto const r2 = s2->pubsync(); + return r1 == 0 ? r2 : r1; + } +private: + std::basic_streambuf<CharT, Traits> * const s1; + std::basic_streambuf<CharT, Traits> * const s2; +}; +template <typename CharT, typename Traits = std::char_traits<CharT> +> class basic_teeostream: public std::basic_ostream<CharT, Traits> +{ +public: + basic_teeostream(std::basic_ostream<CharT, Traits> &o1, std::basic_ostream<CharT, Traits> &o2) : + std::basic_ostream<CharT, Traits>(&tbuf), tbuf(o1.rdbuf(), o2.rdbuf()) {} +private: + basic_teebuf<CharT, Traits> tbuf; +}; +#endif |