All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: Intel Graphics Development <intel-gfx@lists.freedesktop.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Subject: [PATCH 3/3] lib/igt_core: Document library design best practices
Date: Sun, 16 Mar 2014 20:10:00 +0100	[thread overview]
Message-ID: <1394997000-3022-3-git-send-email-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <1394997000-3022-1-git-send-email-daniel.vetter@ffwll.ch>

This is what I've been doing in the past few months when refactoring
i-g-t code. More ideas and also patterns to add highly welcome.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 lib/igt_core.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/lib/igt_core.c b/lib/igt_core.c
index d8a44193a7b7..b8329cbca7ff 100644
--- a/lib/igt_core.c
+++ b/lib/igt_core.c
@@ -115,6 +115,55 @@
  *    - "they are local to the function that made the corresponding setjmp() call;
  *    - "their values are changed between the calls to setjmp() and longjmp(); and
  *    - "they are not declared as volatile."
+ *
+ * # Best Practices for Test Helper Libraries Design
+ *
+ * Kernel tests itself tend to have fairly complex logic already. It is
+ * therefore paramount that helper code, both in libraries and test-private
+ * function, add as little boilerplate code to the main test logic as possible.
+ * But then dense code is hard to understand without constantly consulting
+ * documentation and implementation of all the helper functions if it doesn't
+ * follow some clear patterns. Hence follow these established best practices:
+ *
+ * - Make extensive use of the implicit control flow afforded by igt_skip(),
+ *   igt_fail and igt_success(). When dealing with optional kernel features
+ *   combine igt_skip() with igt_fail() to skip when the kernel support isn't
+ *   available but fail when anything else goes awry. void should be the most
+ *   common return type in all your functions.
+ *
+ * - Main test logic should have no explicit control flow for failure
+ *   conditions, but instead such assumptions should be written in a declarative
+ *   style.  Use one of the many macros which encapsulate i-g-t's implicit
+ *   control flow.  Pick the most suitable one to have as much debug output as
+ *   possible, without polluting the code unecessarily. For example
+ *   igt_assert_cmpint() for comparing integers or do_ioctl() for running ioctls
+ *   and checking their results.  Feel free to add new ones to the libary or
+ *   wrap up a set of checks into a private function to further condense your
+ *   test logic.
+ *
+ * - When adding a new feature test function which uses igt_skip() internally,
+ *   use the &lt;prefix&gt;_require_&lt;feature_name&gt; naming scheme. When you
+ *   instead add a feature test function which returns a boolean, because your
+ *   main test logic must take different actions depending upon the feature's
+ *   availability, then instead use the &lt;prefix&gt;_has_&lt;feature_name&gt;.
+ *
+ * - As already mentioned eschew explicit error handling logic as much as
+ *   possible. If your test absolutely has to handle the error of some function
+ *   the customary naming pattern is to prefix those variants with __. Try to
+ *   restrict explicit error handling to leaf functions. For the main test flow
+ *   simply pass the expected error condition down into your helper code, which
+ *   results in tidy and declarative test logic.
+ *
+ * - Make your library functions as simple to use as possible. Automatically
+ *   register cleanup handlers through igt_install_exit_handler(). Reduce the
+ *   amount of setup boilerplate needed by using implicit singletons and lazy
+ *   structure initialization and similar design patterns as much as possible.
+ *
+ * - Don't shy away from refactoring common code, even when there are just 2-3
+ *   users and even if it's not a net reduction in code. As long as it helps to
+ *   remove boilerplate and makes the code more declarative the resulting
+ *   clearer test flow is worth it. All i-g-t library code has been organically
+ *   extracted from testcases in this fashion.
  */
 
 static unsigned int exit_handler_count;
-- 
1.8.1.4

      parent reply	other threads:[~2014-03-16 19:31 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-16 19:09 [PATCH 1/3] lib/igt_debugfs: s/igt_pipe_crc_check/igt_require_pipe_crc/ Daniel Vetter
2014-03-16 19:09 ` [PATCH 2/3] lib/igt_core: Small api doc fix Daniel Vetter
2014-03-16 19:10 ` Daniel Vetter [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1394997000-3022-3-git-send-email-daniel.vetter@ffwll.ch \
    --to=daniel.vetter@ffwll.ch \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.