chiark / gitweb /
@@@ fltfmt mess
[mLib] / test / tvec-output.h
diff --git a/test/tvec-output.h b/test/tvec-output.h
new file mode 100644 (file)
index 0000000..38ba039
--- /dev/null
@@ -0,0 +1,194 @@
+/* -*-c-*-
+ *
+ * Test-vector framework output machinery
+ *
+ * (c) 2024 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * mLib is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with mLib.  If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef MLIB_TVEC_OUTPUT_H
+#define MLIB_TVEC_OUTPUT_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef MLIB_TVEC_H
+#  include "tvec.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+struct tvec_state;
+
+struct tvec_output {
+  /* An output formatter. */
+
+  const struct tvec_outops *ops;       /* pointer to operations */
+};
+
+enum {
+  /* Register output dispositions. */
+
+  TVRD_INPUT,                          /* input-only register */
+  TVRD_OUTPUT,                         /* output-only (input is dead) */
+  TVRD_MATCH,                          /* matching (equal) registers */
+  TVRD_FOUND,                          /* mismatching output register */
+  TVRD_EXPECT,                         /* mismatching input register */
+  TVRD_LIMIT                           /* (number of dispositions) */
+};
+
+struct tvec_fallbackoutput {
+  /* Dummy fallback output driver.  This may be useful for fallback output
+   * driver implementations.
+   */
+
+  struct tvec_output _o;
+  struct tvec_state *tv;
+};
+
+struct tvec_outops {
+  /* Output operations. */
+
+  void (*bsession)(struct tvec_output */*o*/, struct tvec_state */*tv*/);
+    /* Begin a test session.  The output driver will probably want to
+     * save @tv@, because this isn't provided to any other methods.
+     */
+
+  int (*esession)(struct tvec_output */*o*/);
+    /* End a session, and return the suggested exit code. */
+
+  void (*bgroup)(struct tvec_output */*o*/);
+    /* Begin a test group.  The test group description is @tv->test@. */
+
+  void (*skipgroup)(struct tvec_output */*o*/,
+                   const char */*excuse*/, va_list */*ap*/);
+    /* The group is being skipped; @excuse@ may be null or a format
+     * string explaining why.  The @egroup@ method will not be called
+     * separately.
+     */
+
+  void (*egroup)(struct tvec_output */*o*/);
+    /* End a test group.  At least one test was attempted or @skipgroup@
+     * would have been called instead.  If @tv->curr[TVOUT_LOSE]@ is nonzero
+     * then the test group as a whole failed; otherwise it passed.
+     */
+
+  void (*btest)(struct tvec_output */*o*/);
+    /* Begin a test case. */
+
+  void (*skip)(struct tvec_output */*o*/,
+              const char */*excuse*/, va_list */*ap*/);
+    /* The test case is being skipped; @excuse@ may be null or a format
+     * string explaining why.  The @etest@ function will still be called (so
+     * this works differently from @skipgroup@ and @egroup@).  A test case
+     * can be skipped at most once, and, if skipped, it cannot fail.
+     */
+
+  void (*fail)(struct tvec_output */*o*/,
+              const char */*detail*/, va_list */*ap*/);
+    /* The test case failed.
+     *
+     * The output driver should preferably report the filename (@infile@) and
+     * line number (@test_lno@, not @lno@) for the failing test.
+     *
+     * The @detail@ may be null or a format string describing detail about
+     * how the failing test was run which can't be determined from the
+     * registers; a @detail@ is usually provided when (and only when) the
+     * test environment potentially invokes the test function more than once.
+     *
+     * A single test case can fail multiple times!
+     */
+
+  void (*dumpreg)(struct tvec_output */*o*/,
+                 unsigned /*disp*/, const union tvec_regval */*rv*/,
+                 const struct tvec_regdef */*rd*/);
+    /* Dump a register.  The `disposition' @disp@ explains what condition the
+     * register is in; see @tvec_dumpreg@ and the @TVRD_...@ codes.  The
+     * register value is at @rv@, and its definition, including its type, at
+     * @rd@.  Note that this function may be called on virtual registers
+     * which aren't in either of the register vectors or mentioned by the
+     * test description.  It may also be called with @rv@ null, indicating
+     * that the register is not live.
+     */
+
+  void (*etest)(struct tvec_output */*o*/, unsigned /*outcome*/);
+    /* The test case concluded with the given @outcome@ (one of the
+     * @TVOUT_...@ codes.
+     */
+
+  void (*report)(struct tvec_output */*o*/, unsigned /*level*/,
+                const char */*msg*/, va_list */*ap*/);
+    /* Report a message.  The driver should ideally report the filename
+     * (@infile@) and line number (@lno@) prompting the error.
+     */
+
+  const void *(*extend)(struct tvec_output */*o*/, const char */*name*/);
+    /* Return a pointer to the output driver's implementation of the
+     * extension @name@, or null.  Typically, the implementation will be a
+     * structure of function pointers, though the details are necessarily
+     * extension-specific.
+     */
+
+  void (*destroy)(struct tvec_output */*o*/);
+    /* Release any resources acquired by the driver. */
+};
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @tvec_outputext@ --- *
+ *
+ * Arguments:  @struct tvec_state *tv@ = test-vector state
+ *             @struct tvec_output **o_out@ = output object
+ *             @struct tvec_fallbackoutput *fo@ = fallback output
+ *                     (uninitialized)
+ *             @const char *ext@ = extension name
+ *             @const void *fops@ = fallback operations
+ *
+ * Returns:    An output extension operations table.
+ *
+ * Use:                Calls the output driver's @extend@ function, passing @ext@ as
+ *             the extension name.  If the output driver recognizes the
+ *             extension, then @*o_out@ is set to the output driver object
+ *             and the driver's extension-operations table is returned.
+ *             Otherwise, a fallback output object is constructed in @*fo@,
+ *             @*o_out@ is set to @&fo->_o@, and @fops@ is returned.  In
+ *             this way, a call to an extension function, passing @*o_out@
+ *             as the output object, will either call the output driver's
+ *             extension implementation or the fallback implementation as
+ *             required.
+ */
+
+extern const void *tvec_outputext(struct tvec_state */*tv*/,
+                                 struct tvec_output **/*o_out*/,
+                                 struct tvec_fallbackoutput */*fo*/,
+                                 const char */*ext*/, const void */*fops*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif