Commit e6ed0d2f03625f5d6b60db54fc894902d7ddbc32

Edward Thomson 2016-12-13T11:31:38

odb_loose: fsync tests Introduce a simple counter that `p_fsync` implements. This is useful for ensuring that `p_fsync` is called when we expect it to be, for example when we have enabled an odb backend to perform `fsync`s when writing objects.

diff --git a/src/posix.c b/src/posix.c
index e68f324..94deb6a 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include <ctype.h>
 
+size_t p_fsync__cnt = 0;
+
 #ifndef GIT_WIN32
 
 #ifdef NO_ADDRINFO
diff --git a/src/posix.h b/src/posix.h
index f204751..bd5a98e 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -111,6 +111,12 @@ extern int p_rename(const char *from, const char *to);
 extern int git__page_size(size_t *page_size);
 extern int git__mmap_alignment(size_t *page_size);
 
+/* The number of times `p_fsync` has been called.  Note that this is for
+ * test code only; it it not necessarily thread-safe and should not be
+ * relied upon in production.
+ */
+extern size_t p_fsync__cnt;
+
 /**
  * Platform-dependent methods
  */
diff --git a/src/unix/posix.h b/src/unix/posix.h
index b478640..52985fd 100644
--- a/src/unix/posix.h
+++ b/src/unix/posix.h
@@ -40,9 +40,14 @@ typedef int GIT_SOCKET;
 #define p_link(o,n) link(o, n)
 #define p_unlink(p) unlink(p)
 #define p_mkdir(p,m) mkdir(p, m)
-#define p_fsync(fd) fsync(fd)
 extern char *p_realpath(const char *, char *);
 
+GIT_INLINE(int) p_fsync(int fd)
+{
+	p_fsync__cnt++;
+	return fsync(fd);
+}
+
 #define p_recv(s,b,l,f) recv(s,b,l,f)
 #define p_send(s,b,l,f) send(s,b,l,f)
 #define p_inet_pton(a, b, c) inet_pton(a, b, c)
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index fea634b..5172627 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -113,6 +113,8 @@ int p_fsync(int fd)
 {
 	HANDLE fh = (HANDLE)_get_osfhandle(fd);
 
+	p_fsync__cnt++;
+
 	if (fh == INVALID_HANDLE_VALUE) {
 		errno = EBADF;
 		return -1;
diff --git a/tests/odb/loose.c b/tests/odb/loose.c
index c91927c..43dabcb 100644
--- a/tests/odb/loose.c
+++ b/tests/odb/loose.c
@@ -56,11 +56,13 @@ static void test_read_object(object_data *data)
 
 void test_odb_loose__initialize(void)
 {
+	p_fsync__cnt = 0;
 	cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE));
 }
 
 void test_odb_loose__cleanup(void)
 {
+	cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0));
 	cl_fixture_cleanup("test-objects");
 }
 
@@ -150,3 +152,35 @@ void test_odb_loose__permissions_readwrite(void)
 {
 	test_write_object_permission(0777, 0666, 0777, 0666);
 }
+
+static void write_object_to_loose_odb(int fsync)
+{
+	git_odb *odb;
+	git_odb_backend *backend;
+	git_oid oid;
+
+	cl_git_pass(git_odb_new(&odb));
+	cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, fsync, 0777, 0666));
+	cl_git_pass(git_odb_add_backend(odb, backend, 1));
+	cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJ_BLOB));
+	git_odb_free(odb);
+}
+
+void test_odb_loose__does_not_fsync_by_default(void)
+{
+	write_object_to_loose_odb(0);
+	cl_assert_equal_sz(0, p_fsync__cnt);
+}
+
+void test_odb_loose__fsync_obeys_odb_option(void)
+{
+	write_object_to_loose_odb(1);
+	cl_assert(p_fsync__cnt > 0);
+}
+
+void test_odb_loose__fsync_obeys_global_setting(void)
+{
+	cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1));
+	write_object_to_loose_odb(0);
+	cl_assert(p_fsync__cnt > 0);
+}