summaryrefslogtreecommitdiff
path: root/libinotifytools/src/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'libinotifytools/src/test.c')
-rw-r--r--libinotifytools/src/test.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/libinotifytools/src/test.c b/libinotifytools/src/test.c
new file mode 100644
index 0000000..7c5fc07
--- /dev/null
+++ b/libinotifytools/src/test.c
@@ -0,0 +1,325 @@
+// kate: replace-tabs off; space-indent off;
+
+#include "inotifytools/inotifytools.h"
+#include "inotifytools/inotify.h"
+
+#include "../../config.h"
+
+#define __USE_MISC
+#include <unistd.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+
+#define verify(A) if (!_verify((int)(A), #A, __FILE__, __LINE__, __PRETTY_FUNCTION__)) return;
+#define verify2(A,B) if (!_verify((int)(A), B, __FILE__, __LINE__, __PRETTY_FUNCTION__)) return;
+#define compare(A,B) if (!_compare((int)(A), (int)(B), #A, #B, __FILE__, __LINE__, __PRETTY_FUNCTION__))return;
+
+#define succeed() do {\
+ ++tests_succeeded;\
+ /*fprintf(stderr, "%s:%d Test '%s' passed", file, line, func);*/\
+ /*fprintf(stderr, "\n");*/\
+} while(0)
+
+#define fail(...) do {\
+ ++tests_failed;\
+ fprintf(stderr, "%s:%d Test '%s' failed: ", file, line, func);\
+ fprintf(stderr, __VA_ARGS__);\
+ fprintf(stderr, "\n");\
+ if (inotifytools_error() != 0) {\
+ fprintf(stderr, "inotifytools_error() returns %d (%s)\n",\
+ inotifytools_error(), strerror( inotifytools_error() ) );\
+ }\
+} while(0)
+
+#define TEST_DIR "/tmp/inotifytools_test"
+
+#define INFO(...) do { \
+ printf("%s: ", __PRETTY_FUNCTION__); \
+ printf(__VA_ARGS__); \
+} while(0)
+
+#define ENTER INFO("test begin\n");
+#define EXIT INFO("test end\n");
+
+
+static int tests_failed;
+static int tests_succeeded;
+
+int _verify( int cond, char const * teststr, char const * file, int line, char const *func ) {
+ if ( cond ) {
+ succeed();
+ return cond;
+ }
+
+ fail("Verification failed (%s)", teststr);
+ return cond;
+}
+
+int _compare( int value, int expval, char const* act_str, char const* exp_str, char const* file,
+ int line, char const *func ) {
+ if ( value == expval ) {
+ succeed();
+ return 1;
+ }
+
+ fail("Actual (%s): %d, Expected (%s): %d", act_str, value, exp_str, expval);
+ return 0;
+}
+
+void event_to_str() {
+ENTER
+ verify2(
+ !strcmp( inotifytools_event_to_str( IN_OPEN | IN_MODIFY | IN_ACCESS ),
+ "OPEN,MODIFY,ACCESS" ) ||
+ !strcmp( inotifytools_event_to_str( IN_OPEN | IN_MODIFY | IN_ACCESS ),
+ "OPEN,ACCESS,MODIFY" ) ||
+ !strcmp( inotifytools_event_to_str( IN_OPEN | IN_MODIFY | IN_ACCESS ),
+ "ACCESS,OPEN,MODIFY" ) ||
+ !strcmp( inotifytools_event_to_str( IN_OPEN | IN_MODIFY | IN_ACCESS ),
+ "MODIFY,OPEN,ACCESS" ) ||
+ !strcmp( inotifytools_event_to_str( IN_OPEN | IN_MODIFY | IN_ACCESS ),
+ "ACCESS,MODIFY,OPEN" ) ||
+ !strcmp( inotifytools_event_to_str( IN_OPEN | IN_MODIFY | IN_ACCESS ),
+ "MODIFY,ACCESS,OPEN" )
+ , inotifytools_event_to_str( IN_OPEN | IN_MODIFY | IN_ACCESS ));
+EXIT
+}
+
+void event_to_str_sep() {
+ENTER
+ verify2(
+ !strcmp( inotifytools_event_to_str_sep(IN_OPEN|IN_MODIFY|IN_ACCESS,':'),
+ "OPEN:MODIFY:ACCESS" ) ||
+ !strcmp( inotifytools_event_to_str_sep(IN_OPEN|IN_MODIFY|IN_ACCESS,':'),
+ "OPEN:ACCESS:MODIFY" ) ||
+ !strcmp( inotifytools_event_to_str_sep(IN_OPEN|IN_MODIFY|IN_ACCESS,':'),
+ "ACCESS:OPEN:MODIFY" ) ||
+ !strcmp( inotifytools_event_to_str_sep(IN_OPEN|IN_MODIFY|IN_ACCESS,':'),
+ "MODIFY:OPEN:ACCESS" ) ||
+ !strcmp( inotifytools_event_to_str_sep(IN_OPEN|IN_MODIFY|IN_ACCESS,':'),
+ "ACCESS:MODIFY:OPEN" ) ||
+ !strcmp( inotifytools_event_to_str_sep(IN_OPEN|IN_MODIFY|IN_ACCESS,':'),
+ "MODIFY:ACCESS:OPEN" )
+ ,inotifytools_event_to_str_sep(IN_OPEN|IN_MODIFY|IN_ACCESS,':'));
+EXIT
+}
+
+void str_to_event() {
+ENTER
+ compare( inotifytools_str_to_event("open,modify,access"),
+ IN_OPEN | IN_MODIFY | IN_ACCESS );
+ compare( inotifytools_str_to_event(",open,modify,access"), 0 );
+ compare( inotifytools_str_to_event("open,modify,access,"), 0 );
+ compare( inotifytools_str_to_event("open,modify,,access,close"), 0 );
+ compare( inotifytools_str_to_event("open,mod,access,close"), -1 );
+ compare( inotifytools_str_to_event("mod"), -1 );
+ compare( inotifytools_str_to_event(","), 0 );
+ compare( inotifytools_str_to_event(",,"), 0 );
+ compare( inotifytools_str_to_event("open"), IN_OPEN );
+ compare( inotifytools_str_to_event("close"), IN_CLOSE );
+ compare( inotifytools_str_to_event(",close"), 0 );
+ compare( inotifytools_str_to_event(",,close"), 0 );
+ compare( inotifytools_str_to_event("close,"), 0 );
+ compare( inotifytools_str_to_event("close,,"), 0 );
+EXIT
+}
+
+void str_to_event_sep() {
+ENTER
+ compare( inotifytools_str_to_event_sep("open:modify:access", ':'),
+ IN_OPEN | IN_MODIFY | IN_ACCESS );
+ compare( inotifytools_str_to_event_sep("open,modify,access", ','),
+ IN_OPEN | IN_MODIFY | IN_ACCESS );
+ compare( inotifytools_str_to_event_sep(":open:modify:access", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("open:modify:access:", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("open:modify::access:close", ':'),0);
+ compare( inotifytools_str_to_event_sep("open:mod:access:close", ':'), -1 );
+ compare( inotifytools_str_to_event_sep("mod", ':'), -1 );
+ compare( inotifytools_str_to_event_sep(":", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("::", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("open", ':'), IN_OPEN );
+ compare( inotifytools_str_to_event_sep("close", ':'), IN_CLOSE );
+ compare( inotifytools_str_to_event_sep(":close", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("::close", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("close:", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("close::", ':'), 0 );
+ compare( inotifytools_str_to_event_sep("open:modify:access", ','), -1 );
+ compare( inotifytools_str_to_event_sep("open:modify:access", 'o'), -1 );
+EXIT
+}
+
+void basic_watch_info() {
+ENTER
+ verify( inotifytools_initialize() );
+ verify( inotifytools_watch_file( "/", IN_CLOSE ) );
+ compare( inotifytools_wd_from_filename( "/" ), 1 );
+ compare( inotifytools_wd_from_filename( "foobar" ), -1 );
+ verify( !strcmp( inotifytools_filename_from_wd(1), "/" ) );
+ verify( inotifytools_remove_watch_by_filename( "/" ) );
+ compare( inotifytools_wd_from_filename( "/" ), -1 );
+ compare( inotifytools_filename_from_wd( 1 ), 0 );
+ verify( inotifytools_watch_file( "/", IN_CLOSE ) );
+ compare( inotifytools_wd_from_filename( "/" ), 2 );
+ compare( inotifytools_wd_from_filename( "foobar" ), -1 );
+ verify( !strcmp( inotifytools_filename_from_wd(2), "/" ) );
+ verify( inotifytools_remove_watch_by_wd( 2 ) );
+ compare( inotifytools_wd_from_filename( "/" ), -1 );
+ compare( inotifytools_filename_from_wd( 2 ), 0 );
+EXIT
+}
+
+void tst_inotifytools_snprintf() {
+ENTER
+ verify( (0 == mkdir(TEST_DIR, 0700)) || (EEXIST == errno) );
+ verify( inotifytools_initialize() );
+ verify( inotifytools_watch_file( TEST_DIR, IN_CLOSE ) );
+
+#define BUFSZ 2048
+#define RESET do { \
+ memset(buf, 0, BUFSZ); \
+ memset(test_event, 0, sizeof(struct inotify_event)); \
+ test_event->wd = inotifytools_wd_from_filename( TEST_DIR "/"); \
+ verify( test_event->wd >= 0 ); \
+ inotifytools_set_printf_timefmt(0); \
+} while(0)
+
+ char buf[BUFSZ];
+ char event_buf[4096];
+ struct inotify_event *test_event = (struct inotify_event*)event_buf;
+
+ RESET;
+ test_event->mask = IN_ACCESS;
+ inotifytools_snprintf(buf, 1024, test_event, "Event %e %.e on %w %f %T");
+ verify2( !strcmp(buf, "Event ACCESS ACCESS on " TEST_DIR "/ "), buf );
+
+ RESET;
+ test_event->mask = IN_ACCESS | IN_DELETE;
+ inotifytools_snprintf(buf, 1024, test_event, "Event %e %.e on %w %f %T");
+ verify2( !strcmp(buf, "Event ACCESS,DELETE ACCESS.DELETE on " TEST_DIR "/ ")
+ || !strcmp(buf, "Event DELETE,ACCESS DELETE.ACCESS on " TEST_DIR "/ "), buf );
+
+ RESET;
+ test_event->mask = IN_MODIFY;
+ inotifytools_snprintf(buf, 10, test_event, "Event %e %.e on %w %f %T");
+ verify2( !strcmp(buf, "Event MODI"), buf );
+
+ RESET;
+ test_event->mask = IN_ACCESS;
+ strcpy( test_event->name, "my_great_file" );
+ test_event->len = strlen( test_event->name )+1;
+ inotifytools_snprintf(buf, 1024, test_event, "Event %e %.e on %w %f %T");
+ verify2( !strcmp(buf, "Event ACCESS ACCESS on " TEST_DIR "/ my_great_file "), buf );
+
+ RESET;
+ test_event->mask = IN_ACCESS;
+ inotifytools_set_printf_timefmt("%D%% %H:%M");
+ {
+ char expected[1024];
+ char timestr[1024];
+ time_t now = time(0);
+ strftime(timestr, 1024, "%D%% %H:%M", localtime(&now));
+ snprintf(expected, 1024, "Event ACCESS ACCESS on %s/ %s", TEST_DIR, timestr);
+ inotifytools_snprintf(buf, 1024, test_event, "Event %e %.e on %w %f %T");
+ verify2( !strcmp(buf, expected), buf );
+ }
+
+#undef BUFSZ
+EXIT
+}
+
+void watch_limit() {
+ENTER
+ verify( (0 == mkdir(TEST_DIR, 0700)) || (EEXIST == errno) );
+
+ INFO("Warning, this test may take a while\n");
+#define INNER_LIMIT 16000
+#define OUTER_LIMIT 5
+
+ verify( inotifytools_initialize() );
+ inotifytools_initialize_stats();
+
+ for (int j = 0; j < OUTER_LIMIT; ++j) {
+ char fn[1024];
+ int max = 0;
+ for (int i = 0; i < INNER_LIMIT; ++i) {
+ snprintf(fn, 1023, "%s/%d", TEST_DIR, i);
+ int fd = creat(fn, 0700);
+ verify( -1 != fd );
+ verify( 0 == close(fd) );
+ int ret = inotifytools_watch_file(fn, IN_ALL_EVENTS);
+ verify( ret || inotifytools_error() == ENOSPC );
+ if (ret) {
+ max = i + 1;
+ int wd = inotifytools_wd_from_filename(fn);
+ verify(wd > 0);
+ verify( !strcmp(fn, inotifytools_filename_from_wd(wd) ) );
+ }
+ }
+
+ compare( inotifytools_get_num_watches(), max );
+
+ for (int i = 0; i < max; ++i) {
+ snprintf(fn, 1023, "%s/%d", TEST_DIR, i);
+ verify( inotifytools_remove_watch_by_filename(fn) );
+ }
+ }
+EXIT
+}
+
+void cleanup() {
+ compare( system("rm -rf " TEST_DIR), 0 );
+ inotifytools_cleanup();
+}
+
+int main() {
+ tests_failed = 0;
+ tests_succeeded = 0;
+
+#ifdef HAVE_MCHECK_H
+ char *mtrace_name = getenv("MALLOC_TRACE");
+ if (mtrace_name) {
+ printf("malloc trace might be written to %s\n", mtrace_name);
+ } else {
+ printf("If you want to do a malloc trace, set MALLOC_TRACE to "
+ "a path for logging.\n");
+ }
+ mtrace();
+#endif
+
+ cleanup();
+
+ event_to_str();
+ cleanup();
+ event_to_str_sep();
+ cleanup();
+
+ str_to_event();
+ cleanup();
+ str_to_event_sep();
+ cleanup();
+
+ basic_watch_info();
+ cleanup();
+
+ watch_limit();
+ cleanup();
+
+ tst_inotifytools_snprintf();
+ cleanup();
+
+ printf("Out of %d tests, %d succeeded and %d failed.\n",
+ tests_failed + tests_succeeded, tests_succeeded, tests_failed );
+
+ if ( tests_failed ) return -tests_failed;
+}