WL#5052: Extending mytap with vararg versions of basic functions

Affects: Server-5.4   —   Status: Code-Review   —   Priority: Medium

RATIONALE
=========

To be able to write vararg functions that can further call mytap functions using
these vararg arguments, it is necessary to introduce vararg versions of the
basic functions.


DESCRIPTION
===========

In order to be able to write vararg functions that can perform more complicated
tasks and report status, it is necessary to be able pass vararg parameters
further down.

For example, consider this function to test a range of values for a function::

  void test_gcs(int a, int b, const char *fmt, ) {
    unsigned int d = gcs(a, b);
    va_list ap;
    va_start(ap, fmt);
    va_ok(a % d != 0 || b % d != 0, fmt, ap);
    va_end(ap);
  }

Another case is when one wants to test several different aspects while still
providing a informative header for a sequence of tests (example uses my_vle in
the mysys library)::

  void test_vle_encode(unsigned long value, uint8_t buf[sizeof(value)+1],
                       const char *fmt, ...)
  {
    uchar *endp;
    int l;
    int error= 0;

    va_list ap;
    va_start(ap, fmt);
    va_diag(fmt, ap);

    endp= my_vle_encode(buf, ULONG_MAX, value);
    for (l = 0 ; l < endp - buf ; ++l)
    {
      uint8_t v = (value >> (7 * l)) & 0x7f;
      if (l > 0)
        v |= 0x80;
      if (*(endp - l - 1) != v)
      {
        diag("expected: %u, was: %u", v, buf[l]);
        ++error;
      }
    }
    va_ok(error == 0, fmt, ap);
    va_end(ap);
  }


  void test_vle_decode(unsigned long expect, uint8_t buf[sizeof(expect)+1],
                       const char *fmt, ...)
  {
    uchar const *endp;
    unsigned long result;
    va_list ap;
    va_start(ap, fmt);
    va_diag(fmt, ap);
    va_end(ap);

    endp= my_vle_decode(&result, buf);
    ok(endp - buf != 0, "Checking length is no zero (is: %d)", endp - buf);
    ok(result == expect, "expect: %lu, is: %lu", expect, result);
  }


  void test_vle(unsigned long value, const char *fmt, ...)
  {
    va_list ap;
    va_start(ap, fmt);
    va_diag(fmt, ap);
    va_end(ap);

    uint8_t buf[sizeof(value)+1];
    unsigned long result;

    test_vle_encode(value, buf, "Encoding %d", value);
    test_vle_decode(value, buf, "Decoding %d", value);
  }

New functions
-------------

Introduce the new functions ``va_diag``, ``va_ok``, and ``va_skip``.

void va_diag(char const *fmt, va_list ap);

Print a diagnostics message in TAP format.

void va_skip(int how_many, char const *fmt, va_list ap);

Print a message information that 'how_many' tests are skipped and the reason for
skipping them.

void va_ok(int pass, char const *fmt, va_list ap);

Print a message informing whether a test passed or failed. If 'pass' is true,
the test passed, otherwise, it failed.


Testing
-------

In order to test the functions, some basic tests are added as well as a test of
the ``my_vle`` file for serializing and de-serializing variable length integers.