You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2011/07/27 03:08:58 UTC

[lucy-commits] svn commit: r1151301 - in /incubator/lucy/trunk/charmonizer: Makefile Makefile.MSVC Makefile.MinGW src/Charmonizer/Core/Stat.c src/Charmonizer/Core/Stat.h src/Charmonizer/Probe.c src/Charmonizer/Probe/LargeFiles.c src/Charmonizer/Test/TestLargeFiles.c

Author: marvin
Date: Wed Jul 27 01:08:56 2011
New Revision: 1151301

URL: http://svn.apache.org/viewvc?rev=1151301&view=rev
Log:
Refactor large-files testing code.

Move code which is only needed for testing of Charmonizer's large files
probing results out of the Probe and into the Test.  Use probing to determine
whether the compiler/OS has the features needed to run the test (looking for
sys/stat.h and certain struct stat members).  Zap the Rube-Goldberg-esque
Charmonizer/Core/Stat module, which is no longer necessary once we can use
sys/stat.h.

Removed:
    incubator/lucy/trunk/charmonizer/src/Charmonizer/Core/Stat.c
    incubator/lucy/trunk/charmonizer/src/Charmonizer/Core/Stat.h
Modified:
    incubator/lucy/trunk/charmonizer/Makefile
    incubator/lucy/trunk/charmonizer/Makefile.MSVC
    incubator/lucy/trunk/charmonizer/Makefile.MinGW
    incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe.c
    incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe/LargeFiles.c
    incubator/lucy/trunk/charmonizer/src/Charmonizer/Test/TestLargeFiles.c

Modified: incubator/lucy/trunk/charmonizer/Makefile
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/charmonizer/Makefile?rev=1151301&r1=1151300&r2=1151301&view=diff
==============================================================================
--- incubator/lucy/trunk/charmonizer/Makefile (original)
+++ incubator/lucy/trunk/charmonizer/Makefile Wed Jul 27 01:08:56 2011
@@ -22,11 +22,11 @@ PROGNAME= charmonize
 
 TESTS= TestDirManip TestFuncMacro TestHeaders TestIntegers TestLargeFiles TestUnusedVars TestVariadicMacros
 
-OBJS= charmonize.o src/Charmonizer/Core/Compiler.o src/Charmonizer/Core/ConfWriter.o src/Charmonizer/Core/HeaderChecker.o src/Charmonizer/Core/OperatingSystem.o src/Charmonizer/Core/Stat.o src/Charmonizer/Core/Util.o src/Charmonizer/Probe.o src/Charmonizer/Probe/AtomicOps.o src/Charmonizer/Probe/DirManip.o src/Charmonizer/Probe/Floats.o src/Charmonizer/Probe/FuncMacro.o src/Charmonizer/Probe/Headers.o src/Charmonizer/Probe/Integers.o src/Charmonizer/Probe/LargeFiles.o src/Charmonizer/Probe/Memory.o src/Charmonizer/Probe/UnusedVars.o src/Charmonizer/Probe/VariadicMacros.o
+OBJS= charmonize.o src/Charmonizer/Core/Compiler.o src/Charmonizer/Core/ConfWriter.o src/Charmonizer/Core/HeaderChecker.o src/Charmonizer/Core/OperatingSystem.o src/Charmonizer/Core/Util.o src/Charmonizer/Probe.o src/Charmonizer/Probe/AtomicOps.o src/Charmonizer/Probe/DirManip.o src/Charmonizer/Probe/Floats.o src/Charmonizer/Probe/FuncMacro.o src/Charmonizer/Probe/Headers.o src/Charmonizer/Probe/Integers.o src/Charmonizer/Probe/LargeFiles.o src/Charmonizer/Probe/Memory.o src/Charmonizer/Probe/UnusedVars.o src/Charmonizer/Probe/VariadicMacros.o
 
 TEST_OBJS= src/Charmonizer/Test.o src/Charmonizer/Test/TestDirManip.o src/Charmonizer/Test/TestFuncMacro.o src/Charmonizer/Test/TestHeaders.o src/Charmonizer/Test/TestIntegers.o src/Charmonizer/Test/TestLargeFiles.o src/Charmonizer/Test/TestUnusedVars.o src/Charmonizer/Test/TestVariadicMacros.o
 
-HEADERS= src/Charmonizer/Core/Compiler.h src/Charmonizer/Core/ConfWriter.h src/Charmonizer/Core/Defines.h src/Charmonizer/Core/HeaderChecker.h src/Charmonizer/Core/OperatingSystem.h src/Charmonizer/Core/Stat.h src/Charmonizer/Core/Util.h src/Charmonizer/Probe.h src/Charmonizer/Probe/AtomicOps.h src/Charmonizer/Probe/DirManip.h src/Charmonizer/Probe/Floats.h src/Charmonizer/Probe/FuncMacro.h src/Charmonizer/Probe/Headers.h src/Charmonizer/Probe/Integers.h src/Charmonizer/Probe/LargeFiles.h src/Charmonizer/Probe/Memory.h src/Charmonizer/Probe/UnusedVars.h src/Charmonizer/Probe/VariadicMacros.h src/Charmonizer/Test.h
+HEADERS= src/Charmonizer/Core/Compiler.h src/Charmonizer/Core/ConfWriter.h src/Charmonizer/Core/Defines.h src/Charmonizer/Core/HeaderChecker.h src/Charmonizer/Core/OperatingSystem.h src/Charmonizer/Core/Util.h src/Charmonizer/Probe.h src/Charmonizer/Probe/AtomicOps.h src/Charmonizer/Probe/DirManip.h src/Charmonizer/Probe/Floats.h src/Charmonizer/Probe/FuncMacro.h src/Charmonizer/Probe/Headers.h src/Charmonizer/Probe/Integers.h src/Charmonizer/Probe/LargeFiles.h src/Charmonizer/Probe/Memory.h src/Charmonizer/Probe/UnusedVars.h src/Charmonizer/Probe/VariadicMacros.h src/Charmonizer/Test.h
 
 CLEANABLE= $(OBJS) $(PROGNAME) $(TEST_OBJS) $(TESTS) 
 

Modified: incubator/lucy/trunk/charmonizer/Makefile.MSVC
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/charmonizer/Makefile.MSVC?rev=1151301&r1=1151300&r2=1151301&view=diff
==============================================================================
--- incubator/lucy/trunk/charmonizer/Makefile.MSVC (original)
+++ incubator/lucy/trunk/charmonizer/Makefile.MSVC Wed Jul 27 01:08:56 2011
@@ -22,11 +22,11 @@ PROGNAME= charmonize.exe
 
 TESTS= TestDirManip.exe TestFuncMacro.exe TestHeaders.exe TestIntegers.exe TestLargeFiles.exe TestUnusedVars.exe TestVariadicMacros.exe
 
-OBJS= charmonize.obj src\Charmonizer\Core\Compiler.obj src\Charmonizer\Core\ConfWriter.obj src\Charmonizer\Core\HeaderChecker.obj src\Charmonizer\Core\OperatingSystem.obj src\Charmonizer\Core\Stat.obj src\Charmonizer\Core\Util.obj src\Charmonizer\Probe.obj src\Charmonizer\Probe\AtomicOps.obj src\Charmonizer\Probe\DirManip.obj src\Charmonizer\Probe\Floats.obj src\Charmonizer\Probe\FuncMacro.obj src\Charmonizer\Probe\Headers.obj src\Charmonizer\Probe\Integers.obj src\Charmonizer\Probe\LargeFiles.obj src\Charmonizer\Probe\Memory.obj src\Charmonizer\Probe\UnusedVars.obj src\Charmonizer\Probe\VariadicMacros.obj
+OBJS= charmonize.obj src\Charmonizer\Core\Compiler.obj src\Charmonizer\Core\ConfWriter.obj src\Charmonizer\Core\HeaderChecker.obj src\Charmonizer\Core\OperatingSystem.obj src\Charmonizer\Core\Util.obj src\Charmonizer\Probe.obj src\Charmonizer\Probe\AtomicOps.obj src\Charmonizer\Probe\DirManip.obj src\Charmonizer\Probe\Floats.obj src\Charmonizer\Probe\FuncMacro.obj src\Charmonizer\Probe\Headers.obj src\Charmonizer\Probe\Integers.obj src\Charmonizer\Probe\LargeFiles.obj src\Charmonizer\Probe\Memory.obj src\Charmonizer\Probe\UnusedVars.obj src\Charmonizer\Probe\VariadicMacros.obj
 
 TEST_OBJS= src\Charmonizer\Test.obj src\Charmonizer\Test\TestDirManip.obj src\Charmonizer\Test\TestFuncMacro.obj src\Charmonizer\Test\TestHeaders.obj src\Charmonizer\Test\TestIntegers.obj src\Charmonizer\Test\TestLargeFiles.obj src\Charmonizer\Test\TestUnusedVars.obj src\Charmonizer\Test\TestVariadicMacros.obj
 
-HEADERS= src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Stat.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
+HEADERS= src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
 
 CLEANABLE= $(OBJS) $(PROGNAME) $(TEST_OBJS) $(TESTS) *.pdb
 

Modified: incubator/lucy/trunk/charmonizer/Makefile.MinGW
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/charmonizer/Makefile.MinGW?rev=1151301&r1=1151300&r2=1151301&view=diff
==============================================================================
--- incubator/lucy/trunk/charmonizer/Makefile.MinGW (original)
+++ incubator/lucy/trunk/charmonizer/Makefile.MinGW Wed Jul 27 01:08:56 2011
@@ -22,11 +22,11 @@ PROGNAME= charmonize.exe
 
 TESTS= TestDirManip.exe TestFuncMacro.exe TestHeaders.exe TestIntegers.exe TestLargeFiles.exe TestUnusedVars.exe TestVariadicMacros.exe
 
-OBJS= charmonize.o src\Charmonizer\Core\Compiler.o src\Charmonizer\Core\ConfWriter.o src\Charmonizer\Core\HeaderChecker.o src\Charmonizer\Core\OperatingSystem.o src\Charmonizer\Core\Stat.o src\Charmonizer\Core\Util.o src\Charmonizer\Probe.o src\Charmonizer\Probe\AtomicOps.o src\Charmonizer\Probe\DirManip.o src\Charmonizer\Probe\Floats.o src\Charmonizer\Probe\FuncMacro.o src\Charmonizer\Probe\Headers.o src\Charmonizer\Probe\Integers.o src\Charmonizer\Probe\LargeFiles.o src\Charmonizer\Probe\Memory.o src\Charmonizer\Probe\UnusedVars.o src\Charmonizer\Probe\VariadicMacros.o
+OBJS= charmonize.o src\Charmonizer\Core\Compiler.o src\Charmonizer\Core\ConfWriter.o src\Charmonizer\Core\HeaderChecker.o src\Charmonizer\Core\OperatingSystem.o src\Charmonizer\Core\Util.o src\Charmonizer\Probe.o src\Charmonizer\Probe\AtomicOps.o src\Charmonizer\Probe\DirManip.o src\Charmonizer\Probe\Floats.o src\Charmonizer\Probe\FuncMacro.o src\Charmonizer\Probe\Headers.o src\Charmonizer\Probe\Integers.o src\Charmonizer\Probe\LargeFiles.o src\Charmonizer\Probe\Memory.o src\Charmonizer\Probe\UnusedVars.o src\Charmonizer\Probe\VariadicMacros.o
 
 TEST_OBJS= src\Charmonizer\Test.o src\Charmonizer\Test\TestDirManip.o src\Charmonizer\Test\TestFuncMacro.o src\Charmonizer\Test\TestHeaders.o src\Charmonizer\Test\TestIntegers.o src\Charmonizer\Test\TestLargeFiles.o src\Charmonizer\Test\TestUnusedVars.o src\Charmonizer\Test\TestVariadicMacros.o
 
-HEADERS= src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Stat.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
+HEADERS= src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
 
 CLEANABLE= $(OBJS) $(PROGNAME) $(TEST_OBJS) $(TESTS) 
 

Modified: incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe.c?rev=1151301&r1=1151300&r2=1151301&view=diff
==============================================================================
--- incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe.c (original)
+++ incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe.c Wed Jul 27 01:08:56 2011
@@ -25,7 +25,6 @@
 #include "Charmonizer/Core/Util.h"
 #include "Charmonizer/Core/Compiler.h"
 #include "Charmonizer/Core/OperatingSystem.h"
-#include "Charmonizer/Core/Stat.h"
 
 /* Write the "_charm.h" file used by every probe.
  */
@@ -62,7 +61,6 @@ Probe_clean_up(void) {
     /* Dispatch various clean up routines. */
     S_remove_charm_h();
     ConfWriter_clean_up();
-    Stat_clean_up();
     CC_clean_up();
 
     if (Util_verbosity) { printf("Cleanup complete.\n"); }

Modified: incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe/LargeFiles.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe/LargeFiles.c?rev=1151301&r1=1151300&r2=1151301&view=diff
==============================================================================
--- incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe/LargeFiles.c (original)
+++ incubator/lucy/trunk/charmonizer/src/Charmonizer/Probe/LargeFiles.c Wed Jul 27 01:08:56 2011
@@ -19,7 +19,6 @@
 #include "Charmonizer/Core/HeaderChecker.h"
 #include "Charmonizer/Core/Compiler.h"
 #include "Charmonizer/Core/ConfWriter.h"
-#include "Charmonizer/Core/Stat.h"
 #include "Charmonizer/Core/Util.h"
 #include "Charmonizer/Probe/LargeFiles.h"
 #include <errno.h>
@@ -72,22 +71,6 @@ S_probe_lseek(unbuff_combo *combo);
 static chaz_bool_t
 S_probe_pread64(unbuff_combo *combo);
 
-/* Determine whether we can use sparse files.
- */
-static chaz_bool_t
-S_check_sparse_files(void);
-
-/* Helper for check_sparse_files().
- */
-static void
-S_test_sparse_file(long offset, Stat *st);
-
-/* See if trying to write a 5 GB file in a subprocess bombs out.  If it
- * doesn't, then the test suite can safely verify large file support.
- */
-static chaz_bool_t
-S_can_create_big_files(void);
-
 /* Vars for holding lfs commands, once they're discovered. */
 static char fopen_command[10];
 static char fseek_command[10];
@@ -155,16 +138,16 @@ LargeFiles_run(void) {
         }
     }
 
-    /* Check for sparse files. */
-    if (S_check_sparse_files()) {
-        ConfWriter_append_conf("#define CHAZ_HAS_SPARSE_FILES\n");
-        /* See if we can create a 5 GB file without crashing. */
-        if (success && S_can_create_big_files()) {
-            ConfWriter_append_conf("#define CHAZ_CAN_CREATE_BIG_FILES\n");
-        }
+    /* Make checks needed for testing. */
+    const char *stat_includes = "#include <stdio.h>\n#include <sys/stat.h>";
+    if (HeadCheck_check_header("sys/stat.h")) {
+        ConfWriter_append_conf("#define CHAZ_HAS_SYS_STAT_H\n");
     }
-    else {
-        ConfWriter_append_conf("#define CHAZ_NO_SPARSE_FILES\n");
+    if (HeadCheck_contains_member("struct stat", "st_size", stat_includes)) {
+        ConfWriter_append_conf("#define CHAZ_HAS_STAT_ST_SIZE\n");
+    }
+    if (HeadCheck_contains_member("struct stat", "st_blocks", stat_includes)) {
+        ConfWriter_append_conf("#define CHAZ_HAS_STAT_ST_BLOCKS\n");
     }
 
     /* Short names. */
@@ -322,110 +305,3 @@ S_probe_pread64(unbuff_combo *combo) {
     return success;
 }
 
-static chaz_bool_t
-S_check_sparse_files(void) {
-    Stat st_a, st_b;
-
-    /* Bail out if we can't stat() a file. */
-    if (!HeadCheck_check_header("sys/stat.h")) {
-        return false;
-    }
-
-    /* Write and stat a 1 MB file and a 2 MB file, both of them sparse. */
-    S_test_sparse_file(1000000, &st_a);
-    S_test_sparse_file(2000000, &st_b);
-    if (!(st_a.valid && st_b.valid)) {
-        return false;
-    }
-    if (st_a.size != 1000001) {
-        Util_die("Expected size of 1000001 but got %ld", (long)st_a.size);
-    }
-    if (st_b.size != 2000001) {
-        Util_die("Expected size of 2000001 but got %ld", (long)st_b.size);
-    }
-
-    /* See if two files with very different lengths have the same block size. */
-    if (st_a.blocks == st_b.blocks) {
-        return true;
-    }
-    else {
-        return false;
-    }
-}
-
-static void
-S_test_sparse_file(long offset, Stat *st) {
-    FILE *sparse_fh;
-
-    /* Make sure the file's not there, then open. */
-    Util_remove_and_verify("_charm_sparse");
-    if ((sparse_fh = fopen("_charm_sparse", "w+")) == NULL) {
-        Util_die("Couldn't open file '_charm_sparse'");
-    }
-
-    /* Seek fh to [offset], write a byte, close file. */
-    if ((fseek(sparse_fh, offset, SEEK_SET)) == -1) {
-        Util_die("seek failed: %s", strerror(errno));
-    }
-    if ((fprintf(sparse_fh, "X")) != 1) {
-        Util_die("fprintf failed");
-    }
-    if (fclose(sparse_fh)) {
-        Util_die("Error closing file '_charm_sparse': %s", strerror(errno));
-    }
-
-    /* Stat the file. */
-    Stat_stat("_charm_sparse", st);
-
-    remove("_charm_sparse");
-}
-
-/* Open a file, seek to a loc, print a char, and communicate success. */
-static const char create_bigfile_code[] =
-    QUOTE(  #include "_charm.h"                                      )
-    QUOTE(  int main() {                                             )
-    QUOTE(      FILE *fh = fopen("_charm_large_file_test", "w+");    )
-    QUOTE(      int check_seek;                                      )
-    QUOTE(      Charm_Setup;                                         )
-    /* Bail unless seek succeeds. */
-    QUOTE(      check_seek = %s(fh, 5000000000, SEEK_SET);           )
-    QUOTE(      if (check_seek == -1)                                )
-    QUOTE(          exit(1);                                         )
-    /* Bail unless we write successfully. */
-    QUOTE(      if (fprintf(fh, "X") != 1)                           )
-    QUOTE(          exit(1);                                         )
-    QUOTE(      if (fclose(fh))                                      )
-    QUOTE(          exit(1);                                         )
-    /* Communicate success to Charmonizer. */
-    QUOTE(      printf("1");                                         )
-    QUOTE(      return 0;                                            )
-    QUOTE(  }                                                        );
-
-static chaz_bool_t
-S_can_create_big_files(void) {
-    char *output;
-    size_t output_len;
-    FILE *truncating_fh;
-    size_t needed = strlen(create_bigfile_code)
-                    + strlen(fseek_command)
-                    + 10;
-    char *code_buf = (char*)malloc(needed);
-
-    /* Concat the source strings, compile the file, capture output. */
-    sprintf(code_buf, create_bigfile_code, fseek_command);
-    output = CC_capture_output(code_buf, strlen(code_buf), &output_len);
-
-    /* Truncate, just in case the call to remove fails. */
-    truncating_fh = fopen("_charm_large_file_test", "w");
-    if (truncating_fh != NULL) {
-        fclose(truncating_fh);
-    }
-    Util_remove_and_verify("_charm_large_file_test");
-
-    /* Return true if the test app made it to the finish line. */
-    free(code_buf);
-    return output == NULL ? false : true;
-}
-
-
-

Modified: incubator/lucy/trunk/charmonizer/src/Charmonizer/Test/TestLargeFiles.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/charmonizer/src/Charmonizer/Test/TestLargeFiles.c?rev=1151301&r1=1151300&r2=1151301&view=diff
==============================================================================
--- incubator/lucy/trunk/charmonizer/src/Charmonizer/Test/TestLargeFiles.c (original)
+++ incubator/lucy/trunk/charmonizer/src/Charmonizer/Test/TestLargeFiles.c Wed Jul 27 01:08:56 2011
@@ -17,6 +17,8 @@
 #define CHAZ_USE_SHORT_NAMES
 
 #include "charmony.h"
+#include <string.h>
+#include <errno.h>
 
 #ifdef HAS_SYS_TYPES_H
   #include <sys/types.h>
@@ -25,6 +27,31 @@
 #include <stdio.h>
 #include "Charmonizer/Test.h"
 
+#if (defined(HAS_LARGE_FILE_SUPPORT) \
+     && defined(CHAZ_HAS_STAT_ST_SIZE) \
+     && defined(CHAZ_HAS_STAT_ST_BLOCKS))
+#define STAT_TESTS_ENABLED
+
+#include <sys/stat.h>
+
+/* Determine whether we can use sparse files.
+ */
+static chaz_bool_t
+S_check_sparse_files(void);
+
+/* Helper for check_sparse_files().
+ */
+static chaz_bool_t 
+S_test_sparse_file(long offset, struct stat *st);
+
+/* See if trying to write a 5 GB file in a subprocess bombs out.  If it
+ * doesn't, then the test suite can safely verify large file support.
+ */
+static chaz_bool_t
+S_can_create_big_files(void);
+
+#endif /* criteria for defining STAT_TESTS_ENABLED */
+
 static void
 S_run_tests(TestBatch *batch) {
     FILE *fh;
@@ -44,13 +71,20 @@ S_run_tests(TestBatch *batch) {
 #ifndef HAS_LARGE_FILE_SUPPORT
     SKIP_REMAINING(batch, "No large file support");
 #endif
-#ifndef CHAZ_HAS_SPARSE_FILES
-    SKIP_REMAINING(batch,
-                   "Can't verify large file support without sparse files");
-#endif
-#ifndef CHAZ_CAN_CREATE_BIG_FILES
-    SKIP_REMAINING(batch, "Unsafe to create 5GB sparse files on this system");
-#endif
+#ifndef STAT_TESTS_ENABLED
+    SKIP_REMAINING(batch, "Need stat with st_size and st_blocks");
+#else
+    /* Check for sparse files. */
+    if (!S_check_sparse_files()) {
+        SKIP_REMAINING(batch, "Can't verify large file support "
+                       "without sparse files");
+        return;
+    }
+    if (!S_can_create_big_files()) {
+        SKIP_REMAINING(batch, "Unsafe to create 5GB sparse files "
+                       "on this system");
+        return;
+    }
 
     fh = fopen64("_charm_large_file_test", "w+");
     if (fh == NULL) {
@@ -91,8 +125,87 @@ S_run_tests(TestBatch *batch) {
         fclose(fh);
     }
     remove("_charm_large_file_test");
+#endif /* STAT_TESTS_ENABLED */
+}
+
+#ifdef STAT_TESTS_ENABLED
+
+static chaz_bool_t
+S_check_sparse_files(void) {
+    struct stat st_a, st_b;
+
+    /* Write and stat a 1 MB file and a 2 MB file, both of them sparse. */
+    if (!S_test_sparse_file(1000000, &st_a)) { return false; }
+    if (!S_test_sparse_file(2000000, &st_b)) { return false; }
+    if (st_a.st_size != 1000001 || st_b.st_size != 2000001) {
+        return false;
+    }
+
+    /* See if two files with very different lengths have the same block size. */
+    return st_a.st_blocks == st_b.st_blocks ? true : false;
 }
 
+static chaz_bool_t
+S_test_sparse_file(long offset, struct stat *st) {
+    FILE *sparse_fh;
+    chaz_bool_t result = false;
+
+    /* Make sure the file's not there, then open. */
+    remove("_charm_sparse");
+    if ((sparse_fh = fopen("_charm_sparse", "w+")) == NULL) {
+        return false;
+    }
+
+    /* Seek fh to [offset], write a byte, close file. */
+    if ((fseek(sparse_fh, offset, SEEK_SET)) != -1) {
+        if ((fprintf(sparse_fh, "X")) == 1) {
+            result = true;
+        }
+    }
+    if (fclose(sparse_fh)) {
+        result = false;
+    }
+
+    /* Stat the file. */
+    stat("_charm_sparse", st);
+
+    remove("_charm_sparse");
+    return true;
+}
+
+static chaz_bool_t
+S_can_create_big_files(void) {
+    chy_bool_t result = 0;
+    FILE *fh = fopen("_charm_large_file_test", "w+");
+    if (!fh) {
+        return false;
+    }
+    else {
+        /* Bail unless seek succeeds. */
+        int64_t check_seek = fseeko64(fh, I64_C(5000000000), SEEK_SET);
+        if (check_seek != -1) {
+            /* Bail unless we write successfully. */
+            if (fprintf(fh, "X") == 1) {
+                result = true;
+            }
+        }
+        if (fclose(fh)) {
+            result = false;
+        }
+    }
+
+    /* Truncate, just in case the call to remove fails. */
+    fh = fopen("_charm_large_file_test", "w");
+    if (fh != NULL) {
+        fclose(fh);
+    }
+    remove("_charm_large_file_test");
+
+    return result;
+}
+
+#endif /* STAT_TESTS_ENABLED */
+
 int main(int argc, char **argv) {
     TestBatch *batch;