--- /dev/null
+RFC - Testpoint mechanism\r
+\r
+Author: Christian Babeux <christian.babeux@efficios.com>\r
+\r
+Contributors:\r
+ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>\r
+\r
+Version:\r
+ - v0.1: 11/09/2012\r
+ * Initial proposal\r
+\r
+Motivation\r
+----------\r
+\r
+The main goal behind the testpoint mechanism is to be able to test and\r
+validate failure cases in different portion of the LTTng codebase. It\r
+could also be used by developers as a debugging aid.\r
+\r
+By injecting code at runtime in the lttng daemons/processes/executables,\r
+we can painlessly trigger faulty behavior, test errors paths or even\r
+reproduce race conditions by introducing or exacerbating delays between\r
+threads.\r
+\r
+Requirements\r
+------------\r
+\r
+The testpoint mechanism should be able to be triggered via scripts to\r
+automate testing efforts.\r
+\r
+Ideally, the testpoint mechanism should *NOT* incur a significant\r
+performance hit if we want to leave it always on, in a similar fashion\r
+to the assert() macros.\r
+\r
+By leaving it always on, any user is able to use our tests and validate\r
+the behavior of his installation via a simple 'make check' execution.\r
+\r
+Proposed solution\r
+-----------------\r
+\r
+This patch introduce two new macros: TESTPOINT_DECL(name)\r
+and testpoint(name).\r
+\r
+Here a quick example that shows how to use the testpoint mechanism:\r
+\r
+file: main.c\r
+#include <stdio.h>\r
+#include <common/testpoint/testpoint/testpoint.h>\r
+\r
+/* Testpoint declaration */\r
+TESTPOINT_DECL(interesting_function)\r
+\r
+void interesting_function(void)\r
+{\r
+ testpoint(interesting_function);\r
+ /* Some processing that can fail */\r
+ ...\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+ interesting_function();\r
+ ...\r
+ printf("End");\r
+}\r
+\r
+file: testpoint.c\r
+#include <stdio.h>\r
+void __testpoint_interesting_function(void)\r
+{\r
+ printf("In testpoint of interesting function!");\r
+}\r
+\r
+Compile:\r
+gcc -o test main.c\r
+gcc -fPIC -shared -o testpoint.so testpoint.c\r
+\r
+Run:\r
+> ./test\r
+ End\r
+> export LTTNG_TESTPOINT_ENABLE=1\r
+> LD_PRELOAD=testpoint.so ./test\r
+ In testpoint of interesting function!\r
+ End\r
+> export LTTNG_TESTPOINT_ENABLE=0\r
+> LD_PRELOAD=testpoint.so ./test\r
+ End\r
+\r
+The testpoint mechanism is triggered via the preloading of a shared\r
+object containing the appropriate testpoint symbols and by setting the\r
+LTTNG_TESTPOINT_ENABLE environment variable.\r
+\r
+The check on this environment variable is done on the application\r
+startup with the help of a constructor (lttng_testpoint_check) which\r
+toggle a global state variable indicating whether or not the testpoints\r
+should be activated.\r
+\r
+When enabled, the testpoint() macro calls an underlying wrapper specific\r
+to the testpoint and simply try to lookup the testpoint symbol via a\r
+dlsym() call.\r
+\r
+When disabled, the testpoint() call will only incur an additionnal test\r
+per testpoint on a global variable. This performance 'hit' should be\r
+acceptable for production use.\r
+\r
+As stated previously, the testpoint mechanism should be *always on*. It\r
+can be explicitly disabled via CFLAGS="-DNTESTPOINT" in a way similar to\r
+NDEBUG and assert().\r