doc: test-writing-guidelines: Add correct cleanup
Add discussion on how to write correct cleanup() function.
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index 38db28c..ff12b8e 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -277,6 +277,81 @@
NOTE: The 'test()' function must work correctly even if executed several times
from test main loop.
+A word about the cleanup() callback
++++++++++++++++++++++++++++++++++++
+
+There are a few rules that needs to be followed in order to write correct
+cleanup() callback.
+
+1. Don't call callback() from within the callback().
+(This includes passing callback pointer to library 'tst_' functions.)
+
+2. Make sure to uninitialize resources in the inverser order they were
+ initialized. (Some of the steps may not depend on others and everything
+ will work if there were swapped but let's keep it in order.)
+
+3. Uninitialize only resources that were initialized.
+
+The third rule needs a bit more detailed discussion. Consider, for example,
+test setup below which is example of a setup that prepares temporary
+directory, two file descriptors and allocates a buffer.
+
+[source,c]
+-------------------------------------------------------------------------------
+static int fd0, fd1;
+static void *buf;
+#define BUFSIZE (1024 * 1024)
+
+static void setup(void)
+{
+ tst_require_root();
+ tst_tmpdir();
+
+ fd0 = SAFE_OPEN(cleanup, "test_file1", O_CREAT | O_RDWR, 0666);
+ SAFE_UNLINK(cleanup, "test_file1");
+ fd1 = SAFE_OPEN(cleanup, "test_file2", O_CREAT | O_RDWR, 0666);
+ SAFE_UNLINK(cleanup, "test_file2");
+
+ buf = SAFE_MALLOC(cleanup, BUFSIZE);
+}
+-------------------------------------------------------------------------------
+
+In this case the 'cleanup()' function may be entered in five different states:
+
+* The first 'SAFE_OPEN()' has failed, tempororary directory is created
+ no files are open and +fd0 == -1+, +fd1 == 0+ and +buf == NULL+.
+
+* The first 'SAFE_UNLINK()' has failed, +fd0+ holds file descriptor and
+ +fd1 == 0+.
+
+* The second SAFE_OPEN() has failed, +fd0+ holds file descriptor and
+ +fd1 == -1+.
+
+* The second 'SAFE_UNLINK()' or 'SAFE_MALLOC()' has failed and both 'fd0' and
+ 'fd1' holds file descriptors, +buf+ is still +NULL+.
+
+* The 'cleanup()' was called at the end of the test, all +fd0+, +fd1+ and
+ +buf+ are initialized.
+
+The 'cleanup()' functions should be able to cope with all scenarios. In this
+case following code will do:
+
+[source,c]
+-------------------------------------------------------------------------------
+static void cleanup(void)
+{
+ if (buf)
+ free(buf);
+
+ if (fd1 > 0)
+ close(fd1);
+
+ if (fd0 > 0)
+ close(fd0);
+
+ tst_rmdir();
+}
+-------------------------------------------------------------------------------
2.2.2 Basic test interface
^^^^^^^^^^^^^^^^^^^^^^^^^^